Помогите сделать код без delay().
- Войдите на сайт для отправки комментариев
Сб, 09/06/2018 - 21:09
Здравствуйте.
Полгода назад сделал контролер для аквариума, где реализовано плавное включение
выключение света, открытие воздуха шаговым двигателем, управление инфракрасным пультом.
Еще планирую подключить датчик 18b20 ну и там еще чего-нибудь.
И все меня устраивает, кроме одного, что при плавном включение выключение света контролер больше нечего не делает.
Помогите избавится от delay().
В программирование ничего не понимаю, делал программу из того что находил в инете.
Здесь часть программы, где ардуино управляет светом.
#include <RTC.h>
RTC time;
int t1 = 10; // включение света
int m1=30; // Минуты включения
int t2 = 23; // выключение сета
int m2=10; // Минуты вылючения
int d; // Переменная в которую записываются текущий показатель часов
int m; // Переменная в которую записываются текущий показатель минут
int led = 5; //подключен к цифровому выводу 5
int i;
void setup(){
Serial.begin(9600);
pinMode(led, OUTPUT);
// инициализация модуля RTC
time.begin(RTC_DS3231); // на базе чипа DS3231 модуль подключается к аппаратным выводам I2C
// time.begin(RTC_DS1307); // на базе чипа DS1307 модуль подключается к аппаратным выводам I2C
// time.begin(RTC_DS1302,10,13,12); // на базе чипа DS1302, вывод RST, вывод CLK, вывод DAT доступны любые выводы
// запись даты и времени
// time.settime(0,14,9,13,03,18,2); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг
// time.settime(35,10,20); // 35 сек, 10 мин, 20 час, дату оставить без изменений
// time.settime(-1,-1,-1,31,12,15); // 31, декабря, 2015 года, время и день недели оставить без изменений
}
void loop(){
d=time.Hours ;
m=time.minutes;
// Передать время
Serial.println(time.gettime("d-m-Y, H:i:s, D"));
// Плавное включение
if ((time.Hours == 10) && (time.minutes == 00))
{
for (int i=0; i<=255; i++)
{
analogWrite(led, i);
if (i==255)
{
digitalWrite(led, HIGH);
}
delay(16000);
}
}
/////
// Защита от выключения эдектричества
else{
if (d <= t2 && d >= t1) {
if (d==t1 && m<m1) {goto label;}
if (d==t2 && m>m2) {goto label;}
digitalWrite(led, HIGH); // свет включен
Serial.println(" HIGH ");
}
else
{
label:
digitalWrite(led, LOW); // свет выключен
Serial.println(" LOW ");
}
}
/////
// Плавное выключение
if ((time.Hours == 22) && (time.minutes == 10))
{
for (int i=255; i>=0; i--)
{
analogWrite(led, i);
if (i==0)
{
digitalWrite(led, LOW);
}
delay(16000);
}
}
delay(1000);
}
Поищите так же "blink без delay" - должно подойти к вашей программе.
"blink без delay" у меня не получается срастить с плавным включением.
С таким подходом Вы от delay не избавитесь.
Нужно не вносить в программу изменея (так не получится), а полностью переписывать программу, опираясь на совершенно другую идеологию.
В общем, надо хорошо понимать, что делаешь и зачем. Иначе - никак.
У Вас четыре варианта:
1. Прокачать знания и начать что-то понимать
2. Найти в Интернете готовое решение
3. Заказать эту работу за деньги
4. Забить на это
Вариант сидеть в этой теме и ждать, что кто-то сжалится и подаст Христа ради почти бесперспективен.
Чтобы сделать неблокирующее гашение, надо:
1. Определиться с длительностью гашения и поделить на 256. Я тут вижу delay(1000) и цикл 255->0, так что далее считаю длительность равной 256с, из чего следует что перод (длительность шага) - одна секунда ровно. Но это вовсе необязательно, например можно погасить за 20с, тогда период 20000/256=78, за 5 минут, тогда 300000/256=1171.
2. Делается подпрограмма, которая крутит этот период. Это здесь принято называть конечным автоматом, или тем самым blink без delay(). Состоит из условия "если время минус прошлое время равно или больше периода", и внутри этого условия присвоение прошлое время=текущее, чтобы оно повторялось, каждый период.
Фсё! Далее останется только увеличивать/уменьшать нужную переменную, в вашей программе это i, в новой будет led_level. Мб с вариациями типа разрешить/запретить уменьшение/увеличение, такая переменная называется "флаг".
Ага. Без blink без delay() тут никак. Советую хороше разобратся с ним например на моргании светодиода типа 1сек горит одну сек нет. Показателем того, что разобрались можно считать что Вы легко и непренужденно находите место в коде, которое всегда выполняется раз в сек. В этом месте вставляете код вида i++;if(i==10){i=0;...} - код на месте в скобках будет выполнятся уже раз в 10 сек. Там можете понижать/повышать яркость или датчики опрашивать или делать любые действия которые надо делать раз в 10 сек. Аналогично формируются остальные периодические интервалы. Почему именно так советую - специфика такого кантроллера как у Вас в том, что таких интервалов надо много, а так их получать легко просто и понятно.
//В программирование ничего не понимаю, делал программу из того что находил в инете - так не получится, надо подучить основы хотябы.
А ты его, лодыря, загрузи, чтоб он в это время таки еще и немношко биткойны майнил.
Держи!
#include <RTC.h> RTC time; int t1 = 10; // включение света int m1=30; // Минуты включения int t2 = 23; // выключение сета int m2=10; // Минуты вылючения int d; // Переменная в которую записываются текущий показатель часов int m; // Переменная в которую записываются текущий показатель минут int led = 5; //подключен к цифровому выводу 5 byte i=0; boolean running = false; boolean stop = false; unsigned long timeR; void setup(){ Serial.begin(9600); pinMode(led, OUTPUT); timeR = millis(); // инициализация модуля RTC time.begin(RTC_DS3231); // на базе чипа DS3231 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1307); // на базе чипа DS1307 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1302,10,13,12); // на базе чипа DS1302, вывод RST, вывод CLK, вывод DAT доступны любые выводы // запись даты и времени // time.settime(0,14,9,13,03,18,2); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг // time.settime(35,10,20); // 35 сек, 10 мин, 20 час, дату оставить без изменений // time.settime(-1,-1,-1,31,12,15); // 31, декабря, 2015 года, время и день недели оставить без изменений } void loop(){ d=time.Hours ; m=time.minutes; // Передать время Serial.println(time.gettime("d-m-Y, H:i:s, D")); // Плавное включение if ((time.Hours == 10) && (time.minutes == 00)) running = true; if ((running)&&(millis()-timeR>=16000)) { i++; analogWrite(led, i); timeR = millis(); } if ((running)&&(i==255)) { digitalWrite(led, HIGH); running = false; i = 0; } // Плавное выключение if ((time.Hours == 22) && (time.minutes == 10)) stop = true; if ((stop)&&(millis()-timeR>=16000)) { i++; analogWrite(led, (255-i)); timeR = millis(); } if ((stop)&&(i==255)) { digitalWrite(led, LOW); stop = false; i = 0; } ///// // Защита от выключения эдектричества else{ if (d <= t2 && d >= t1) { if (d==t1 && m<m1) {goto label;} if (d==t2 && m>m2) {goto label;} digitalWrite(led, HIGH); // свет включен Serial.println(" HIGH "); } else { label: digitalWrite(led, LOW); // свет выключен Serial.println(" LOW "); } } delay(10); }Похоже встретились два "одиночества". ;))
/**/ //----------------------------------------------- typedef struct { byte min; byte second; } aaa; void save(aaa &v, unsigned long mill) { mill /= 1000; v.second = mill % 60; mill /= 60; v.min = mill % 60; } void print(aaa &v) { Serial.println(); Serial.print(v.min); Serial.print(":"); Serial.print(v.second); Serial.print(" "); }; int total(aaa &v) { return 60 * v.min + v.second; } /*сравнить вернуть 1 если v1>v2 / -1 если v1<v2 / 0 если v1==v2 */ int compare(aaa &v1, aaa &v2) { int a = total(v1); int b = total(v2); if (a > b) return 1; else if (a < b) return -1; else return 0; }; //--------------------------- aaa tON = {/*минута*/0,/*секунда*/3}; aaa tOFF = {/*минута*/0,/*секунда*/10}; //-----main()------------------- void setup() { Serial.begin(9600); } void loop() { aaa tNow; save(tNow, millis()); print(tNow); Serial.print(compare(tON, tNow)); Serial.print(" "); Serial.print(compare(tOFF, tNow)); Serial.print(" "); delay(1000); } /**/Держи!
#include <RTC.h> RTC time; int t1 = 10; // включение света int m1=30; // Минуты включения int t2 = 23; // выключение сета int m2=10; // Минуты вылючения int d; // Переменная в которую записываются текущий показатель часов int m; // Переменная в которую записываются текущий показатель минут int led = 5; //подключен к цифровому выводу 5 byte i=0; boolean running = false; boolean stop = false; unsigned long timeR; void setup(){ Serial.begin(9600); pinMode(led, OUTPUT); timeR = millis(); // инициализация модуля RTC time.begin(RTC_DS3231); // на базе чипа DS3231 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1307); // на базе чипа DS1307 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1302,10,13,12); // на базе чипа DS1302, вывод RST, вывод CLK, вывод DAT доступны любые выводы // запись даты и времени // time.settime(0,14,9,13,03,18,2); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг // time.settime(35,10,20); // 35 сек, 10 мин, 20 час, дату оставить без изменений // time.settime(-1,-1,-1,31,12,15); // 31, декабря, 2015 года, время и день недели оставить без изменений } void loop(){ d=time.Hours ; m=time.minutes; // Передать время Serial.println(time.gettime("d-m-Y, H:i:s, D")); // Плавное включение if ((time.Hours == 10) && (time.minutes == 00)) running = true; if ((running)&&(millis()-timeR>=16000)) { i++; analogWrite(led, i); timeR = millis(); } if ((running)&&(i==255)) { digitalWrite(led, HIGH); running = false; i = 0; } // Плавное выключение if ((time.Hours == 22) && (time.minutes == 10)) stop = true; if ((stop)&&(millis()-timeR>=16000)) { i++; analogWrite(led, (255-i)); timeR = millis(); } if ((stop)&&(i==255)) { digitalWrite(led, LOW); stop = false; i = 0; } ///// // Защита от выключения эдектричества else{ if (d <= t2 && d >= t1) { if (d==t1 && m<m1) {goto label;} if (d==t2 && m>m2) {goto label;} digitalWrite(led, HIGH); // свет включен Serial.println(" HIGH "); } else { label: digitalWrite(led, LOW); // свет выключен Serial.println(" LOW "); } } delay(10); }Код компилируется, но свет не зажигается.
Давайте разбираться. Забыл убрать некую защиту от выключения электричества.
#define PinLed 5 //подключен к цифровому выводу 5 #include <RTC.h> RTC time; byte tON = 10; // включение света byte mON = 30; // Минуты включения byte tOFF = 23; // выключение сета byte mOFF = 10; // Минуты вылючения byte d; // Переменная в которую записываются текущий показатель часов byte m; // Переменная в которую записываются текущий показатель минут byte iPwm = 0; boolean running = false; boolean stop = false; unsigned long timeR; void setup(){ Serial.begin(9600); pinMode(PinLed, OUTPUT); timeR = millis(); // инициализация модуля RTC time.begin(RTC_DS3231); // на базе чипа DS3231 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1307); // на базе чипа DS1307 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1302,10,13,12); // на базе чипа DS1302, вывод RST, вывод CLK, вывод DAT доступны любые выводы // запись даты и времени // time.settime(0,14,9,13,03,18,2); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг // time.settime(35,10,20); // 35 сек, 10 мин, 20 час, дату оставить без изменений // time.settime(-1,-1,-1,31,12,15); // 31, декабря, 2015 года, время и день недели оставить без изменений } void loop(){ d=time.Hours ; m=time.minutes; // Передать время Serial.println(time.gettime("d-m-Y, H:i:s, D")); // Плавное включение if ((time.Hours == tON) && (time.minutes == mON)) running = true; if ((running)&&(millis()-timeR>=16000)) { iPwm++; analogWrite(PinLed, iPwm); timeR = millis(); } if ((running)&&(iPwm==255)) { digitalWrite(PinLed, HIGH); running = false; iPwm = 0; } // Плавное выключение if ((time.Hours == tOFF) && (time.minutes == mOFF)) stop = true; if ((stop)&&(millis()-timeR>=16000)) { iPwm++; analogWrite(PinLed, (255-iPwm)); timeR = millis(); } if ((stop)&&(iPwm==255)) { digitalWrite(PinLed, LOW); stop = false; iPwm = 0; } }Сейчас должен включатся и выключатся в заданное время. Защиту придется писать заново.
Давайте разбираться. Забыл убрать некую защиту от выключения электричества.
#define PinLed 5 //подключен к цифровому выводу 5 #include <RTC.h> RTC time; byte tON = 10; // включение света byte mON = 30; // Минуты включения byte tOFF = 23; // выключение сета byte mOFF = 10; // Минуты вылючения byte d; // Переменная в которую записываются текущий показатель часов byte m; // Переменная в которую записываются текущий показатель минут byte iPwm = 0; boolean running = false; boolean stop = false; unsigned long timeR; void setup(){ Serial.begin(9600); pinMode(PinLed, OUTPUT); timeR = millis(); // инициализация модуля RTC time.begin(RTC_DS3231); // на базе чипа DS3231 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1307); // на базе чипа DS1307 модуль подключается к аппаратным выводам I2C // time.begin(RTC_DS1302,10,13,12); // на базе чипа DS1302, вывод RST, вывод CLK, вывод DAT доступны любые выводы // запись даты и времени // time.settime(0,14,9,13,03,18,2); // 0 сек, 17 мин, 15 час, 1, октября, 2015 года, четверг // time.settime(35,10,20); // 35 сек, 10 мин, 20 час, дату оставить без изменений // time.settime(-1,-1,-1,31,12,15); // 31, декабря, 2015 года, время и день недели оставить без изменений } void loop(){ d=time.Hours ; m=time.minutes; // Передать время Serial.println(time.gettime("d-m-Y, H:i:s, D")); // Плавное включение if ((time.Hours == tON) && (time.minutes == mON)) running = true; if ((running)&&(millis()-timeR>=16000)) { iPwm++; analogWrite(PinLed, iPwm); timeR = millis(); } if ((running)&&(iPwm==255)) { digitalWrite(PinLed, HIGH); running = false; iPwm = 0; } // Плавное выключение if ((time.Hours == tOFF) && (time.minutes == mOFF)) stop = true; if ((stop)&&(millis()-timeR>=16000)) { iPwm++; analogWrite(PinLed, (255-iPwm)); timeR = millis(); } if ((stop)&&(iPwm==255)) { digitalWrite(PinLed, LOW); stop = false; iPwm = 0; } }Сейчас должен включатся и выключатся в заданное время. Защиту придется писать заново.
Да не осуждают они вас, а пытаются наоборот научить. Я просто дал вам возможность это сделать на примере.