да и пусть себе сыпет, вопрос в другом - как избежать морганий диода, и почему спустя минуту диод всё таки гаснет.
Попробуйте добавить еще одну переменную. Если время включить, присваиваем переменной 1. Если время выключить то 0. Т в цикле включить реле если переменная =1 и выключить если переменная = 0.
Всем спасибо за советы. Несколько своих ошибок я исправил, но всё равно, к желаемому результату не пришёл. Решил плюнуть на это дело и найти уже рабочий скетч. P.S //Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время //delay(1); // приостанавливаем на 1 мс, чтоб не выводить время несколько раз за 1мс //если закомментировать строки выше, то диод горит ярко (и без миганий, так как убрать delay(1000) в качестве паузы между выводом показаний в serial) tmp_h = time.Hours; tmp_m = time.minutes; tmp_s = time.seconds; if (tmp_h>=11 && tmp_m>=17) { //заменил == на >= для корректного включения диода даже после условного времени. //Включаем в 7 утра digitalWrite(lamp, HIGH); } if (tmp_h>=19 && tmp_m>=00); { //по идее, 19>11 и после 19.00 условие будет действовать //Выключаем в 7 вечера digitalWrite(lamp, LOW); }
Рабочего скетча так и не нашёл, зато написал свой. Делюсь, может кому пригодиться. Там два варианта - один понятный, второй короткий. void loop() { Serial.println(time.gettime("d-m-Y, H:i:s, D")); // выводим время delay(1000); // приостанавливаем на 1с, чтоб не выводить время несколько раз за 1с tmp_h = time.Hours; tmp_m = time.minutes; tmp_s = time.seconds; // короткий if (H_off<=tmp_h || tmp_h<H_on) //tmp_h = 18.59 h_off = 19 h_on = 17 светит с 19 до 17 часов. digitalWrite(lamp, HIGH); else digitalWrite(lamp, LOW); //стопудово рабочий вариант (понятный) //if (tmp_h >= H_off && tmp_m >= M_off) //digitalWrite(lamp, LOW); //if (tmp_h < H_off) //digitalWrite(lamp, HIGH); Критика приветствуется.
Использую библиотеку RtcDS3231 (https://github.com/Makuna/Rtc). При перепрошивке текущее время с компа записывается корректно, но после отключения питания и последующего включения отсчет продолжается с момента отключения, т.е. если отключаю питание в 19:40, а включаю в 9:15, то время в МК становится 19:41, тогда как должно быть 9:15. В каком направлении копать? Как вообще реализовать следующую логику работы (без дальнейшего вмешательства в скетч, если понадобится изменить время)? * после каждой перепрошивки дата и время берутся из компа (время компиляции) и принудительно записываются в RTC. * Далее при каждом включении питания (кроме перепрошивки) дата и время берется из RTC. * При ручном задании обновленные дата и время записываются в RTC. Т.е. по отдельности каждый пункт я знаю как сделать, а вот как логика комплексной работы пока недоступна. Вчерне так: при прошивке ставить флаг "0" в EEPROM (как это сделать однократно, только при прошивке, а не после каждого вызова setup?), далее в setup смотреть его состояние и ветка на два направления.
Код (C++): //Подключаем библиотеки для работы часов реального времени #include <DS3231.h> #include <Wire.h> // выводы для дешифратора int out1 = A3; int out2 = A1; int out4 = A0; int out8 = A2; // выводы для транзисторных ключей int key1= 4; int key2 = 6; int key3 = 7; int key4 = 8; int led1=11;// вывод светодиода int keyb=A6;// пин для клавиатуры int keynum=0; //номер нажатой кнопки int mode =0; //0 - отображение текущего времени 1- установка времени int currentdigit = 0; //0 - установка часов 1- установка минут bool blinkflag = 0; // флаг для мигания цифр при установке времени bool timeout=false; // таймаут после нажатия кнопки (для устраниния дребезга) unsigned long startTime; //для мигания светодиода unsigned long startTime2; // для опроса нажатых кнопок int sec; //переменная увеличивается каждые 500мс на единицу. Нужна для мигания секундных светодиодов, бывает в двух значениях 0 - светодиоды не горят, 1 - горят, если больше 1, то сбрысывается в 0 // переменные, необходимые для работы ds3231 DS3231 Clock; bool Century=false; bool h12; bool PM; byte ADay, AHour, AMinute, ASecond, ABits; bool ADy, A12h, Apm; //определяем глобальные переменные для различных параметров часов int second,minute,hour,date,month,year,temperature; void setup() { // put your setup code here, to run once: // задаем частоту ШИМ на 9 выводе 30кГц TCCR1B=TCCR1B&0b11111000|0x01; analogWrite(9,130); // Start the I2C interface Wire.begin(); // Start the serial interface Serial.begin(9600); //задаем режим работы выходов микроконтроллера pinMode(out1,OUTPUT); pinMode(out2,OUTPUT); pinMode(out4,OUTPUT); pinMode(out8,OUTPUT); pinMode(key1,OUTPUT); pinMode(key2,OUTPUT); pinMode(key3,OUTPUT); pinMode(key4,OUTPUT); pinMode(led1,OUTPUT); startTime = millis(); startTime2=startTime; sec = 0; // считываем текущее вермя ReadDS3231(); } void ReadDS3231() //функция считывает в глобальные переменные minute и hour текущие значения { minute=Clock.getMinute(); hour=Clock.getHour(h12, PM); } void loop() { // put your main code here, to run repeatedly: int digits[3]; // массив для текущего значения времени на четыре цифры int keyval= analogRead(keyb); // считываем значение с клавиатуры unsigned long currentTime = millis(); //текущее время с момента запуска рограммы if (currentTime>=(startTime2+200)) // если прошло 200мс посмотрим какая кнопка была нажата { timeout=false; //проверим нажатие кнопок if (keynum==3) // кнопка переключения между режимами "время" и "настройка" { timeout=true; // запрещаем считывать нажатия кнопок if (mode==0) mode=1; // если отображалось время, переходим в режим настроек else if (mode==1) mode=0; //если был режим настроек, переключаемся на текущее время } if (keynum==2) // кнопка переключения между часами и минутами { timeout=true; // запрещаем считывать нажатия кнопок // currentdigit либо 0 - настройка часов, либо 1 - настройка минут currentdigit++; if (currentdigit==2) currentdigit=0; } if (keynum==1) // кнопка увеличения количества часов или минут(при настройке) { blinkflag=true; // прекращаем мигать цифрами startTime=millis(); timeout=true; // запрещаем считывать нажатия кнопок if (currentdigit==0) // если меняем часы { if (hour<=22) hour++; else hour=0; Clock.setHour(hour); } if (currentdigit==1) // если меняем минуты { if (minute<=58) minute++; else minute=0; Clock.setMinute(minute);//Set the minute Clock.setSecond(0); } } keynum=0; //сбрасываем нажатую кнопку startTime2=millis(); } if (currentTime>=(startTime+500)) // если прошло 500мс { blinkflag=!blinkflag; // инвертируем флаг мигающей цифры if(sec<1) // светодиоды не горят { // зажечь светодиоды digitalWrite(led1,HIGH); Serial.println(blinkflag); } if(sec>=1) // светодиоды горят { // потушить светодиоды digitalWrite(led1,LOW); } startTime = currentTime; ReadDS3231(); sec = (sec+1); if(sec>=2) sec=0; } digits[0] = hour/10; digits[1] = hour%10; digits[2] = minute/10; digits[3] = minute%10; show(digits); // вывести цифры на дисплей //проверяем нажатые кнопки if(!timeout) //если разрешено, считываем нажатую кнопку { /*keyval - значение функции analogread * если нажата первая кнопка, то принимает значение около 200 * если нажата вторая кнопка то значение около 700 * если третяя кнопка, то значение будет около 1000 * эти значения зависят от выбранных резисторов в клавиатуре */ if (keyval>150 && keyval<400) keynum=1; if (keyval>700 && keyval<900) keynum=2; if (keyval>960) keynum=3; } } void show(int a[]) { //выведем цифру a[0] на первый индикатор setNumber(a[0]); if (!(mode==1&¤tdigit==0&&blinkflag==false)) //если мы в режиме настройки и происходит настройка часов, то в первая цифра будет мигать { digitalWrite(key1,HIGH); delay(2); //потушим первый индикатор digitalWrite(key1,LOW); delay(1); } //цифра a[1] на второй индикатор setNumber(a[1]); if (!(mode==1&¤tdigit==0&&blinkflag==false)) { digitalWrite(key2,HIGH); delay(2); //потушим второй индикатор digitalWrite(key2,LOW); delay(1); } //цифра a[2] на третий индикатор setNumber(a[2]); if (!(mode==1&¤tdigit==1&&blinkflag==false)) { digitalWrite(key3,HIGH); delay(2); //потушим третий индикатор digitalWrite(key3,LOW); delay(1); } //выведем цифру a[3] на четвертый индикатор setNumber(a[3]); if (!(mode==1&¤tdigit==1&&blinkflag==false)) { digitalWrite(key4,HIGH); delay(2); //потушим четвертый индикатор digitalWrite(key4,LOW); delay(1); } } // передача цифры на дешифратор void setNumber(int num) { switch (num) { case 0: digitalWrite (out1,LOW); digitalWrite (out2,LOW); digitalWrite (out4,LOW); digitalWrite (out8,LOW); break; case 1: digitalWrite (out1,HIGH); digitalWrite (out2,LOW); digitalWrite (out4,LOW); digitalWrite (out8,LOW); break; case 2: digitalWrite (out1,LOW); digitalWrite (out2,HIGH); digitalWrite (out4,LOW); digitalWrite (out8,LOW); break; case 3: digitalWrite (out1,HIGH); digitalWrite (out2,HIGH); digitalWrite (out4,LOW); digitalWrite (out8,LOW); break; case 4: digitalWrite (out1,LOW); digitalWrite (out2,LOW); digitalWrite (out4,HIGH); digitalWrite (out8,LOW); break; case 5: digitalWrite (out1,HIGH); digitalWrite (out2,LOW); digitalWrite (out4,HIGH); digitalWrite (out8,LOW); break; case 6: digitalWrite (out1,LOW); digitalWrite (out2,HIGH); digitalWrite (out4,HIGH); digitalWrite (out8,LOW); break; case 7: digitalWrite (out1,HIGH); digitalWrite (out2,HIGH); digitalWrite (out4,HIGH); digitalWrite (out8,LOW); break; case 8: digitalWrite (out1,LOW); digitalWrite (out2,LOW); digitalWrite (out4,LOW); digitalWrite (out8,HIGH); break; case 9: digitalWrite (out1,HIGH); digitalWrite (out2,LOW); digitalWrite (out4,LOW); digitalWrite (out8,HIGH); break; } } Народ помогите!!! С ардуино первый раз. Собрал часы http://itworkclub.ru/arduino-часы-на-газоразрядных-индикаторах/. Отстают за минуту секунд на 15. Не могу вставить антиотравление.
Если без индикации, кнопок и прочего, только вывод в serial - часы (RTC) идут правильно, или то же отстают? По коду. Вот в этом месте возможна опечатка: Код (C++): int digits[3]; // массив для текущего значения времени на четыре цифры Массив заявляете на четыре значения, а объявляете на три.
Поизучал код - просто фиэрия какая-то. Может знаете для чего используется конструкция на подобия этой: Код (C++): if (!(mode==1&¤tdigit==0&&blinkflag==false)) { digitalWrite(key2,HIGH); delay(2); //потушим второй индикатор digitalWrite(key2,LOW); delay(1); } Только для мигания цифрой в режиме настройки, или для регенерации значений индикатора? Раз часы сами по себе идут правильно, то попробуйте теперь просто выводить значение времени на индикаторы. Т. е. без кнопок и функции настроек. Например, с такой функцией loop(): Код (C++): void loop() { static unsigned long currentTime = 0; int digits[4]; if (millis() - currentTime >= 500) // если прошло 0,5с { digitalWrite(led1, !digitalRead(led1)); // мигнуть светодиодом currentTime = millis(); ReadDS3231(); digits[0] = hour/10; digits[1] = hour%10; digits[2] = minute/10; digits[3] = minute%10; show(digits); // вывести цифры на дисплей } }
На всякий случай, дайте ссылку на библиотеку DS3231, которую Вы используете. А то некоторые места в коде вызывают вопросы. По первому куску кода, я так понимаю Вы ничего сказать не можете? Допустим, что этот кусок нужен только для мигания цифр. Тогда, можете попробовать такой код? Код (C++): void loop() { static unsigned long currentTime = 0; if (millis() - currentTime >= 1000) // если прошла 1с { digitalWrite(led1, !digitalRead(led1)); currentTime = millis(); ReadDS3231(); setNumber(hour/10); setNumber(hour%10); setNumber(minute/10); setNumber(minute%10); } } Если после включения цифры гореть не будут, то попробуйте добавить в конец setup() строчки: Код (C++): digitalWrite(key1,HIGH); digitalWrite(key2,HIGH); digitalWrite(key3,HIGH); digitalWrite(key4,HIGH); Позвольте глупый вопрос. Отстают на 15 сек за 1 мин - это значит, что в реальности проходит 5 минут, а часы отсчитывают только 4 минуты? Или значение минут сменяются на 15 секунд позже чем в "эталонных" часах?
Значение минут сменяется примерно на 15 секунд позже. По куску кода, указанному выше -без понятия. Библиотеку прилагаю. Спасибо за терпение....
Посмотрел примеры к библиотеке, сразу заметил несоответствие с Вашим кодом. Согласно примеру, объявление и инициализация объекта Clock должны выглядеть так: Код (C++): . . . DS3231 Clock(SDA, SCL); . . . void setup() { . . . Clock.begin(); . . . } Функции getHour() и getMinute() в библиотеке вовсе отсутствуют. Вместо этого, если нужны числовые значения даты и времени, есть функция getTime(), которая записывает значения в структуру Time. Для получения даты или времени в текстовом формате, в библиотеке есть функции getDateStr() и getTimeStr(). Т. е. в вашем случае, вместо int minute, hour; нужно объявить, например, переменную Time cur_time; и все вызовы функции ReadDS3231() заменить на: Код (C++): cur_time = Clock.getTime(); Так же, заменить minute и hour на cur_time.min и cur_time.hour ответственно. Либо, если не хотите заморачиваться, изменить функцию ReadDS3231(): Код (C++): void ReadDS3231() { cur_time = Clock.getTime(); minute = cur_time.min; hour = cur_time.hour; } PS Странно, что код вообще компилировался.
void ReadDS3231() //функция считывает в глобальные переменные minute и hour текущие значения { cur_time = Clock.getTime(); minute = cur_time.min; hour = cur_time.hour; } ошибка 75:error: 'cur_time' was not declared in this scope :75: error: 'class DS3231' has no member named 'getTime' Библиотека с официального сайта не компилировалась. Из кучи скачанных из инета подошла только выше указанная
Либо перед setup() добавьте строчку: Код (C++): Time cur_time; или в функции поправьте: Код (C++): Time cur_time = Clock.getTime(); Но, судя по тексту ошибки, Вы дали ссылку не на ту библиотеку. Название библиотек совпадают, а содержимое разное. Посмотрите примеры к библиотеки, которая установлена конкретно у Вас. Возможно упущены какие-то нюансы. Заодно убедитесь, что время в часах выставлено правильное. В исходном коде, при установки значений минут, значение секунд сбрасывается на "0". Может, пока выставляли минуты, секунды и сбились. Код (C++): if (currentdigit==1) // если меняем минуты { if (minute<=58) minute++; else minute=0; Clock.setMinute(minute);//Set the minute Clock.setSecond(0); }