byte btn_flag = 1;
boolean btn_off = 1;
boolean reley_on;
boolean btn_on;
unsigned long last_press;
unsigned long wattering_time;
void setup() {
Serial.begin(9600);
pinMode(2, OUTPUT);
pinMode(A4, INPUT_PULLUP);
}
void loop() {
btn_on = !digitalRead(A4);
if(btn_on == 1){
while (btn_flag){
if(millis() - wattering_time > 2000){
Serial.println(btn_flag);
Serial.print("btn_on ..... ");Serial.println(btn_on);
digitalWrite(2, HIGH);
reley_on = 1;
wattering_time = millis();
btn_on = !digitalRead(A4);
}
if(reley_on == 1 && millis() - wattering_time > 2000){
digitalWrite(2, LOW);
reley_on = 0;
wattering_time = millis();
Serial.print("btn_on ..... ");Serial.println(btn_on);
Serial.print("btn_off ..... ");Serial.println(btn_off);
}
if(btn_on){
break;
}
}
}
}
Потому что на два таймера одна общая переменная wattering_time
btn_on = !digitalRead(A4);
убираю это из цикла while и все работает корректно, не не могу додуматься как мне выходить из цикла при повторном нажатии на кнопку
Опишите своими словами, как , по вашему, всё должно работать
Я нажимаю на кнопку —> включается реле на определенное время —> после истечения времени реле отключается на определенное время —> этот цикл продолжается пока я повторно не нажму кнопку
Не прописал в условии reley_on ==0
Код надо переписать, сейчас уже занят. Если смогу, отвечу позже
Большое спасибо за содействие
boolean cycle_counter = 1; // условие для цикла
boolean reley_flag; // флаг положения реле
boolean btn_flag; // флаг положения кнопки
byte reley = 2; // переменная для пина реле
byte button = 18; // переменная для пина кнопки
unsigned long wattering_time; // переменная для хранения времени
unsigned long button_timer; // переменная для хранения времени от дребезга
void setup() {
Serial.begin(9600);
pinMode(reley, OUTPUT); // инициализация пинов
pinMode(button, INPUT_PULLUP); //
}
void loop() {
btn_flag = !digitalRead(button); // считываю кнопку
if(btn_flag == 1 && millis() - button_timer > 150){ // если кнопка нажата перехожу к циклу
cycle_counter = 1;
button_timer = millis();
while (cycle_counter){ // поочередно включает и отключает реле с заданным промежутком времени
btn_flag = !digitalRead(button); // снова считываю положение кнопки
if(reley_flag == 0 && millis() - wattering_time > 2000){
digitalWrite(2, HIGH);
reley_flag = 1;
wattering_time = millis();
Serial.println("Реле в работе ");
}
if(reley_flag == 1 && millis() - wattering_time > 2000){
digitalWrite(2, LOW);
reley_flag = 0;
wattering_time = millis();
Serial.println("Реле не работает");
}
if(reley_flag == 0 && btn_flag == 1 && millis() - button_timer > 150){ // если повторно нажал на кнопку, останавливаем цикл
cycle_counter = 0; // можно отключить только когда реле не в работе
button_timer = millis();
}
}
}
}
переписал немного код.
теперь все функционирует как планировал.
Буду рад замечаниям и советам для дальнейшего улучшения кода
Цикл while тормозит реакцию на кнопку. Пока он не отработает, ничего изменить невозможно.
Вот набросал на скорую руку. Нажатие на кнопку действует немедленно(почти) останавливая/запуская цикл.
Спойлер
#define RelayPin 2
#define BtnPin 18
boolean btn_flag = 0; //нули для наглядности
boolean btn = 0;
boolean relay_on = 0;
boolean btn_on = 0;
boolean ON = false;
boolean OFF = false;
uint8_t btnStat = 0;
unsigned long last_millis = 0;
unsigned long wattering_time = 0;
unsigned long wattering_timeOFF = 0;
void setup() {
Serial.begin(9600);
pinMode(RelayPin, OUTPUT);
pinMode(BtnPin, INPUT_PULLUP);//A4 это цифровой пин 18
}
void loop() {
if(millis() - last_millis > 10)//опрос кнопки
{
last_millis = millis();
btn = !digitalRead(BtnPin);
if (btn && btnStat == 0)
{
btnStat = 1;
btn_flag = true;
relay_on = true;
ON = true;
}
if (!btn && btnStat == 1)
btnStat = 2;
if (btn && btnStat == 2)
{
btnStat = 3;
btn_flag = false;
relay_on = false;
OFF = true;
}
if (!btn && btnStat == 3)
btnStat = 0;
}
if (btn_flag)
{
if ((millis() - wattering_time > 1000) || ON) {//мигаем или вкл/выкл
wattering_time = millis();
ON = false;
Serial.print("btn_flag ");
Serial.println(btn_flag);
Serial.print("rele = "); Serial.println(relay_on);
Serial.println();
digitalWrite(RelayPin, relay_on);
relay_on = !relay_on;
}
}
else
{
if ((millis() - wattering_timeOFF > 1000) || OFF)
{//этот таймер лишь для наглядности, для вывода в сериал
wattering_timeOFF = millis();
OFF = false;
Serial.print("btn_flag ");
Serial.println(btn_flag);
digitalWrite(RelayPin, relay_on);
Serial.print("rele = "); Serial.println(relay_on);
Serial.println();
}
}
}