Удаленный термометр
- Войдите на сайт для отправки комментариев
Сб, 18/04/2020 - 12:33
Здравствуйте. Делаю удаленную передачу температуры DS18B20 через передатчик\приемник 433МГц. Все прекрасно работает. Но после отключения передатчика, приемник выдает последние показания, которые в буфере остались. Не подскажите как очищать буфер приемника, перед приемом новых показаний.
Код передатчика
/*Передатчик температуры DS18B20 по 433МГц
* с использованием SimpleTimer
*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <VirtualWire.h>
#include <SimpleTimer.h>
//-----------------------------------------------------------
#define ONE_WIRE_BUS 2 // DS18B20 Pin
#define TEMPERATURE_PRECISION 9 // точность измерения DS18B20
#define timer1_Interval 5000 // время (5*1000) милисекунд многократно выполнять функцию Measure()
#define timer2_Interval 10000 // время (10*1000) милисекунд многократно выполнять функцию Send()
//-----------------------------------------------------------
float temp; // текущая температура DS18B20
unsigned int timer1, timer2; // номера таймеров
//-----------------------------------------------------------
SimpleTimer timer;
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature ds(&oneWire);
DeviceAddress ds0;
//-----------------------------------------------------------
void setup(){
//настройка virtualWire
vw_set_tx_pin(12);//пин передачи
vw_set_rx_pin(11);//пин приема
vw_set_ptt_inverted(true);
vw_setup(2000);//скорость передачи данных(бит/с)
Serial.begin(9600);
// инициируем датчик
ds.begin(); // start up the library DallasTemperature
delay(50);
// достаем адрес датчика с индесом 0
if (!ds.getAddress(ds0, 0)) Serial.println("Unable to find address for Device 0");
// устанавливаем разрешение 9 bit
ds.setResolution(ds0, TEMPERATURE_PRECISION);
// запускаем таймеры
timer1 = timer.setInterval (timer1_Interval, Measure); // каждые timer1_Interval выполнять функцию Measure()
timer2 = timer.setInterval (timer2_Interval, Send); //каждые timer2_Interval выполнять функцию Send()
}
//-----------------------------------------------------------
void Measure() {
// считываем температуру с датчика
ds.requestTemperatures();
delay(50);
temp = ds.getTempC(ds0) - 1;
// отправляем serial
Serial.print("Temperature DS18B20: ");
Serial.print(temp);
Serial.println(" C");
}
//-----------------------------------------------------------
void Send(){
// формирование данных для для отправки
char msg[255];
String strMsg = "X";
strMsg = strMsg + ",";
strMsg = strMsg + "A";
strMsg = strMsg + ",";
strMsg = strMsg + temp;
strMsg.toCharArray(msg,100);
Serial.print("Send ");
Serial.println(msg);
vw_send((uint8_t*)msg, strlen(msg));
vw_wait_tx(); // Ждем пока передача будет окончена
}
//-----------------------------------------------------------
void loop(){
timer.run();
}
//END--------------------------------------------------------
Код приемника:
/*Приемник температуры DS18B20 по 433МГц
* с использованием SimpleTimer
*/
#include <VirtualWire.h>
#include <SimpleTimer.h>
//-----------------------------------------------------------
#define timer1_Interval 1000 // время (1000) милисекунд многократно выполнять функцию Receiver()
#define timer2_Interval 10000 // время (10*1000) милисекунд многократно выполнять функцию Print_Temp()
//-----------------------------------------------------------
uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения
uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера
long lastdisplayTime = 0; // время последнего отображения данных
const int transmit_pin = 12;
const int receive_pin = 11;
char data[100];
char mode[2];
char paramA[2];
char valueA[6];
float temp0; //AX
unsigned int timer1, timer2; // номера таймеров
//-----------------------------------------------------------
SimpleTimer timer;
//-----------------------------------------------------------
void setup() {
Serial.begin(9600);
vw_set_tx_pin(transmit_pin);
vw_set_rx_pin(receive_pin);
vw_set_ptt_inverted(true);
vw_setup(2000);
vw_rx_start(); // Начинаем мониторинг эфира
// запускаем таймеры
timer1 = timer.setInterval (timer1_Interval, Receiver); // каждые timer1_Interval выполнять функцию Receiver()
timer2 = timer.setInterval (timer2_Interval, Print_Temp); //каждые timer2_Interval выполнять функцию Print_Temp()
}
//-----------------------------------------------------------
void Print_Temp(){
Serial.print("Temp0: ");
Serial.println(temp0,1);
}
//-----------------------------------------------------------
void Receiver(){
if (vw_get_message(buf, &buflen)){ // Если принято сообщение
if (buf[0] == 'X'){ // Если сообщение X
strcpy(data,buf);
sscanf(data, "%[^','],%[^','],%s",
&mode, ¶mA, &valueA);
temp0 = atof(valueA);
}
}
}
//-----------------------------------------------------------
void loop(){
timer.run();
}
//END--------------------------------------------------------
приемник и его буфер тут совершенно не при чем. Ошибка в том что - вы в вашей процедуре Print_Temp() печатаете температуру, не проверяя. реальные это данные или просто мусор. Можно, например, завести флаг "новые данные" , взводить его при получении , а в процедуре Print_Temp() сначала проверять и печатать только свежие данные.
На самом деле, ошибка в целом в логике программы - в том что у вас получение данных и вывод на экран зачем-то разнесено по разным функциям и делается отдельно. Для чего вы читаете данные с приемника раз в секунду, если ывод на экран запускается в 10 раз реже? Сделали бы и то и другое в одном таймере - и проблем бы не было
Спасибо за ответ. Попробую переделать как Вы советуете. Но проблема в том, что при работе передатчика данные обновляются, а при его отключении, выводятся последние из буфера. Надо, чтобы в этом случае принятые данные обнулялись.
В коде передатчика вы пишите
48 ds.requestTemperatures();
49 delay(50);
50 temp = ds.getTempC(ds0) - 1;
Но для 9-ти бит время преобразования может быть до 93 мс. Сделайте как минимум delay(100);
Понял. Сделаю.
В коде передатчика вы пишите
48 ds.requestTemperatures();
49 delay(50);
50 temp = ds.getTempC(ds0) - 1;
Но для 9-ти бит время преобразования может быть до 93 мс. Сделайте как минимум delay(100);
если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)
если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)
Не знаю, как реализовано в библиотеке, но на уровне датчика - пока измерение не завершится, прочитать ничего нельзя.
Переделал программу, вроде получилось как надо.
/*Приемник температуры DS18B20 по 433МГц * с использованием SimpleTimer * V2-убрал timer2 и функцию Print_Temp() * V2_1-вставил Serial.println("ERROR") */ #include <VirtualWire.h> #include <SimpleTimer.h> //----------------------------------------------------------- #define timer1_Interval 5000 // время (5*1000) милисекунд многократно выполнять функцию Measure() //----------------------------------------------------------- uint8_t buf[VW_MAX_MESSAGE_LEN]; // Буфер для сообщения uint8_t buflen = VW_MAX_MESSAGE_LEN; // Длина буфера long lastdisplayTime = 0; // время последнего отображения данных const int transmit_pin = 12; const int receive_pin = 11; char data[100]; char mode[2]; char paramA[2]; char valueA[6]; float temp0; //AX unsigned int timer1; // номера таймеров bool NEW_MESSAGE = false; // если NEW_MESSAGE ON - true //----------------------------------------------------------- SimpleTimer timer; //----------------------------------------------------------- void setup() { Serial.begin(9600); vw_set_tx_pin(transmit_pin); vw_set_rx_pin(receive_pin); vw_set_ptt_inverted(true); vw_setup(2000); vw_rx_start(); // Начинаем мониторинг эфира // запускаем таймеры timer1 = timer.setInterval (timer1_Interval, Receiver); // каждые timer1_Interval выполнять функцию Receiver() } //----------------------------------------------------------- void Receiver(){ if (vw_get_message(buf, &buflen)){ // Если принято сообщение if (buf[0] == 'X'){ // Если сообщение X strcpy(data,buf); sscanf(data, "%[^','],%[^','],%s",&mode, ¶mA, &valueA); temp0 = atof(valueA); Serial.print("Temp0: "); Serial.println(temp0,1); } } else { Serial.println("ERROR"); // ошибка приема } } //----------------------------------------------------------- void loop(){ timer.run(); } //END--------------------------------------------------------