Таймер на несколько включений в день по расписанию на одном канале без экрана. Используется Arduino Pro Mini и DS1307. С одним включением и выключением работает нормально. Код (C++): #include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC #include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC RTC_DS1307 RTC; //Создаем переменную класса - для использования RTC const int led = 11; //Используем цифровой ПОРТ 13 для ПЕРВОГО канала релейного модуля // Массивы со временм включения и выключения long onh[]={16,16,16,16}; //Часы включения long onm[]={19,19,19,19}; // Минуты long ons[]={0,5,10,15}; //Секунды long time_on = 0; long offh[]={16,16,16,16}; //Часы выключения long offm[]={19,19,19,19}; //Минуты long offs[]={3,8,13,19}; //Секунды long time_off = 0; void setup(){ Serial.begin(9600); pinMode(led,OUTPUT); //Инициализируем порт для ПЕРВОГО канала как ВЫХОД analogWrite(led,0); //Устанавливаем на входах модуля НИЗКИЙ уровень Wire.begin(); //Инициируем I2C интерфейс RTC.begin(); //Инициирум RTC модуль } void loop() { DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла long utime = myTime.unixtime(); //сохраняем в переменную - время в формате UNIX utime %= 86400; //Сохраняем в этой же переменной остаток деления на кол-во секнд в сутках, //Это дает количество секунд с начала текущих суток for (int a = 0; a < 4; a++){ // изменить цифру на кол-во раз ключения long time_on = ((onh[a]*3600)+(onm[a]*60)+ons[a]); //Рсчет секунд для включения Serial.println(time_on); long time_off = ((offh[a]*3600)+(offm[a]*60)+offs[a]); //Рсчет секунд для выключения Serial.println(time_off); if ((utime >= time_on) && (utime <= time_off)) { analogWrite(led,255); //Устанавливаем на ПЕРВОМ канале ВЫСОКИЙ уровень } else //во всех остальных случаях { analogWrite(led,0); //Устанавливаем на ПЕРВОМ канале НИЗКИЙ уровень } } } Если добавить оставшиеся включения, получается абракадабра. В таком варианте кода цикл считает массивы по кругу не дожидаясь выполнения условия. И из-зи этого появляется мерцание . Нужно заставить посчитать первые элементы массивов, дождаться, когда выполнится условие, включить и выключить led, посчитать вторые элементы массивов, дождаться, когда выполнится условие, включить и выключить led и т.д.Как это увязать?
Включение/выключение светодиода необходимо вынести за пределы цикла: Код (C++): #include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC #include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC RTC_DS1307 RTC; //Создаем переменную класса - для использования RTC const int led = 11; //Используем цифровой ПОРТ 13 для ПЕРВОГО канала релейного модуля // Массивы со временм включения и выключения long onh[]={16,16,16,16}; //Часы включения long onm[]={19,19,19,19}; // Минуты long ons[]={0,5,10,15}; //Секунды long time_on = 0; long offh[]={16,16,16,16}; //Часы выключения long offm[]={19,19,19,19}; //Минуты long offs[]={3,8,13,19}; //Секунды long time_off = 0; void setup(){ Serial.begin(9600); pinMode(led,OUTPUT); //Инициализируем порт для ПЕРВОГО канала как ВЫХОД analogWrite(led,0); //Устанавливаем на входах модуля НИЗКИЙ уровень Wire.begin(); //Инициируем I2C интерфейс RTC.begin(); //Инициирум RTC модуль } void loop() { DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла long utime = myTime.unixtime(); //сохраняем в переменную - время в формате UNIX utime %= 86400; //Сохраняем в этой же переменной остаток деления на кол-во секнд в сутках, //Это дает количество секунд с начала текущих суток bool doLedOn = false; for (int a = 0; a < 4; a++){ // изменить цифру на кол-во раз ключения long time_on = ((onh[a]*3600)+(onm[a]*60)+ons[a]); //Рсчет секунд для включения Serial.println(time_on); long time_off = ((offh[a]*3600)+(offm[a]*60)+offs[a]); //Рсчет секунд для выключения Serial.println(time_off); if ((utime >= time_on) && (utime <= time_off)) { doLedOn = true; } } if (doLedOn) { analogWrite(led,255); //Устанавливаем на ПЕРВОМ канале ВЫСОКИЙ уровень } else //во всех остальных случаях { analogWrite(led,0); //Устанавливаем на ПЕРВОМ канале НИЗКИЙ уровень } }
Заработало. Спасибо. Потребовалось также немного усложнить программу. По достижении времени выполнить увеличение и уменьшение шим. Код (C++): #include <Bounce2.h> // подключаем библиотеку #include <Wire.h> //Подключаем библиотеку для использования I2C интерфейса с модулем RTC #include <RTClib.h> //Подключаем библиотеку для использования модуля часов реального времени RTC RTC_DS1307 RTC; //Создаем переменную класса - для использования RTC long onh[]={20,20,20,20}; //Часы включения long onm[]={50,50,50,50}; // Минуты long ons[]={0,10,20,30}; //Секунды long time_on = 0; long offh[]={20,16,16,16}; //Часы выключения long offm[]={50,50,50,50}; //Минуты long offs[]={5,15,25,30}; //Секунды long time_off = 0; int t = 0; // начало счетчика(не имеет значения, но лучше не трогать) int tpwm = 1; // величина счетчика, устанавливает длительность шим int onb = 0; // устанавливает начальное значение включения int one = 255; // устанавливает конечное значение включения int offb = 255; // устанавливает начальное значение выключения int offe = 0; // устанавливает конечное значение выключения const int switchPin = 8; // пин кнопки const int ledPin = 11; // пин светодиода int cnt = 0; // счётчик нажатий int c = 0 ; // переменная для восстановления начальных значений вкл и выкл Bounce b = Bounce(); // инстанциируем объект Bounce void setup() { Serial.begin(9600); pinMode(switchPin, INPUT); digitalWrite(switchPin, HIGH); // включаем подтягивающий резистор pinMode(ledPin, OUTPUT); analogWrite(ledPin,0); //Устанавливаем на входах модуля НИЗКИЙ уровень b.attach(switchPin); // объект Bounce будет слушать кнопку на пине switchPin b.interval(5); // устанавливаем время задержки в [мс] Wire.begin(); //Инициируем I2C интерфейс RTC.begin(); //Инициирум RTC модуль } void loop() { DateTime myTime = RTC.now(); //Читаем данные времени из RTC при каждом выполнении цикла long utime = myTime.unixtime(); //сохраняем в переменную - время в формате UNIX utime %= 86400; //Сохраняем в этой же переменной остаток деления на кол-во секнд в сутках, //Это дает количество секунд с начала текущих суток for (int a = 0; a < 4; a++){ long time_on = ((onh[a]*3600)+(onm[a]*60)+ons[a]); long time_off = ((offh[a]*3600)+(offm[a]*60)+offs[a]); if (utime==time_on) { c = onb; while(c < one) { t++; if(t>tpwm) t=0; if(t==1)c++; Serial.println(c); { analogWrite(ledPin, c);// иначе - зажигаем светодиод } } } else if (utime==time_off) { c = offb; // запоминание начального значения while(c > offe) { t++; if(t>tpwm) t=0; if(t==1)c--; Serial.println(c); { analogWrite(ledPin, c);// гасим светодиод } } } } /* if (b.update() && b.read() == 0) { // если зарегистрировано событие и кнопка нажата, cnt += 1; // инкрементируем счётчик нажатий if (cnt %2 == 0) //если четное, то гасим { c = offb; // запоминание начального значения while(offb > offe) { t++; if(t>tpwm) t=0; if(t==1)offb--; Serial.println(offb); { analogWrite(ledPin, offb);// гасим светодиод } } offb = c ; } else { c = onb; while(onb < one) { t++; if(t>tpwm) t=0; if(t==1)onb++; Serial.println(onb); { analogWrite(ledPin, onb);// иначе - зажигаем светодиод } } onb = c ; } } */ } первый раз включился от 0 до 255, выключился 255 - 0, и потом 3 раза только включается 0 - 255. От кнопки код работал правильно.
Код (C++): long onh[]={20,20,20,20}; //Часы включения ........... long offh[]={20,16,16,16}; //Часы выключения Внимательно смотрим и сравниваем последние три элемента массивов 'onh[]' и 'offh[]'.
не по делу if(t>tpwm)t=0; if(t==1)c++; Serial.println(c); { analogWrite(ledPin, c);// иначе - зажигаем светодиод }
Код (C++): long onh[]={20,20,20,20}; . . . int offb = 255; int offe = 0; Извиняюсь, что не совсем по теме, но может объясните, в чем выгода использовать для подобных переменных избыточный тип данных? Логичнее, на первый взгляд, было бы здесь использовать тип byte.
посмотрите на условие в мониторе порта. Наверное, делаете плавно нарастающий и плавно спадающий ШИМ просто подсчет от минимума к максимуму выполняется быстро, поэтому ШИМ выйдет на максимум и аналогично на минимум быстро. Можно применить delayMicroseconds
Limoney, код заработал, ошибка по невнимательности в указании времени в массивах. Код (C++): if(t>tpwm)t=0; if(t==1)c++; Serial.println(c); { analogWrite(ledPin, c);// иначе - зажигаем светодиод } Не хочу использовать delay и millis, первый по причине остановке всей программы, второй - не хочу делать рестарт каждые 50 дней. Или можно как-нибудь более красиво выйти из положения?