термореле для холодильника ds18b20+oled+nano
- Войдите на сайт для отправки комментариев
Всем привет форумчане! Делаю потихоньку для своего холодильника термореле, т.к. оно скончалось, поискав нельколько проектов нашел у человека один подходящий и на его основе сделал под себя, поменял дисплей на oled 128*32 i2c(то что есть в наличии), и добавил меню для настройки некоторых параметров работы реле по заданной температуре(тоже взято у человека с этого форума), все это делается еще некоторых идей которые получат реализацию чуть позже, сейчас с этим бы разобраться. Столкнулся для меня не понятной ситуацией, являюсь новичком в программирование, суть в чем, при подключенном датчике температуры ds18b20, начинает тормозить окпрос кнопок ну и соотвественно вывод на экран. Как только его отключаю, сразу все летает, опрос кнопок работает как надо. Но при подключеном датчика температуры , все выводится корректно и быстро, временные задежки работают корректно. Пересмотрел подключение темп.датчика, но для себя не выявил каких либо ощибок, на этом мои познания заканчиваются. помогите оптимизировать код без тормозов при подключенном датчике температуры. и опросе кнопок.
#include <Wire.h> #include <Adafruit_GFX.h> #include <Adafruit_SSD1306.h> #include <OneWire.h> #include <DallasTemperature.h> #define OLED_RESET 4 Adafruit_SSD1306 display(OLED_RESET); double f_tempC; // Текущая температура double t_min,t_max; // переменне для установки макс.и мин. тепературы unsigned long ul_offTime; // Время отключения компрессора unsigned long ul_workTime; // Время включения компрессора unsigned long ul_newTime; // Текущее время unsigned long ul_deltaTime; // Разница времени //unsigned long ul_actHeartLedTime; // Время светодиода активности //boolean b_actLedOn; // Светодиод активности включён boolean b_compressorOff; // Компрессор выключен boolean t_ok; // флаг исправности датчика температуры для вывода на oled ошибки // Температура включения компрессора #define TEMPERATURE_MAX t_max // Температура отключения компрессора #define TEMPERATURE_MIN t_min // Пауза перед включением компрессора (600000 = 10 минут) #define DELAY_COMPRESSOR 600000 // Максимальное время работы компрессора (3600000 = 1 час) #define MAXTIME_COMPRESSOR 1200000 // Реле подключено к 3 пину #define RELE 3 // Датчик температуры подключён к 2 пину #define ONE_WIRE_BUS 2 // Светодиод активности подключён к 13 пину //#define LED_ACTIVITY 13 // Свечение светодиода активности в мс //#define LED_ACTIVITY_ON 50 // Пауза светодиода активности в мс //#define LED_ACTIVITY_OFF 3950 // Светодиод ошибки датчика температуры подключён к 12 пину //#define LED_ERROR 12 // Время работы компрессора при ошибке датчика температуры (1200000 = 20 минут) #define ERROR_COMPRESSOR_ON 1200000 // Время паузы компрессора при ошибке датчика температуры (2400000 = 40 минут) #define ERROR_COMPRESSOR_OFF 2400000 OneWire oneWire(ONE_WIRE_BUS); DallasTemperature sensors(&oneWire); //массив надписей которые выводяться не на одном экране для экономии памяти char* myLabel[]={//повторяющиеся надписи "Parametr","P1=","P2=","P3="}; int tt; int m=0; //переменная для экранов меню int p1=0; // переменная для примера 1 int p2=0; // переменная для примера 2 boolean p3=0; // переменная для примера 3 unsigned long PSTimer = 0;//таймер для обновления экрана unsigned long KPTimer = 0;//таймер для опроса кнопок unsigned long MSRTimer = 0;//таймер для автовозврата к MainScreen #define MSRecovery 10000 //задержка автовозврата к MainScreen 10сек #define nextPin 12 //кнопка "SET" на 12 входе #define upPin 11 //кнопка "+" #define downPin 10 //кнопка "-" boolean f_key=0;//флаг для фиксации нажатия кнопки #define bounce 100 //задержка антидребезга #define ledPin 13 //Светодиод #define eventLenght 10//длина очереди событий byte eventList[eventLenght+1];//инициализация очереди событий + 1 пустое // |состояния| события | на пересечении действие // |---------+-+----+---+---+---+---+---| // | v |0| 1 | 2 | 3 | 4 | 5 | 6 | -расшифровка событий- // | | |SET | + | - | | | | 0-нет действий // |---------+-+----+---+---+---+---+---| 1-кнопка SET // | 0 m=0|0|m++ | 0 | 0 |PS | 0 |gk | 2-кнопка + // | 1 m=1|0|m++ |p1+|p1-|PS |m0 |gk | 3-кнопка - // | 2 m=2|0|m++ |p2+|p2-|PS |m0 |gk | 4-таймер обновления экрана // | 3 m=3|0|m++ |p3+|p3-|PS |m0 |gk | 5-таймер возврата к основному экрану // |---------+-+----+---+---+---+---+---| 6-таймер опроса кнопок //коды действий #define m_up 1// цифра - адрес команды в функции run(event) #define p1_up 3 #define p1_dn 4 #define p2_up 5 #define p2_dn 6 #define led_on 7 #define led_off 8 #define PS 9 #define m0 10 #define gk 11 byte automat[4][7] = { { 0, m_up, 0, 0, PS, 0, gk } ,{ 0, m_up, p1_up, p1_dn, PS, m0, gk } ,{ 0, m_up, p2_up, p2_dn, PS, m0, gk } ,{ 0, m_up, led_on, led_off, PS, m0, gk } }; void setup() { // by default, we'll generate the high voltage from the 3.3v line internally! (neat!) display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3C (for the 128x32) // init done display.display(); display.clearDisplay(); //Настройка входов pinMode(nextPin, INPUT); pinMode(upPin, INPUT); pinMode(downPin, INPUT); //Настройка выходов pinMode(ledPin, OUTPUT); pinMode(RELE, OUTPUT); digitalWrite(RELE, LOW); // При загрузке компрессор отключён b_compressorOff = true; sensors.begin(); ul_offTime = millis(); // Запоминаем время начала работы программы //ul_actHeartLedTime = ul_offTime; } // Функция вычисления разницы времени, в том числе и при длительной // непрерывной работе более 49 суток unsigned long deltamills(unsigned long t_old, unsigned long t_new) { unsigned long delta; if ( t_old <= t_new ) { delta = t_new - t_old; } else { delta = (4294967295 - t_old) + t_new; } return delta; } //--------------функция изменения переменной------------------- //х=var(переменная,минимум,максимум,шаг,циклически); int var(int v, int mn, int mx, int stp, boolean c){ v+=stp; switch (c){//c-1 циклически с-0 до пределов case 1:// if (v<mn){ v=mx; } if (v>mx){ v=mn; } break; case 0: if (v<mn){ v=mn; } if (v>mx){ v=mx; } break; } return v; } //-------------ОПРОС КНОПОК------------ void getKey(){ KPTimer=millis()+bounce;//сброс таймера switch (f_key){ case 0: key_dn();//получаем события кнопок if (f_key==true){//если кнопка была нажата MSRTimer=millis();//сброс таймера автовозврата к главному экрану } break; case 1: key_up();//проверка отпускания кнопки break; } } //--------------ПРОВВЕРКА НАЖАТИЯ------------ void key_dn(){ //Обработка нажатия кнопки NEXT if (digitalRead(nextPin)== HIGH) { f_key=true;//устанавливаем флаг cludEvent(1);//сохраняем в очередь код события } //Обработка нажатия UP if (digitalRead(upPin)== HIGH)//если находимся на экране с переменной р1 { f_key=true;//устанавливаем флаг cludEvent(2);//сохраняем в очередь код события } //Обработка нажатия DN if (digitalRead(downPin)== HIGH)//если находимся на экране с переменной р1 { f_key=true;//устанавливаем флаг cludEvent(3);//сохраняем в очередь код события } } //проверка отпускания кнопки void key_up(){ if (digitalRead(nextPin)==0 && digitalRead(upPin)==0 && digitalRead(downPin)==0){ f_key=false;//сброс флага } } //---------ФУНКЦИИ ОЧЕРЕДИ СОБЫТИЙ------------- //положить задание void cludEvent(byte e){ if(eventList[0] !=0){//чтобы не потерять задание в очереди run(automat[m][getEvent()]);//выполнение действия из таблицы переходов } pushEvent();//сдвигаем очередь eventList[eventLenght-1]=e;//положить задание в очередь } //взять задание byte getEvent(){ return eventList[0]; } //сдвинуть очередь void pushEvent(){ for (int i=0; i <= eventLenght-1; i++){ eventList[i]=eventList[i+1]; } } //количество заданий в очереди byte getEventLenght(){ byte el=0; for (int i=0; i <= eventLenght-1; i++){ //для отладки //lcd.setCursor(5+i, 0);//выводит на дисплей очередь //lcd.print(eventList[i]); if(eventList[i] != 0){//подсчет заданий в очереди el++; } } return el;//возвращает кол-во заданий в очереди } //выполнить действие согласно таблице переходов //где переменная = var(переменная,минимум,максимум,шаг,циклически) void run(int f){ switch (f){ case 0: break; case 1: m=var(m, 0, 3, 1, 1);//увеличиваем переменную уровня меню break; case 3: p1= var(p1, -5, 10, 1, 1);//то при нажатии кнопки + увеличиваем переменную р1 на единицу break; case 4: p1= var(p1,-5, 10, -1, 1);//то при нажатии кнопки - уменьшаем переменную р1 на единицу break; case 5: p2= var(p2, -5, 10, -1, 1); break; case 6: p2= var(p2, -5, 10, -1, 1); break; case 7: p3= var(p3, 0, 1, 1, 0); break; case 8: p3= var(p3, 0, 1, -1, 0); break; case 9: PreentScreen(m);//обновление экрана break; case 10: m=0; break; case 11: getKey(); break; } } //--------Вывод экранов---------------------- void PreentScreen(int s){ display.clearDisplay(); display.setTextSize(1); display.setTextColor(WHITE); display.setCursor(30,0); display.println("ATLANT 130-3M"); //Выводи надпись название модели холодильника switch (s){ case 0://Экран выводимый по умолчанию (не пункт меню) PrintLabel("Tempeture:",0,10); if (t_ok==0) { //если ds18b20 не исправен то выводим об ошибке подключения display.setTextColor(WHITE); display.setCursor(10,20); display.println("Tempsensor ERROR"); } else { display.setCursor(60,10); //если ds18b20 исправен то выводим текущую температуру display.print(f_tempC); display.println(" C");//выводим температуру } break; case 1://экран изменения переменной 1 PrintLabel(myLabel[0],0,10); PrintLabel(myLabel[1],0,20); display.setCursor(30,20); display.println(p1); break; case 2://экран изменения переменной 2 PrintLabel(myLabel[0],0,10); PrintLabel(myLabel[2],0,20); display.setCursor(30,20); display.println(p2); break; case 3://экран изменения переменной 3 PrintLabel("SCREEN 3",0,10); PrintLabel(myLabel[3],0,20); display.setCursor(30,20); display.println(p3); break; /*case 4://экран изменения переменной 4 PrintLabel("SCREEN 4",0,10); PrintLabel(myLabel[3],0,20); display.setCursor(30,20); display.println(p3); break;*/ } display.display(); } //---------вывод лейблов в указанном месте экрана------------- void PrintLabel(char* t, byte x, byte y){//char* t - лейбл, x-столбец, y-строка display.setCursor(x,y); display.println(t); } void loop() { ul_newTime = millis(); // Получаем текущее время //heartIndication(ul_newTime); // Моргаем светодиодом активности run(automat[m][getEvent()]);//выполнение действия из таблицы переходов pushEvent();//сдвигаем очередь //------Опрос кнопок----------------------- if (millis()>KPTimer){//если пришло время cludEvent(6);//опрос кнопок - сохраняем в очередь код события } digitalWrite(ledPin,p3); //-----Автовозврат к основному экрану--------------- if (millis()-MSRTimer>=MSRecovery && m !=0 ){ //если пришло время и экран не основной MSRTimer=millis(); cludEvent(5);//то отобразить главный экран - сохраняем в очередь код события } //getEventLenght();//выводит очередь заданий на экран //-----------Обновление экрана-------------- if (millis()-PSTimer>250){//вывод экрана каждые 250мсек 4р/сек PSTimer=millis(); cludEvent(4);//обновление экрана - сохраняем в очередь код события } sensors.requestTemperatures(); f_tempC = sensors.getTempCByIndex(0); // Получаем температуру с датчика // Проверяем работоспособность датчика температуры if(( f_tempC > -30.0 ) && ( f_tempC < 50.0 )){ // Температурный датчик исправен t_ok=1; //флаг исправности датчика температуры в 1 если исправен //digitalWrite(LED_ERROR, LOW); if ( b_compressorOff ) { // Если компрессор выключен ul_deltaTime = deltamills(ul_offTime, ul_newTime); // Разница времени простоя if (ul_deltaTime > DELAY_COMPRESSOR) { // Если разница времени простоя больше разрешенной if ( f_tempC > TEMPERATURE_MAX ) { // Если температура больше максимально допустимой digitalWrite(RELE, HIGH); // Включаем компрессор b_compressorOff = false; ul_workTime = millis(); // Записываем время включения } } } else { // Если компрессор включен ul_deltaTime = deltamills(ul_workTime, ul_newTime); // Разница времени работы // Если температура меньше минимально допустимой или время работы больше допустимого if ( ( f_tempC < TEMPERATURE_MIN ) || ( ul_deltaTime > MAXTIME_COMPRESSOR ) ) { digitalWrite(RELE, LOW); // Выключаем компрессор b_compressorOff = true; ul_offTime = millis(); // Запоминаем время выключения компрессора } } } else { // Температурный датчик неисправен или оборван t_ok=0; //флаг исправности датчика температуры в ноль если не исправен if( b_compressorOff ){ // Если компрессор выключен при неисправном датчике ul_deltaTime = deltamills(ul_offTime, ul_newTime); // Разница времени простоя if (ul_deltaTime > ERROR_COMPRESSOR_OFF) { // Если разница времени простоя больше разрешенной digitalWrite(RELE, HIGH); // Включаем компрессор b_compressorOff = false; ul_workTime = millis(); // Записываем время включения } } else { // Если компрессор включен при неисправном датчике ul_deltaTime = deltamills(ul_workTime, ul_newTime); if ( ul_deltaTime > ERROR_COMPRESSOR_ON ) { digitalWrite(RELE, LOW); // Выключаем компрессор b_compressorOff = true; ul_offTime = millis(); // Запоминаем время выключения компрессора } } } }//end LOOP
пробую скомпилировать ваш код! ругается на sensors.isConversionAvailable(deviceAddress), такими словами Arduino: 1.8.5 (Windows 7), Плата:"Arduino Nano, ATmega328P"
Значит, у Вас другая версия библиотеки DallasTemperature. Возмите вот эту - https://drive.google.com/open?id=1KaWWTHU3KcSg2R8Hcx6CyIyO1a9iSOt5
Значит, у Вас другая версия библиотеки DallasTemperature. Возмите вот эту - https://drive.google.com/open?id=1KaWWTHU3KcSg2R8Hcx6CyIyO1a9iSOt5
С вашей заработал пример, до этого последняя была установлена версия dt 3,8,0
Спасибо вам что направили меня! С этим примером код стал шустро работать ни каких затыков! опрос датчика около 43-44мс.
Либо без монструозной библиотеки.
Либо без монструозной библиотеки.
120% согласен. В температурной библиотеке оч много ненужных задержек.