термореле для холодильника 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"
template <typename T> inline Print & operator << (Print &s, T n) { s.print(n); return s; } #include <OneWire.h> #include <DallasTemperature.h> #define SENSOR_PIN 6 OneWire oneWire(SENSOR_PIN); DallasTemperature sensors(&oneWire); DeviceAddress deviceAddress; void setup(void) { Serial.begin(115200); Serial << "Non blocking Dallas Temperature Demo\n"; sensors.begin(); sensors.getAddress(deviceAddress, 0); sensors.setWaitForConversion(false); } void loop(void) { static bool didNotSendYet = true; static unsigned long start; if (didNotSendYet) { start = millis(); sensors.requestTemperaturesByAddress(deviceAddress); didNotSendYet = false; } else if (sensors.isConversionAvailable(deviceAddress)) { const float temp = sensors.getTempC(deviceAddress); const unsigned long duration = millis() - start; Serial << "Temperature: " << temp << " (" << duration << " ms)\n"; delay(2000); didNotSendYet = true; } }Значит, у Вас другая версия библиотеки DallasTemperature. Возмите вот эту - https://drive.google.com/open?id=1KaWWTHU3KcSg2R8Hcx6CyIyO1a9iSOt5
Значит, у Вас другая версия библиотеки DallasTemperature. Возмите вот эту - https://drive.google.com/open?id=1KaWWTHU3KcSg2R8Hcx6CyIyO1a9iSOt5
С вашей заработал пример, до этого последняя была установлена версия dt 3,8,0
Спасибо вам что направили меня! С этим примером код стал шустро работать ни каких затыков! опрос датчика около 43-44мс.
Либо без монструозной библиотеки.
Либо без монструозной библиотеки.
120% согласен. В температурной библиотеке оч много ненужных задержек.