класс титановый велосипед для delay без delay().
- Войдите на сайт для отправки комментариев
Пнд, 01/02/2016 - 22:33
класс титановый велосипед для delay без delay().
динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для delay без delay(). // динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями. class noDELAY { public: unsigned long previous; unsigned long interval; boolean s; boolean push; boolean push_tick; noDELAY() { previous = millis(); s = 0; push = 0; push_tick = 0; } void start() {s = 1;} void stop() {s = 0;} void read(unsigned long _interval) { interval = _interval; unsigned long current = millis(); push_tick = 0; if (s == 0) {previous = current;} if (current - previous > interval) {previous = current; push_tick = 1; push = !push; } } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // пример blink для двух светодиодов с использованием класс титановый велосипед для delay без delay(). #include "class_noDELAY.h" noDELAY nD_01; noDELAY nD_02; void setup () { pinMode(14, OUTPUT); // LED_01 digitalWrite(14, 1); pinMode(15, OUTPUT); // LED_02 digitalWrite(15, 1); nD_01.start(); nD_02.start(); } void loop() { nD_01.read(100); nD_02.read(900); digitalWrite(14, nD_01.push); digitalWrite(15, nD_02.push); }//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // спагетти примеров использования класса титановый велосипед для delay без delay(). #include "class_noDELAY.h" noDELAY nD_01; // объявление объекта класса noDELAY с именем nD_01. noDELAY nD_02; // объявление объекта класса noDELAY с именем nD_02. void setup () { pinMode(14, OUTPUT); // LED_01 digitalWrite(14, 1); pinMode(15, OUTPUT); // LED_02 digitalWrite(15, 1); nD_01.start(); // если требуется начать немедленно, можно сразу в setup стартовать. nD_02.start(); // если требуется начать немедленно, можно сразу в setup стартовать. } void loop() { //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // явное указание периода генерации. nD_01.read(100); nD_02.read(900); // неявное указание периода генерации посредством переменной. static unsigned long tt = 50; static unsigned long nn = 300; nD_01.read(tt); nD_02.read(nn); if (условие) {tt = 800; nn = 200;} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (условие) {nD_01.start(); nD_02.start();} // старт по условию. if (условие) {nD_01.stop(); nD_02.stop();} // стоп по условию. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // реализация blink: // по условию срабатывания push_tick == TRUE. if (nD_01.push_tick) {digitalWrite(14, !digitalRead(14));} if (nD_02.push_tick) {digitalWrite(15, !digitalRead(15));} // или // согласно логического состояния переменной push. digitalWrite(14, nD_01.push); digitalWrite(15, nD_02.push); //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ if (nD_01.push_tick) {код чего-то;} // что-то делать с частотой интервала генерации. if (nD_01.push) {код чего-то;} // что-то делать в течении интервала и не делать в течении следующего интервала. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // что-то сделать один раз по условию и по истечении времени интервала - генератор в одновибратор. if (условие) {nD_01.start();} if (nD_01.push_tick) {nD_01.stop(); код чего-то;} //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ }Хорошо, но на мой взгляд, не удобно. Не понятно зачем в цикле каждый раз делать read(100)
Надо бы так: Создаем объект, Указываем периодичность события, В цикле остается только
if(nD_01.push_tick) {код чего-то;}Хорошо, но на мой взгляд, не удобно. Не понятно зачем в цикле каждый раз делать read(100)
кому не удобно?
на самом деле это не read(100) , а read(n) , где n может измениться далее в коде.
т.е. read(100) является частным случаем read(n).
Надо бы так: Создаем объект, Указываем периодичность события, В цикле остается только
if(nD_01.push_tick) {код чего-то;}я не знаю как проверять актуальное значение nD_01.push_tick без read(100).
покажи как - сделаю.
выпилил переменную *.push как странную.
теперь класс генерит одно событие TRUE *.tick в течении одного цикла программы.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для delay без delay(). // динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями. #include <Arduino.h> class noDELAY { public: unsigned long previous; unsigned long interval; boolean s; boolean tick; noDELAY() { previous = millis(); s = 0; tick = 0; } void read(unsigned long _interval) { interval = _interval; unsigned long current = millis(); tick = 0; if (s == 0) {previous = current; } if (current - previous > interval) {previous = current; tick = 1;} } void start() {s = 1; } void stop() {s = 0; } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
возьми и сделай, если тебе нужно, что бы...
*кому не требуется жёсткий real time, тот поймёт почему в строке
if(current - previous > interval)написано ">", а не "==" .
Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
Вро де бы и здорово активировать прерывания по таймеру и далее инициировать события в зависимости от установленных интервалов. Но, как известно, обработчик прерывания должен быть максимально коротким и простым, дабы оставалось время на исполнение остальной программы. А если таких событий десяток и работают они то сетью Ethernet, то сетью построенной на nRF24, тогда как быть?
народ, все все титановые велосипеды(их будет есчё) являются производными примера Мигаем светодиодом без delay() - вы видите в примере хардкор и реалтайм? я - нет.
if(currentMillis - previousMillis > interval) {previousMillis = currentMillis;}не более.
народ, все все титановые велосипеды(их будет есчё) являются производными примера Мигаем светодиодом без delay() - вы видите в примере хардкор и реалтайм? я - нет.
if(currentMillis - previousMillis > interval) {previousMillis = currentMillis;}не более.
Все таки предложу свою реализацию, ТС - вы не против? Если пртив - удалю.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями. #include <Arduino.h> class noDELAY { private: unsigned long previous; unsigned long interval; boolean s; public: noDELAY() {s = false;} void start(unsigned long _interval) { interval = _interval; s = true; previous = millis(); } void stop() {s = false;} boolean tick() { unsigned long current = millis(); if (!s) { return false; } else if (current - previous > interval) { previous = current; return true; } else { return false; } } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ noDELAY nD_01; void setup() { pinMode(13, OUTPUT); nD_01.start(1000); } void loop() { if ( nD_01.tick () ) {digitalWrite(13,!digitalRead(13));} }Все таки предложу свою реализацию, ТС - вы не против? Если пртив - удалю.
ты точно уверен, что это именно твоя реализация, а не твоя редакция моего кода?
*ну...
boolean tick() нормальный хода,
if(!s) {returnfalse; }сломает current - previous > interval при старте т.к. current обновляется постоянно, а previous стоит.ну, не знаю - нужно смотреть ещё возможные тараканы.
Я на авторство не претендую. Идея полностью твоя, но мое виденье реализации :)
Помнишь в начале я написал: Надо бы так: Создаем объект, Указываем периодичность события, В цикле остается только
if(nD_01.push_tick) {код чего-то;}Тараканов можно изгнать, код сырой, прямо с колес, а под рукой ардуинки нет, что бы проверить.
Мне не нужно ! Ни разу :) Если честно, я вообще не понимаю зачем это...
Кстати, а почему именно '>' , а не '>=' ?
Мне не нужно ! Ни разу :) Если честно, я вообще не понимаю зачем это...
ок. люди делятся на два типа - те, кто не понимает и те, кто понимает.
Помнишь в начале я написал: Надо бы так: Создаем объект, Указываем периодичность события, В цикле остается только
if(nD_01.push_tick) {код чего-то;}помню - я ж не прогрммист, просто не знал, как сделать boolean tick()
Мне не нужно ! Ни разу :) Если честно, я вообще не понимаю зачем это...
Это для таких как я и еще хуже)))... Клапауций 322, благодарен за труд. Вы мне как-то посоветовали библиотеку Metro, а это, как я понимаю, более модифицированная ее версия?
Вы мне как-то посоветовали библиотеку Metro, а это, как я понимаю, более модифицированная ее версия?
практически то же самое, но для себя.
в Метро зачем-то myname.reset() - что там сбрасывать не знаю.
в Метро зачем-то myname.reset() - что там сбрасывать не знаю.
Я этой строчкой пользуюсь, к примеру, когда необходимо, чтобы какой то интервал сбросился, если, допустим, нажали кнопку для входа в меню дисплея, а на дисплее перед этим каждые 5 секунд менялась инфа всякая... Подозреваю, что это все можно сделать и другими путями, но я их пока не знаю.
Я этой строчкой пользуюсь, к примеру, когда необходимо, чтобы какой то интервал сбросился, если, допустим, нажали кнопку для входа в меню дисплея, а на дисплее перед этим каждые 5 секунд менялась инфа всякая... Подозреваю, что это все можно сделать и другими путями, но я их пока не знаю.
у меня это *.stop()
Хорошо, но на мой взгляд, не удобно. Не понятно зачем в цикле каждый раз делать read(100)
на самом деле это не read(100) , а read(n) , где n может измениться далее в коде.
т.е. read(100) является частным случаем read(n).
возвращаемся к тому, с чего начали - read(n) необходим для динамического изменения интервала.
иначе, придётся вызывать start(n) загромождая код if-фами вместо простого наличия read(n) в коде, плюс n у нас может измениться в то время когда генерация находится в состоянии stop() .
*вердикт - версия #7 считается актуальным релизом.
подключение кода класса как библиотеки #186
Хорошо, но на мой взгляд, не удобно. Не понятно зачем в цикле каждый раз делать read(100)
на самом деле это не read(100) , а read(n) , где n может измениться далее в коде.
т.е. read(100) является частным случаем read(n).
возвращаемся к тому, с чего начали - read(n) необходим для динамического изменения интервала.
иначе, придётся вызывать start(n) загромождая код if-фами вместо простого наличия read(n) в коде, плюс n у нас может измениться в то время когда генерация находится в состоянии stop() .
*вердикт - версия #7 считается актуальным релизом.
Да я и не настаиваю :) Просто read(n) нужен далеко не в каждой итерации loop, а только для изменения интервала, что легко реализуется добавлением соответствующего метода, например ChangeInterval(n).
Ладно все, я просто предложил альтернативный вариант, а дальше кто как хочет.
PS для подключения не обязательно использовать h-файл, можно просто код класса в начало скетча поставить.
Просто read(n) нужен далеко не в каждой итерации loop, а только для изменения интервала, что легко реализуется добавлением соответствующего метода, например ChangeInterval(n).
ну, я ещё напишу велосипед Change(n) - пусть делает TRUE, если изменилась n.
или, о чём это всё, если так или иначе, что то можно в классе сократить, но это что-то вылазит к код скетча.
*ок. а почему так ужасен вызов read(n) при каждом цикле программы? - мне кажется, что проверка Change(n) грозит большими накладными расходами, чем просто перезапись n.
PS для подключения не обязательно использовать h-файл, можно просто код класса в начало скетча поставить.
можно все библиотеки с код скетча слить.
минорное обновление:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для delay без delay(). // динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями. #include <Arduino.h> class noDELAY { public: unsigned long previous; unsigned long interval; boolean s; boolean tick; noDELAY() { previous = millis(); s = 0; tick = 0; } void stop() {s = 0; } void start() {s = 1; } void read(unsigned long _interval) { interval = _interval; unsigned long current = millis(); tick = 0; if (s == 0) {previous = current; } if (current - previous > interval) {previous = current; tick = 1;} } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Извините за глупый вопрос, но...
Почему в примере "blink без delay" проверка астанавливается на строке:
noDELAY nD_01;
пишет: noDELAY does not name a type
Почему в примере "blink без delay" проверка астанавливается на строке:
потому, что нужно внимательно читать тему:
#7 выпилил переменную *.push как странную.
поэтому пример для версии кода класса #26 будет выглядеть так:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // пример blink для двух светодиодов с использованием класс титановый велосипед для delay без delay(). #include "class_noDELAY.h" noDELAY nD_01; noDELAY nD_02; void setup () { pinMode(14, OUTPUT); // LED_01 digitalWrite(14, 1); pinMode(15, OUTPUT); // LED_02 digitalWrite(15, 1); nD_01.start(); nD_02.start(); } void loop() { nD_01.read(100); nD_02.read(900); if (nD_01.tick) {digitalWrite(14, !digitalRead(14));} if (nD_02.tick) {digitalWrite(15, !digitalRead(15));} }arduino-1.6.8
я буду логи читать и подключать класс как библиотеку?
#2
Так и сделано.
Так и сделано.
не ври.
А я как .txt сохранял.
теперь на этой строчке останавливается:
if (nD_02.tick) {digitalWrite(15, !digitalRead(15));}
и ошибка:
А я как .txt сохранял.
ещё один вопрос и ты идёшь нахуй.
сохранить в этой папке с именем class_noDELAY.h
Душевно.... но новобранцы не оценят. надо же любя....
Душевно.... но новобранцы не оценят. надо же любя....
а, никто и не набирает тут армию кретинов.
Клапауций 322, по #26
если не затруднит, со следующим обновлением оторматируйте текст программы с нормальными отступами, будь ласка. Так совсем структуру не вижу. спасибо
ок. по многочисленным просьбам ползателей форума - у кого отсутвует нормальный текстовый редактор и комбинация клавиш Ctrl+C, код будет дублироваться авторским картинко, где структура кода читается построчно.
ага , в ipad mini отсутствует кнопка ctrl. Ты изобрёл способ борьбы с начинающими лентяями на форуме. Картинками им выдавать ответы надо. Пусть руками работают. :)
минорное обновление:
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // класс титановый велосипед для delay без delay(). // динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями. #include <Arduino.h> class noDELAY { public: unsigned long previous; unsigned long interval; boolean s; boolean tick; noDELAY() { previous = micros(); // previous = millis(); s = 0; tick = 0; } void stop() {s = 0; } void start() {s = 1; } void read(unsigned long _interval) { interval = _interval; unsigned long current = micros(); tick = 0; // unsigned long current = millis(); tick = 0; if (s == 0) {previous = current; } if (current - previous > interval) {previous = current; tick = 1;} } }; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~Маленькая непонятка по плавному включению с использованием класса.
if (digitalRead(SW) == LOW && prog == 1) {
if (val < spd && timer3.tick ){
val++;
analogWrite(LED, val);
}
}
Работает только при удержании кнопки. Как сделать по однократному нажатию?
Маленькая непонятка по плавному включению с использованием класса.
Работает только при удержании кнопки. Как сделать по однократному нажатию?
Megawollt, я третий раз прошу прочитать описание класса, вникнуть в суть его работы и, только затем задавать вопросы, не относящиеся к использованию класса.
Я стараюсь, но пока не получается. Надеюсь на твою помощь в ответе
Я стараюсь, но пока не получается. Надеюсь на твою помощь в ответе
заведи переменную типа boolean равную 0, меняй эту переменную на 1 нажатием кнопки и на 0 при условии val == 255. по условию равенства этой переменной 1, запускай процесс увеличения val с использованием класса
Спасибо
Осталось непонятным зачем требуется именно "класс", когда вполне можно обходится типа таким макросом:
// ============= wait without delay ============ // // Простейший конечный автомат сначала исполняющий действие command и // затем ожидающий его повторения через interval тиков таймера по 1 миллисекунде. // В качестве команды может быть последовательность команд через ; // или прямой вызов функции! // интервалы можно задавать константно и переменными (выражениями). // Например (исполнение через 1 сек): // // @param uint32_t interval; [milliseconds] // @param void (*)(void) action; // #define everyMillis(interval, action) \ { \ static unsigned long t = 0UL; \ if( millis() - t > (interval) ) \ { \ { action; } \ t = millis(); \ } \ } // Использование, например прямо так (делать каждую секунду): everyMillis(1000, { pinOut(pinLed, 1-digitalRead(pinLed)); analogWrite(pwm12, analogRead(pin54)>>4); }); // .. или так (вызывать каждую секунду): everyMillis(1000, blink() ); // наборотный макрос "delay()" для выполнения кода ПОКА идет задержка: #define delayYield(interval, action) \ { \ static unsigned long t = millis(); \ while( !(millis() - t > (interval)) ) \ { action; } \ } // использование - аналогично (пока идет секундная пауза, делай это): delayYield(1000, { digitalWrite(pinLed, HIGH); uint16_t mySignal = analogRead(Analog1); everyMillis(100, { // тут ишо чего-нить, каждые 100мсек, не чаще, во время паузы .. :) }); });И по мне так очень удобно, из кода исчезают множественные проверки..
Осталось непонятным зачем требуется именно "класс", когда вполне можно обходится типа таким макросом:
осталось непонятным, почему я-радиомонтажник этим занимаюсь, а ты-программист - нет.
Наверное потому, что я неплохо знаю цену всему "классному" подходу и пользую его ровно там, где оно того стоит, не? :)
Наверное потому, что я неплохо знаю цену всему "классному" подходу и пользую его ровно там, где оно того стоит, не? :)
если бы знал, что не генерил бы быдлокод
12#define everyMillis(interval, action) \13{ \14staticunsignedlongt = 0UL; \15if( millis() - t > (interval) ) \16{ \17{ action; } \18t = millis(); \19} \20}А где тут генерится "быдлокод", покажешь? :)