Решение и пример скетча с условиями температуры Подскажите пожалуйста. Нужно чтобы две нагрузки попеременно работали. Включается одна по температуре --> отработала час выключилась --> включилась другая --> отработала час выключилась --> включилась первая.... Код (Text): void Rele_Control(){ //Функция управления двух реле по температуре if(TempR>=Temp1 && TempR>=Temp2){//оба реле замыкаются, если температура датчика соответствует двум условиям, температуры заданные ранее Temp 1 и Temp 2. TempR с термистора digitalWrite(Rele1, HIGH); digitalWrite(Rele2, HIGH); //подается сигнал на включение } else if(TempR>=Temp1 || TempR>=Temp2){//одно реле запускается digitalWrite(Rele1, HIGH); Millis = millis(); if(Millis >0 && (millis()-Millis >= interval)){ //interval - время между включения нагрузок digitalWrite(Rele1, LOW); digitalWrite(Rele2, HIGH); Millis = millis(); } } Всё это работает пока температура соответствует. Так понимаю надо с millis() писать
Алгоритм понятен, но реализация крайне не верна. Использование в функциях глобальных переменных - не комильфо. На уроках программирования этому отучают на первых занятиях. Millis >0 это условие выполняется всегда millis()-Millis >= interval, если речь идет о интервале времени час, не будет работать никогда. Так как здесь написано millis()-Millis это интервал между заходами в функцию Rele_Control. Это микро или миллисекунды. Возможно, к вечеру напишу пробный, но сразу предупреждаю будут использована эта библиотека. http://forum.amperka.ru/threads/Таймеры-и-программный-антидребезг-входов.4280/ Rele_Control будет классом, а не функцией. Какое реле выключать, после того, как оба были включены? По хорошему, если не вести подсчет выработки, то то, которое включилось первым. В этом режиме так же есть тонкости с подсчетом времени.
У меня получилось вот-что Код (Text): #include <DI.h> //подключаем библиотеку DI - обработка дискретного входа из набора библиотек от X-Dron #include <Timer_P.h> //подключаем библиотеку Timer_P - работа с таямерами из набора библиотек от X-Dron #define T1_PIN 2 #define T2_PIN 3 #define Relay1_PIN 7 #define Relay2_PIN 8 class TCtrl { private: boolean Relay1, Relay2, NewCycle, T1_mode_old, RelayKeep; long Duration; Timer_P Cycle; public: TCtrl(long Duration); void Ctrl(boolean T1, boolean T2); boolean GetRelay1(); boolean GetRelay2(); }; // Создание объектов типа "Дистретный вход" они посажены описанные выше пины. Фильтр антидребезга 10мс. DI T1(T1_PIN, 10); DI T2(T2_PIN, 10); TCtrl MyTCtrl(5000); //Создаем объект класса TCtrl 5000 - длительность работы реле в режиме переключения в мс. Здесь 5сек void setup() { //Режимы выходов pinMode(Relay1_PIN, OUTPUT); pinMode(Relay2_PIN, OUTPUT); //делать pinMode для входов не нужно. Они инициализируются при создании объекта класса DI //при работе со входами используется INPUT_PULLUP-режим. Значения входов нормализовываются во время обработки класса. //замкнутая кнопка - логическая 1. } void loop() { // Обновляем значение дискретных входов // Производится их считывание с пинов и фильтрация через внутреннюю переменную класса. T1.DI_Refresh(); T2.DI_Refresh(); MyTCtrl.Ctrl(T1.DI_Read(), T2.DI_Read()); digitalWrite(Relay1_PIN, MyTCtrl.GetRelay1()); digitalWrite(Relay2_PIN, MyTCtrl.GetRelay2()); } TCtrl::TCtrl(long Duration) { this->Duration = Duration; } boolean TCtrl::GetRelay1() { return this->Relay1; } boolean TCtrl::GetRelay2() { return this->Relay2; } void TCtrl::Ctrl(boolean T1, boolean T2) { if (this->Relay1 and !this->Relay2) this->RelayKeep = true; if (this->Relay2 and !this->Relay1) this->RelayKeep = false; this->NewCycle = this->Cycle.Timer_P::Timer(!(this->NewCycle) && (this->Relay1 || this->Relay2) && !(this->Relay1 && this->Relay2), 0, 2, this->Duration); if (!T1 && !T2) { this->Relay1 = false; this->Relay2 = false; } if ((T1 && T2) || T2) { this->Relay1 = true; this->Relay2 = true; } if (T1 && !T2) { if ((this->NewCycle || ! T1_mode_old) && !this->RelayKeep) { this->Relay1 = true; this->Relay2 = false; } if ((this->NewCycle || ! T1_mode_old) && this->RelayKeep) { this->Relay1 = false; this->Relay2 = true; } } T1_mode_old = (T1 && !T2); } Видео: Логика такая (предположим, что работаем на охлаждение): Есть 2 температурных датчика. Уровень срабатывания 1-го ниже уровня срабатывания 2-го. Если сработает второй, то и 1-й должен быть сработавшим. Например 1-й 30град, второй 40град. Температурные уровни имитирую кнопками. Если нет ни одного уровня - оба реле выключены. Если есть 1-й уровень, то включается одно реле, если до истечения интервала переключения уровень 1 уйдет, то в следующий раз включится другое реле. Если уровень 1 держится дольше интервала переключения, то реле переключаются. Если появится 2-ой уровень, то включится и второе реле. При уходе 2-го уровня отключится то реле, которое было включено первым. Применительно к Вашему скетчу MyTCtrl.Ctrl вызывать Код (Text): MyTCtrl.Ctrl(TempR>=Temp1, TempR>=Temp2) Temp2 > Temp1. Все что связано с T1 и T2 вне void TCtrl::Ctrl(boolean T1, boolean T2) удалить.
Буду разбираться, спасибо за помощь. Планируется что будет все работать от одного терморезистора, и его значения будут сравниваться с заданными, а выполнение условия будет запускать реле. О millis - это счетчик который стартует при запуске МК доходит до опред значения и сбрасывается в ноль. Вот интересует как с ним работать чтобы реле запустилось и пошла проверка на время, одновременно и температуру. Планировал вот так : при запуске реле пишем значение в переменную Millis допустим "Millis()=40000" после этого при каждом круге loop сравниваем выражение с интервалом millis()-Millis >= interval почему не будет работать?
Засечка времени с Millis() делается так: if (фронт условия начала отсчета) Millis=Millis()+interval; if (Millis()>Millis) { действия по истечению времени} В первом условии обязательно должен быть фронт события. Если поставить просто событие, то Millis будет каждый раз высчитываться заново и второе условие не сработает никогда. Подчищенный скетч без кнопок. Код (Text): #include <Timer_P.h> //подключаем библиотеку Timer_P - работа с таямерами из набора библиотек от X-Dron #define Relay1_PIN 7 #define Relay2_PIN 8 class TCtrl { private: boolean Relay1, Relay2, NewCycle, T1_mode_old, RelayKeep; long Duration; Timer_P Cycle; public: TCtrl(long Duration); void Ctrl(boolean T1, boolean T2); boolean GetRelay1(); boolean GetRelay2(); }; TCtrl MyTCtrl(5000); //Создаем объект класса TCtrl 5000 - длительность работы реле в режиме переключения в мс. Здесь 5сек void setup() { //Режимы выходов pinMode(Relay1_PIN, OUTPUT); pinMode(Relay2_PIN, OUTPUT); } void loop() { // Обработка терморезистора, значение на его выходе TempR //Temp1, Temp2 уставки срабатывания MyTCtrl.Ctrl(TempR>=Temp1, TempR>=Temp2) digitalWrite(Relay1_PIN, MyTCtrl.GetRelay1()); digitalWrite(Relay2_PIN, MyTCtrl.GetRelay2()); } TCtrl::TCtrl(long Duration) { this->Duration = Duration; } boolean TCtrl::GetRelay1() { return this->Relay1; } boolean TCtrl::GetRelay2() { return this->Relay2; } void TCtrl::Ctrl(boolean T1, boolean T2) { if (this->Relay1 and !this->Relay2) this->RelayKeep = true; if (this->Relay2 and !this->Relay1) this->RelayKeep = false; this->NewCycle = this->Cycle.Timer_P::Timer(!(this->NewCycle) && (this->Relay1 || this->Relay2) && !(this->Relay1 && this->Relay2), 0, 2, this->Duration); if (!T1 && !T2) { this->Relay1 = false; this->Relay2 = false; } if ((T1 && T2) || T2) { this->Relay1 = true; this->Relay2 = true; } if (T1 && !T2) { if ((this->NewCycle || ! T1_mode_old) && !this->RelayKeep) { this->Relay1 = true; this->Relay2 = false; } if ((this->NewCycle || ! T1_mode_old) && this->RelayKeep) { this->Relay1 = false; this->Relay2 = true; } } T1_mode_old = (T1 && !T2); }
В конце моего скетча лучше подправить Код (Text): if (T1 && !T2) { if ((this->NewCycle || !this->T1_mode_old) && !this->RelayKeep) { this->Relay1 = true; this->Relay2 = false; } if ((this->NewCycle || !this->T1_mode_old) && this->RelayKeep) { this->Relay1 = false; this->Relay2 = true; } } this->T1_mode_old = (T1 && !T2); } T1_mode_old тоже должен быть с "this->"
this-> не совсем пойму и вот сейчас Засечка времени с Millis() делается так: if (фронт условия начала отсчета) Millis=Millis()+interval; if (Millis()>Millis) { действия по истечению времени} Почему с часами не получится? на примере 2х светодиодов
Код (Text): const int ledPin1 = 3; const int ledPin2 = 2; unsigned long previousMillis = 0; const long interval = 5000; void setup() { pinMode(ledPin1, OUTPUT); pinMode(ledPin2, OUTPUT); Serial.begin(9600); } void loop() { if((millis()-previousMillis) > interval){ long delta = interval-millis()+previousMillis; previousMillis=delta; Serial.println(1); } else { if(previousMillis + interval <= millis()){ if(digitalRead(ledPin1)==LOW&&digitalRead(ledPin2)==LOW){ digitalWrite(ledPin1,HIGH); previousMillis = millis(); Serial.println(2); } else if (digitalRead(ledPin1)==HIGH&&digitalRead(ledPin2)==LOW){ digitalWrite(ledPin1,LOW); digitalWrite(ledPin2,HIGH); previousMillis = millis(); Serial.println(3); } else { digitalWrite(ledPin1,HIGH); digitalWrite(ledPin2,LOW); previousMillis = millis(); Serial.println(4); } } } } Если установится максимальное значение для миллис и произойдет сброс, будет работать.
и вот если разместить Serial.println(millis()) то кроме первого условия ничего не выполняется. из-за чего?