Теростат на arduino и NRF24L01
- Войдите на сайт для отправки комментариев
Пнд, 05/03/2018 - 12:17
Нужна помощь. Понадобилось сделать термометр (термостат) со звуковым оповещением и без проводов, и 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);
}
}
заведите таймер.
если по прошедствии интервала нет сигнала - тревога, если есть - обнуляете таймер.
выражайтесь яснее - что должно происходить при пропадании связи с датчиком? - по-моему, показывать последнюю принятую температуру - один из логичных вариантов.
И еще - посмотрел код - что-то термостата в нем вообще не видно, один вывод на экран. Вам бы следовало сделать наоборот - сначала отладить важное (термостат), а уж потом рюшечками (лед-экран) заниматься.
Спасибо за быстрый ответ.
вот тут у меня и есть "термостат":
140elsevalue = temperature;141getDigits(value);142Serial.println(temperature);143if(tempOUT>temperature) tone(5, 3000,1000);144145elsedigitalWrite(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."); }