Удаленный термометр
- Войдите на сайт для отправки комментариев
Сб, 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);
если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)
если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)
Не знаю, как реализовано в библиотеке, но на уровне датчика - пока измерение не завершится, прочитать ничего нельзя.
Переделал программу, вроде получилось как надо.