Теростат на arduino и NRF24L01

staseshe
Offline
Зарегистрирован: 28.02.2018

Нужна помощь. Понадобилось сделать термометр (термостат) со звуковым оповещением и без проводов, и LED индикатором. Скетчи брал за основу с https://github.com/liamjack/Arduino-NRF24L01-Thermometer, но переделал для led индикатора. Термометр (термостат) заработал на установленную  температуру выводит ALARM на 5й PIN, но выяснилась проблема - при пропадании сигнала с передатчика(DS18B20), приемник продолжает отображать последнее значение на экране. Помогите найти (решить) проблему с кодом. Необходимо срабатывание термостата при пропадании данных с модуля-передатчика.

Вот код моего приемника:

// Radio
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include <RF24_config.h>


// -- Global variables --
//#define OUT 5 // выход для Buzzer

//byte pos;
float tempOUT = 15;
int buttonPlus=A0;
int buzerPin = 5;

// int analog=0;


RF24 radio(9,10);

void setupRadio()
{
 // Initiate the radio
 radio.begin();
 radio.setAutoAck(1);
 // Define the number of retries sending a packet
 radio.setRetries(15,15);
 
 // Define the radio's broadcast channel (0 - 127)
 // Must be the same on the sensor and the master node
 radio.setChannel(17);
 
 // Define the radio's bitrate (using cards lowest bitrate)
 radio.setDataRate(RF24_250KBPS);
 
 // Define the radio's power amplifier level (RF24_PA_MIN for debugging, RF24_PA_HIGH for longest range)
 radio.setPALevel(RF24_PA_HIGH);
 
 // Enable dynamic payloads for packets
 radio.enableDynamicPayloads();
 
 // Open reading pipe
 radio.openReadingPipe(1, 0xE8E8F0F0E1LL);
 
 // Start listening for packets
 radio.startListening();
}
int packetCounter = 0;
int anodPins[] = {2, 3, 4}; // Задаем пины для кажого разряда
int segmentsPins[] = {7, 6, 8, 15, 16, 17, 18, 19}; //Задаем пины для каждого сегмента (из 7 + 1(точка))

int pinIn = A0;

void setup() {
  for (int i = 0; i < 3; i++) pinMode(anodPins[i], OUTPUT);
  for (int i = 0; i < 8; i++) pinMode(segmentsPins[i], OUTPUT);
  pinMode(pinIn, INPUT);
  pinMode(buzerPin, OUTPUT);
   

              // разрешаем прерывание по таймеру
 
  // Initiate serial connection
  Serial.begin(57600);
  
  // RF Radio setup
  setupRadio();

}

//{A, B, C, D, E, F, G,DP}
int seg[12][8] = {
  {1, 1, 1, 1, 1, 1, 0, 0}, //Цифра 0
  {0, 1, 1, 0, 0, 0, 0, 0}, //Цифра 1
  {1, 1, 0, 1, 1, 0, 1, 0}, //Цифра 2
  {1, 1, 1, 1, 0, 0, 1, 0}, //Цифра 3
  {0, 1, 1, 0, 0, 1, 1, 0}, //Цифра 4
  {1, 0, 1, 1, 0, 1, 1, 0}, //Цифра 5
  {1, 0, 1, 1, 1, 1, 1, 0}, //Цифра 6
  {1, 1, 1, 0, 0, 0, 0, 0}, //Цифра 7
  {1, 1, 1, 1, 1, 1, 1, 0}, //Цифра 8
  {1, 1, 1, 1, 0, 1, 1, 0}, //Цифра 9
  {0, 0, 0, 0, 0, 0, 1, 0}, //Знак -
  {0, 0, 0, 0, 0, 0, 0, 0}  //Пустой разряд
};

int err[3][8] = {
  //{0, 0, 0, 0, 0, 0, 0, 0}, //Пусто
  {1, 0, 0, 1, 1, 1, 1, 0}, //E
  {0, 0, 0, 0, 1, 0, 1, 0}, //r
  {0, 0, 0, 0, 1, 0, 1, 0}  //r
};

static int arr[3][8]; // Переменная-массив для хранения данных, которые не нужно каждый раз пересчитывать

float value=0.0;
int counter = -1;
//int numindex = 0;
void loop() 

{
 counter += 1;
if ((counter % 100) == 0) { // Пауза между сменами 100 мс
    counter = 0;
    
   {
if(radio.available()) {
        float temperature = 0;
           // Read the packet received into the temperature variable
   
   if(!radio.available()) {
                  // Read the packet received into the temperature variable
   
  Serial.println("ACK not received by client.");  
      
     }
   
   
   
  if(!radio.read(&temperature, sizeof(float)))   {
      // The sensor did not receive the ACK packet
  // tone(5, 3000,1000);  
 
  Serial.println("ACK not received by client.");  
        
     }
  else  value = temperature;
   getDigits(value);
   Serial.println(temperature);  
      if(tempOUT>temperature) tone(5, 3000,1000);
            
      else digitalWrite(5, LOW);
    }
   
   
 
  
  if (digitalRead(buttonPlus) == LOW) 
  
{ 
    tempOUT-=0.05;
    if (-55 > tempOUT) tempOUT = 0;
    delay(27);
    Serial.println(tempOUT);
    getDigits(tempOUT);
   
  
   
      }   // Делаем проверку, если вход под номером 9 (buttonPlus) имеет состояние  5 В. Увеличиваем значение переменной яркости на 5 единиц.
else if (analogRead(buttonPlus) < 800) 
 { 
    tempOUT+=0.05;
    if (tempOUT > 125) tempOUT = 0;
    delay(27);
        Serial.println(tempOUT);
      getDigits(tempOUT);
    

    
    
  }   // Делаем проверк
  
 }
   
  
  displayMessage(arr);

}
}


void getDigits (float value) {
 // Serial.println(value);
//Serial.println(tempOUT);

  // Выдаем ошибку на те значения, которые не можем показать
  if ((value >= 10000) ||
      (value <= -1000)){
      
     // (value > -0.01 && value < 0.001)
    
    for (int i = 0; i < 3; i++) { // Каждый разряд по очереди
      for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
        arr[i][k] = err[i][k];
      }
    }
    return; // Выходим
  }

  int digits = 3; // У нас 4 разряда
  if (value < 0) digits = 2; // Из-за минуса один символ убирается*/

  // Делим число на 2 группы - отдельно целую часть и дробную.
  int intPart = (int)abs(value);
  int intLength = ((String)intPart).length(); // Смотрим, сколько разрядов занимает целая часть

  // На дробную часть у нас остается разрядов: digits-intLength
  int fracPart = (int)((abs(value) - abs(intPart)) * 10); //  *1000 Мы можем показать максимум 3 знака после запятой - 0,000
  int fracDigits = digits - intLength;

  fracPart = (((String)fracPart).substring(0, fracDigits)).toInt();

  // Собираем строку для отображения
  String output = (value < 0) ? "-" : "";
  output += (String)intPart;
   String outputFrac = (digits - intLength < 0) ? "" : ((String)"." + ((String)fracPart).substring(0, digits - intLength));
  //String outputFrac = ((digits - intLength <= 0) || (fracPart == 0)) ? "" : ((String)"." + ((String)fracPart).substring(0, digits - intLength));
  output += (String)outputFrac;

   // Дополняем символы спереди, если цифр слишком мало, например для "-1" делаем "  -1"
  String spaces = "     ";
  digits = 3;
  if (~output.indexOf(".")) digits += 1;
  if (output.length() < digits) output = spaces.substring(0, digits - output.length()) + output;

  // Формирум данные для показа:
  int dig = -1;
  for (int i = 0; i < output.length(); i++) {
    String _char = output.substring(i, i + 1);

    if (_char != ".") dig += 1; // Точка не занимает сегмент - увеличиваем на 1

    int actualdigit = 11; // По умолчанию пустой символ
    if ((_char == "-")) {
      actualdigit = 10;
    }
    else if (_char == " " || _char == ".") {
    }
    else {
      actualdigit = _char.toInt();
    }

    if (_char == ".") {
      arr[dig][7] = 1; // Если нужно - ставим точку
    }
    else  {
      for (int n = 0; n <= 7; n++) {
        arr[dig][n] = seg[actualdigit][n];
      }
    }
  }
}

void displayMessage(int dig[3][8]) {
  for (int i = 0; i < 3; i++) { // Каждый разряд по очереди
    for (int k = 0; k < 8; k++) {// Каждый сегмент по очереди - исходя из заданной карты
      digitalWrite(segmentsPins[k], ((dig[i][k] == 1) ? LOW : HIGH));
    }
    digitalWrite(anodPins[i], HIGH);
    delay(1);
    digitalWrite(anodPins[i], LOW);
      }
    }
vvadim
Offline
Зарегистрирован: 23.05.2012

заведите таймер.

если по прошедствии  интервала нет сигнала - тревога, если есть - обнуляете таймер.

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

выражайтесь яснее - что должно происходить при пропадании связи с датчиком? - по-моему, показывать последнюю принятую температуру - один из логичных вариантов.

И еще - посмотрел код - что-то термостата в нем вообще не видно, один вывод на экран. Вам бы следовало сделать наоборот - сначала отладить важное (термостат), а уж потом рюшечками (лед-экран) заниматься.

staseshe
Offline
Зарегистрирован: 28.02.2018

Спасибо за быстрый ответ.

вот тут у меня и есть "термостат":

140   else  value = temperature;
141    getDigits(value);
142    Serial.println(temperature); 
143       if(tempOUT>temperature) tone(5, 3000,1000);
144             
145       else digitalWrite(5, LOW);
146     }

Показывать последнюю температуру логично и может быть правильно, но для меня критично именно отсутсвие новых значений. При пропадании данных с передатчика  (пропало электричество),  я не контролирую текущую температуру. Датчик установлен на улице и если например там мороз, а у меня еще +15 на экране  и звуковой сигнализации нет соответсвенно. Требуется именно онлайн мониторинг. Это своего рода будильник, а не термостат. На 5 выводе звуковая сигнализация. Я так понимаю необходимо внести изменения в эту часть

void loop()
{ 
  // Check if the radio has received any data
  if(radio.available()) {
    float temperature = 0;
    
    // Read the packet received into the temperature variable
    if(!radio.read(&temperature, sizeof(float))) {
      // The sensor did not receive the ACK packet
      Serial.println("ACK not received by client.");
    }