Аналог беспроводного датчика температуры домашних метеостанций работающих от батарейного питания, используется китайский микроконтроллер LGT8F328P в среде Arduino.
Версия с LGT8F328P и LM75A:
Схема подключения:

- Приемник LR43B подключается к выход D2 Arduino или LGT8F328P.

- Передатчик SYN115 подключается к выход D10 Arduino или LGT8F328P.
- LM75A подключается к I2C интерфейсу, SDA и SCL микросхемы к A4 и A5 соответственно, входы нужно подтянуть резисторами на 10к к питанию, выходы A0, A1 и A2, (выбор адреса на шине) соединяются с массой.
- Питание подключается на вход 5V микроконтроллера, никакое другое питание в этот момент, подключено быть не должно.
Код:
Пример для приемника, одинаков для всех вариантов передатчиков и должен работать без изменений. Перевод в градусы цельсия взят из примера работы с LM75 (без А), перевод 9 битный, вне зависимо от разрешения передатчика, шаг отображаемой температуры будет 0,5, это исправимо, но пока так.
// receiver.pde
//
// Simple example of how to use VirtualWire to receive messages
// Implements a simplex (one-way) receiver with an Rx-B1 module
//
// See VirtualWire.h for detailed API docs
// Author: Mike McCauley (mikem@airspayce.com)
// Copyright (C) 2008 Mike McCauley
// $Id: receiver.pde,v 1.3 2009/03/30 00:07:24 mikem Exp $
#include <VirtualWire.h>
/// медленный, экономный память способ
uint8_t crc8(const uint8_t *addr, uint8_t len) {
uint8_t crc = 0;
while (len--) {
uint8_t inbyte = *addr++;
for (uint8_t i = 8; i; i--) {
uint8_t mix = (crc ^ inbyte) & 0x01;
crc >>= 1;
if (mix) crc ^= 0x8C;
inbyte >>= 1;
}
}
return crc;
}
//// This table comes from Dallas sample code where it is freely reusable,
//// though Copyright (C) 2000 Dallas Semiconductor Corporation
//static const uint8_t PROGMEM dscrc_table[] = {
// 0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
// 157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
// 35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
// 190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
// 70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
// 219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
// 101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
// 248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
// 140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
// 17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
// 175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
// 50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
// 202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
// 87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
// 233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
// 116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
////
//// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
//// and the registers. (note: this might better be done without to
//// table, it would probably be smaller and certainly fast enough
//// compared to all those delayMicrosecond() calls. But I got
//// confused, so I use this table from the examples.)
////
//uint8_t crc8(const uint8_t *addr, uint8_t len) {
// uint8_t crc = 0;
// while (len--) {
// crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
// }
// return crc;
//}
void setup()
{
Serial.begin(9600); // Debugging only
Serial.println("setup");
vw_set_rx_pin(2);
vw_setup(1024); // Bits per sec
vw_rx_start(); // Start the receiver PLL running
}
void loop()
{
uint8_t msb, lsb = 0;
float Grad;
uint8_t buf[VW_MAX_MESSAGE_LEN];
uint8_t buflen = VW_MAX_MESSAGE_LEN;
if (vw_get_message(buf, &buflen)) // Non-blocking
{
digitalWrite(13, true); // Flash a light to show received good message
// Message with a good checksum received, dump it.
Serial.print("Got: ");
for (int i = 0; i < buflen; i++) {
Serial.print(buf[i], HEX);
Serial.print(" ");
}
Serial.println("");
digitalWrite(13, false);
//// температура
msb = buf[1];
lsb = buf[2];
if (msb < 0x80) {
Grad = ((msb * 10) + (((lsb & 0x80) >> 7) * 5));
}
else {
Grad = ((msb * 10) + (((lsb & 0x80) >> 7) * 5));
Grad = (2555.0 - Grad);
}
Grad = Grad / 10;
Serial.print("ID: ");
Serial.println( buf[0]);
Serial.print("Temp: ");
Serial.println(Grad);
Serial.print("crc: ");
Serial.print (buf[3]);
Serial.print(" = ");
Serial.println(crc8((uint8_t*)&buf, buflen - 1));
Serial.println("");
}
}
#include <Wire.h>
#include <PMU.h>
#include <VirtualWire.h>
#define LM75_ADDRESS 0x48
#define LM75_TEMP_REGISTER 0
#define LM75_CONF_REGISTER 1
#define LM75_CONF_SHUTDOWN 0
#define TXPIN 10 // нога OOK радиомодуля
#define LED 13 // светодиод на плате, мигает при передачи
#define SETIDPIN 7 // перемычка выбор id
uint8_t ID = 0;
uint8_t oldmsb = 0;
uint8_t Send[4];
// This table comes from Dallas sample code where it is freely reusable,
// though Copyright (C) 2000 Dallas Semiconductor Corporation
static const uint8_t PROGMEM dscrc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
//
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
// and the registers. (note: this might better be done without to
// table, it would probably be smaller and certainly fast enough
// compared to all those delayMicrosecond() calls. But I got
// confused, so I use this table from the examples.)
//
uint8_t crc8(const uint8_t *addr, uint8_t len) {
uint8_t crc = 0;
while (len--) {
crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
}
return crc;
}
void shutDownLM75(boolean val) { /// 1 выкл, 0 вкл
Wire.beginTransmission(LM75_ADDRESS);
Wire.write(LM75_CONF_REGISTER);
Wire.write(val << LM75_CONF_SHUTDOWN);
Wire.endTransmission();
}
void setup()
{
Wire.begin();
vw_set_tx_pin(TXPIN);
vw_set_ptt_inverted(false); // false! иначе передатчик останется включенным
vw_setup(1024); // Bits per sec
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(SETIDPIN, INPUT_PULLUP); // читаем состояние ноги
ID = digitalRead(SETIDPIN);
pinMode(SETIDPIN, INPUT); // исключаем подтягивающий резистор
}
void loop(){
shutDownLM75(0); // включаем термометр
PMU.sleep(PM_POFFS0, SLEEP_256MS); // ждем пока он очухается (можно SLEEP_128MS)
// читаем регистры LM75
uint8_t msb, lsb = 0;
Wire.beginTransmission(LM75_ADDRESS);
Wire.write(LM75_TEMP_REGISTER);
Wire.endTransmission(LM75_ADDRESS);
Wire.requestFrom(LM75_ADDRESS, 2);
// while(Wire.available() < 2); /// тут может все поламаться
msb = Wire.read();
lsb = Wire.read();
// если температура изменилась
if (oldmsb != msb) { // смотрим в старший бит
oldmsb = msb; // сохраняем для следующей проверки
// заполняем массив
Send[0] = ID;
Send[1] = msb;
Send[2] = lsb;
Send[3] = crc8((uint8_t*)&Send, sizeof(Send) - 1);
// отправляем
digitalWrite(LED, HIGH);
vw_send((uint8_t *)Send, sizeof(Send));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(LED, LOW);
shutDownLM75(1); // выключаем градусник
// PMU.sleep(PM_POWERDOWN, SLEEP_1S);
PMU.sleep(PM_POWERDOWN, SLEEP_32S); // вообще все выключаем на 32 сек
}
else { /// иначе спим дальше
shutDownLM75(1); // выключаем градусник
// PMU.sleep(PM_POWERDOWN, SLEEP_1S);
PMU.sleep(PM_POWERDOWN, SLEEP_32S);
}
// if (msb < 0x80)
// {
// Grad = ((msb * 10) + (((lsb & 0x80) >> 7) * 5));
// }
// else
// {
// Grad = ((msb * 10) + (((lsb & 0x80) >> 7) * 5));
// Grad = (2555.0 - Grad);
// }
//
// Grad = Grad / 10;
}
Видео:
Версия датчика с LGT8F328P и TMP100 \ TMP102:
TMP100 \ TMP102 схожие по характеристикам термодатчики с низким энергопотреблением, имеют аналогичные LM75A регистры с температурой и могут его заменить без особых изменений в коде. Датчики TMP100 и TMP102 имеют одинаковые регистры, код передатчика ниже работает с обоими без изменений, описание датчиков на странице тут и тут. TMP102 имеет корпус SOT563 сложный для ручного монтажа, но доступен в виде модуля, у TMP100 более привычный корпус SOT23-6.
////// датчик температуры с OOK радиомодулем и батарейным питанием
///// TMP100 и 8F328P
#include <Wire.h>
#include <PMU.h>
#include <VirtualWire.h>
#define TMP100_ADDRESS 0x48
#define TMP100_TEMP_REGISTER 0
#define TMP100_CONF_REGISTER 1
#define TMP100_SETRESOLUTION 10 // 9 - 12 bit
#define TXPIN 10 // нога OOK радиомодуля
#define LED 13 // светодиод на плате, мигает при передачи
#define SETIDPIN 7 // перемычка выбор id
uint8_t ID = 0;
uint8_t oldmsb = 0;
uint8_t Send[4];
// This table comes from Dallas sample code where it is freely reusable,
// though Copyright (C) 2000 Dallas Semiconductor Corporation
static const uint8_t PROGMEM dscrc_table[] = {
0, 94,188,226, 97, 63,221,131,194,156,126, 32,163,253, 31, 65,
157,195, 33,127,252,162, 64, 30, 95, 1,227,189, 62, 96,130,220,
35,125,159,193, 66, 28,254,160,225,191, 93, 3,128,222, 60, 98,
190,224, 2, 92,223,129, 99, 61,124, 34,192,158, 29, 67,161,255,
70, 24,250,164, 39,121,155,197,132,218, 56,102,229,187, 89, 7,
219,133,103, 57,186,228, 6, 88, 25, 71,165,251,120, 38,196,154,
101, 59,217,135, 4, 90,184,230,167,249, 27, 69,198,152,122, 36,
248,166, 68, 26,153,199, 37,123, 58,100,134,216, 91, 5,231,185,
140,210, 48,110,237,179, 81, 15, 78, 16,242,172, 47,113,147,205,
17, 79,173,243,112, 46,204,146,211,141,111, 49,178,236, 14, 80,
175,241, 19, 77,206,144,114, 44,109, 51,209,143, 12, 82,176,238,
50,108,142,208, 83, 13,239,177,240,174, 76, 18,145,207, 45,115,
202,148,118, 40,171,245, 23, 73, 8, 86,180,234,105, 55,213,139,
87, 9,235,181, 54,104,138,212,149,203, 41,119,244,170, 72, 22,
233,183, 85, 11,136,214, 52,106, 43,117,151,201, 74, 20,246,168,
116, 42,200,150, 21, 75,169,247,182,232, 10, 84,215,137,107, 53};
//
// Compute a Dallas Semiconductor 8 bit CRC. These show up in the ROM
// and the registers. (note: this might better be done without to
// table, it would probably be smaller and certainly fast enough
// compared to all those delayMicrosecond() calls. But I got
// confused, so I use this table from the examples.)
//
uint8_t crc8(const uint8_t *addr, uint8_t len) {
uint8_t crc = 0;
while (len--) {
crc = pgm_read_byte(dscrc_table + (crc ^ *addr++));
}
return crc;
}
void shutDownTMP100(boolean val) { /// 1 выкл, 0 вкл
Wire.beginTransmission(TMP100_ADDRESS);
Wire.write(TMP100_CONF_REGISTER);
Wire.write((TMP100_SETRESOLUTION - 9) << 5 | val);
Wire.endTransmission();
}
void setup()
{
// Serial.begin(9600);
Wire.begin();
vw_set_tx_pin(TXPIN);
vw_set_ptt_inverted(false); // false! иначе передатчик останется включенным
vw_setup(1024); // Bits per sec
pinMode(LED, OUTPUT);
digitalWrite(LED, LOW);
pinMode(SETIDPIN, INPUT_PULLUP); // читаем состояние ноги
ID = digitalRead(SETIDPIN);
pinMode(SETIDPIN, INPUT); // исключаем подтягивающий резистор
}
void loop(){
shutDownTMP100(0); // включаем термометр
PMU.sleep(PM_POFFS0, SLEEP_256MS); // ждем пока он очухается (можно SLEEP_128MS)
// читаем регистры
uint8_t msb, lsb = 0;
Wire.beginTransmission(TMP100_ADDRESS );
Wire.write(TMP100_TEMP_REGISTER);
Wire.endTransmission(TMP100_ADDRESS);
Wire.requestFrom(TMP100_ADDRESS, 2);
// while(Wire.available() < 2); /// тут может все поламаться
msb = Wire.read();
lsb = Wire.read();
// если температура изменилась
if (oldmsb != msb) { // смотрим в старший бит
oldmsb = msb; // сохраняем для следующей проверки
// заполняем массив
Send[0] = ID;
Send[1] = msb;
Send[2] = lsb;
Send[3] = crc8((uint8_t*)&Send, sizeof(Send) - 1);
// отправляем
digitalWrite(LED, HIGH);
vw_send((uint8_t *)Send, sizeof(Send));
vw_wait_tx(); // Wait until the whole message is gone
digitalWrite(LED, LOW);
shutDownTMP100(1); // выключаем градусник
// PMU.sleep(PM_POWERDOWN, SLEEP_1S);
PMU.sleep(PM_POWERDOWN, SLEEP_32S); // вообще все выключаем на 32 сек
}
else { /// иначе спим дальше
shutDownTMP100(1); // выключаем градусник
// PMU.sleep(PM_POWERDOWN, SLEEP_1S);
PMU.sleep(PM_POWERDOWN, SLEEP_32S);
}
// float Grad;
// int TemperatureSum = ((msb << 8) | lsb) >> 4;
//
// Serial.println(TemperatureSum*0.0625);
// //delay(1000);
}
