класс титановый велосипед для delay без delay().
- Войдите на сайт для отправки комментариев
Пнд, 01/02/2016 - 22:33
класс титановый велосипед для delay без delay().
динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для delay без delay().
03
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
04
05
class
noDELAY {
06
07
public
:
08
unsigned
long
previous;
09
unsigned
long
interval;
10
boolean s;
11
boolean push;
12
boolean push_tick;
13
14
noDELAY() {
15
previous = millis();
16
s = 0;
17
push = 0;
18
push_tick = 0;
19
}
20
21
void
start() {s = 1;}
22
void
stop() {s = 0;}
23
void
read(unsigned
long
_interval) {
24
interval = _interval;
25
unsigned
long
current = millis();
26
push_tick = 0;
27
if
(s == 0) {previous = current;}
28
if
(current - previous > interval) {previous = current;
29
push_tick = 1;
30
push = !push;
31
}
32
}
33
34
};
35
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// пример blink для двух светодиодов с использованием класс титановый велосипед для delay без delay().
03
04
#include "class_noDELAY.h"
05
06
noDELAY nD_01;
07
noDELAY nD_02;
08
09
void
setup
() {
10
11
pinMode(14, OUTPUT);
// LED_01
12
digitalWrite(14, 1);
13
pinMode(15, OUTPUT);
// LED_02
14
digitalWrite(15, 1);
15
16
nD_01.start();
17
nD_02.start();
18
19
}
20
21
void
loop
() {
22
23
nD_01.read(100);
24
nD_02.read(900);
25
26
digitalWrite(14, nD_01.push);
27
digitalWrite(15, nD_02.push);
28
29
}
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// спагетти примеров использования класса титановый велосипед для delay без delay().
03
04
#include "class_noDELAY.h"
05
06
noDELAY nD_01;
// объявление объекта класса noDELAY с именем nD_01.
07
noDELAY nD_02;
// объявление объекта класса noDELAY с именем nD_02.
08
09
void
setup
() {
10
11
pinMode(14, OUTPUT);
// LED_01
12
digitalWrite(14, 1);
13
pinMode(15, OUTPUT);
// LED_02
14
digitalWrite(15, 1);
15
16
nD_01.start();
// если требуется начать немедленно, можно сразу в setup стартовать.
17
nD_02.start();
// если требуется начать немедленно, можно сразу в setup стартовать.
18
19
}
20
21
void
loop
() {
22
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
23
// явное указание периода генерации.
24
nD_01.read(100);
25
nD_02.read(900);
26
27
// неявное указание периода генерации посредством переменной.
28
static
unsigned
long
tt = 50;
29
static
unsigned
long
nn = 300;
30
nD_01.read(tt);
31
nD_02.read(nn);
32
if
(условие) {tt = 800; nn = 200;}
33
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
34
if
(условие) {nD_01.start(); nD_02.start();}
// старт по условию.
35
if
(условие) {nD_01.stop(); nD_02.stop();}
// стоп по условию.
36
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
37
// реализация blink:
38
// по условию срабатывания push_tick == TRUE.
39
if
(nD_01.push_tick) {digitalWrite(14, !digitalRead(14));}
40
if
(nD_02.push_tick) {digitalWrite(15, !digitalRead(15));}
41
// или
42
// согласно логического состояния переменной push.
43
digitalWrite(14, nD_01.push);
44
digitalWrite(15, nD_02.push);
45
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
46
if
(nD_01.push_tick) {код чего-то;}
// что-то делать с частотой интервала генерации.
47
if
(nD_01.push) {код чего-то;}
// что-то делать в течении интервала и не делать в течении следующего интервала.
48
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
49
// что-то сделать один раз по условию и по истечении времени интервала - генератор в одновибратор.
50
if
(условие) {nD_01.start();}
51
if
(nD_01.push_tick) {nD_01.stop(); код чего-то;}
52
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
53
}
Хорошо, но на мой взгляд, не удобно. Не понятно зачем в цикле каждый раз делать 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 в течении одного цикла программы.
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для delay без delay().
03
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
04
05
#include <Arduino.h>
06
07
class
noDELAY {
08
09
public
:
10
unsigned
long
previous;
11
unsigned
long
interval;
12
boolean s;
13
boolean tick;
14
15
noDELAY() {
16
previous = millis();
17
s = 0;
18
tick = 0;
19
}
20
21
void
read(unsigned
long
_interval) {
22
interval = _interval;
23
unsigned
long
current = millis();
24
tick = 0;
25
if
(s == 0) {previous = current; }
26
if
(current - previous > interval) {previous = current; tick = 1;}
27
}
28
29
void
start() {s = 1; }
30
void
stop() {s = 0; }
31
32
};
33
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
возьми и сделай, если тебе нужно, что бы...
*кому не требуется жёсткий real time, тот поймёт почему в строке
if
(current - previous > interval)
написано ">", а не "==" .
Это нужно вешать на прерывания, что бы инициация событий возникала по истечению периода, а не "удалять гладны автогеном" :) Вот тогда будет "титановый".
Вро де бы и здорово активировать прерывания по таймеру и далее инициировать события в зависимости от установленных интервалов. Но, как известно, обработчик прерывания должен быть максимально коротким и простым, дабы оставалось время на исполнение остальной программы. А если таких событий десяток и работают они то сетью Ethernet, то сетью построенной на nRF24, тогда как быть?
народ, все все титановые велосипеды(их будет есчё) являются производными примера Мигаем светодиодом без delay() - вы видите в примере хардкор и реалтайм? я - нет.
1
if
(currentMillis - previousMillis > interval) {previousMillis = currentMillis;}
не более.
народ, все все титановые велосипеды(их будет есчё) являются производными примера Мигаем светодиодом без delay() - вы видите в примере хардкор и реалтайм? я - нет.
1
if
(currentMillis - previousMillis > interval) {previousMillis = currentMillis;}
не более.
Все таки предложу свою реализацию, ТС - вы не против? Если пртив - удалю.
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
03
#include <Arduino.h>
04
05
class
noDELAY
06
{
07
private
:
08
unsigned
long
previous;
09
unsigned
long
interval;
10
boolean s;
11
12
public
:
13
noDELAY() {s =
false
;}
14
15
void
start(unsigned
long
_interval)
16
{
17
interval = _interval;
18
s =
true
;
19
previous = millis();
20
}
21
void
stop() {s =
false
;}
22
23
boolean tick()
24
{
25
unsigned
long
current = millis();
26
if
(!s) {
return
false
; }
27
else
if
(current - previous > interval)
28
{
29
previous = current;
30
return
true
;
31
}
32
else
{
return
false
; }
33
}
34
};
35
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
36
noDELAY nD_01;
37
38
void
setup
()
39
{
40
pinMode(13, OUTPUT);
41
nD_01.start(1000);
42
}
43
44
void
loop
()
45
{
46
if
( nD_01.tick () ) {digitalWrite(13,!digitalRead(13));}
47
}
Все таки предложу свою реализацию, ТС - вы не против? Если пртив - удалю.
ты точно уверен, что это именно твоя реализация, а не твоя редакция моего кода?
*ну...
boolean tick() нормальный ход
а,
if
(!s) {
return
false
; }
сломает 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-файл, можно просто код класса в начало скетча поставить.
можно все библиотеки с код скетча слить.
минорное обновление:
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для delay без delay().
03
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
04
05
#include <Arduino.h>
06
07
class
noDELAY {
08
09
public
:
10
unsigned
long
previous;
11
unsigned
long
interval;
12
boolean s;
13
boolean tick;
14
15
noDELAY() {
16
previous = millis();
17
s = 0;
18
tick = 0;
19
}
20
21
void
stop() {s = 0; }
22
void
start() {s = 1; }
23
24
void
read(unsigned
long
_interval) {
25
interval = _interval;
26
unsigned
long
current = millis(); tick = 0;
27
if
(s == 0) {previous = current; }
28
if
(current - previous > interval) {previous = current; tick = 1;}
29
}
30
31
};
32
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Извините за глупый вопрос, но...
Почему в примере "blink без delay" проверка астанавливается на строке:
noDELAY nD_01;
пишет: noDELAY does not name a type
Почему в примере "blink без delay" проверка астанавливается на строке:
потому, что нужно внимательно читать тему:
#7 выпилил переменную *.push как странную.
поэтому пример для версии кода класса #26 будет выглядеть так:
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// пример blink для двух светодиодов с использованием класс титановый велосипед для delay без delay().
03
04
#include "class_noDELAY.h"
05
06
noDELAY nD_01;
07
noDELAY nD_02;
08
09
void
setup
() {
10
11
pinMode(14, OUTPUT);
// LED_01
12
digitalWrite(14, 1);
13
pinMode(15, OUTPUT);
// LED_02
14
digitalWrite(15, 1);
15
16
nD_01.start();
17
nD_02.start();
18
19
}
20
21
void
loop
() {
22
23
nD_01.read(100);
24
nD_02.read(900);
25
26
if
(nD_01.tick) {digitalWrite(14, !digitalRead(14));}
27
if
(nD_02.tick) {digitalWrite(15, !digitalRead(15));}
28
29
}
Скетч использует 1 072 байт (17%) памяти устройства. Всего доступно 6 144 байт.
Глобальные переменные используют 29 байт (1%) динамической памяти, оставляя 2 019 байт для локальных переменных. Максимум: 2 048 байт.
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. Ты изобрёл способ борьбы с начинающими лентяями на форуме. Картинками им выдавать ответы надо. Пусть руками работают. :)
минорное обновление:
01
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
02
// класс титановый велосипед для delay без delay().
03
// динамически управляемая генерация событий с динамически изменяемым интервалом времени между событиями.
04
05
#include <Arduino.h>
06
07
class
noDELAY {
08
09
public
:
10
unsigned
long
previous;
11
unsigned
long
interval;
12
boolean s;
13
boolean tick;
14
15
noDELAY() {
16
previous = micros();
17
// previous = millis();
18
s = 0;
19
tick = 0;
20
}
21
22
void
stop() {s = 0; }
23
void
start() {s = 1; }
24
25
void
read(unsigned
long
_interval) {
26
interval = _interval;
27
unsigned
long
current = micros(); tick = 0;
28
// unsigned long current = millis(); tick = 0;
29
if
(s == 0) {previous = current; }
30
if
(current - previous > interval) {previous = current; tick = 1;}
31
}
32
33
};
34
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Маленькая непонятка по плавному включению с использованием класса.
if (digitalRead(SW) == LOW && prog == 1) {
if (val < spd && timer3.tick ){
val++;
analogWrite(LED, val);
}
}
Работает только при удержании кнопки. Как сделать по однократному нажатию?
Маленькая непонятка по плавному включению с использованием класса.
Работает только при удержании кнопки. Как сделать по однократному нажатию?
Megawollt, я третий раз прошу прочитать описание класса, вникнуть в суть его работы и, только затем задавать вопросы, не относящиеся к использованию класса.
Я стараюсь, но пока не получается. Надеюсь на твою помощь в ответе
Я стараюсь, но пока не получается. Надеюсь на твою помощь в ответе
заведи переменную типа boolean равную 0, меняй эту переменную на 1 нажатием кнопки и на 0 при условии val == 255. по условию равенства этой переменной 1, запускай процесс увеличения val с использованием класса
Спасибо
Осталось непонятным зачем требуется именно "класс", когда вполне можно обходится типа таким макросом:
01
// ============= wait without delay ============ //
02
// Простейший конечный автомат сначала исполняющий действие command и
03
// затем ожидающий его повторения через interval тиков таймера по 1 миллисекунде.
04
// В качестве команды может быть последовательность команд через ;
05
// или прямой вызов функции!
06
// интервалы можно задавать константно и переменными (выражениями).
07
// Например (исполнение через 1 сек):
08
//
09
// @param uint32_t interval; [milliseconds]
10
// @param void (*)(void) action;
11
//
12
#define everyMillis(interval, action) \
13
{ \
14
static
unsigned
long
t = 0UL; \
15
if
( millis() - t > (interval) ) \
16
{ \
17
{ action; } \
18
t = millis(); \
19
} \
20
}
21
22
// Использование, например прямо так (делать каждую секунду):
23
everyMillis(1000,
24
{
25
pinOut(pinLed, 1-digitalRead(pinLed));
26
analogWrite(pwm12, analogRead(pin54)>>4);
27
});
28
29
// .. или так (вызывать каждую секунду):
30
everyMillis(1000, blink() );
31
32
// наборотный макрос "delay()" для выполнения кода ПОКА идет задержка:
33
#define delayYield(interval, action) \
34
{ \
35
static
unsigned
long
t = millis(); \
36
while
( !(millis() - t > (interval)) ) \
37
{ action; } \
38
}
39
40
// использование - аналогично (пока идет секундная пауза, делай это):
41
delayYield(1000, {
42
digitalWrite(pinLed, HIGH);
43
uint16_t mySignal = analogRead(Analog1);
44
everyMillis(100, {
45
// тут ишо чего-нить, каждые 100мсек, не чаще, во время паузы .. :)
46
});
47
});
И по мне так очень удобно, из кода исчезают множественные проверки..
Осталось непонятным зачем требуется именно "класс", когда вполне можно обходится типа таким макросом:
осталось непонятным, почему я-радиомонтажник этим занимаюсь, а ты-программист - нет.
Наверное потому, что я неплохо знаю цену всему "классному" подходу и пользую его ровно там, где оно того стоит, не? :)
Наверное потому, что я неплохо знаю цену всему "классному" подходу и пользую его ровно там, где оно того стоит, не? :)
если бы знал, что не генерил бы быдлокод
12
#define everyMillis(interval, action) \
13
{ \
14
static
unsigned
long
t = 0UL; \
15
if
( millis() - t > (interval) ) \
16
{ \
17
{ action; } \
18
t = millis(); \
19
} \
20
}
А где тут генерится "быдлокод", покажешь? :)