Удаленный термометр

selan61
Offline
Зарегистрирован: 15.12.2017

Здравствуйте. Делаю удаленную передачу температуры 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, &paramA, &valueA);
    temp0 = atof(valueA);
    }
   }
 }
//----------------------------------------------------------- 
void loop(){
     timer.run();
} 
//END--------------------------------------------------------

b707
Offline
Зарегистрирован: 26.05.2017

приемник и его буфер тут совершенно не при чем. Ошибка в том что - вы в вашей процедуре Print_Temp() печатаете температуру, не проверяя. реальные это данные или просто мусор. Можно, например, завести флаг "новые данные" , взводить его при получении , а в процедуре Print_Temp() сначала проверять и печатать только свежие данные.

На самом деле, ошибка в целом в логике программы - в том что у вас получение данных и вывод на экран зачем-то  разнесено по разным функциям и делается отдельно. Для чего вы читаете данные с приемника  раз в секунду, если ывод на экран запускается в 10 раз реже? Сделали бы и то и другое в одном таймере - и проблем бы не было

selan61
Offline
Зарегистрирован: 15.12.2017

Спасибо за ответ. Попробую переделать как Вы советуете. Но проблема в том, что при работе передатчика данные обновляются, а при его отключении, выводятся последние из буфера. Надо, чтобы в этом случае принятые данные обнулялись.

Bruzzer
Offline
Зарегистрирован: 17.03.2020

В коде передатчика вы пишите

48        ds.requestTemperatures();
49         delay(50);                  
50        temp = ds.getTempC(ds0) - 1;

Но для 9-ти бит время преобразования может быть до 93 мс. Сделайте как минимум delay(100);

selan61
Offline
Зарегистрирован: 15.12.2017

Понял. Сделаю.

b707
Offline
Зарегистрирован: 26.05.2017

Bruzzer пишет:

В коде передатчика вы пишите

48        ds.requestTemperatures();
49         delay(50);                  
50        temp = ds.getTempC(ds0) - 1;

Но для 9-ти бит время преобразования может быть до 93 мс. Сделайте как минимум delay(100);

если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)

Bruzzer
Offline
Зарегистрирован: 17.03.2020

b707 пишет:

если времени для преобразования не хватит - ошибки не будет, датчик просто вернет данные прошлого цикла. С учетом программы ТС ничего страшного в этом нет, он даже не заметит :)

Не знаю, как реализовано в библиотеке, но на уровне датчика - пока измерение не завершится, прочитать ничего нельзя.

selan61
Offline
Зарегистрирован: 15.12.2017

Переделал программу, вроде получилось как надо.

/*Приемник температуры 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, &paramA, &valueA);
       temp0 = atof(valueA);
        Serial.print("Temp0: ");
        Serial.println(temp0,1);
       }
    }
    else {
        Serial.println("ERROR"); // ошибка приема
        }  
 }
//----------------------------------------------------------- 
void loop(){
     timer.run();
} 
//END--------------------------------------------------------