Список таймеров v2.0

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Много таймеров из одного

Основная задача, стоящая перед горе-программистом AVR это не строгий математический анализ каких-нить бестолковых данных, не быстрое преобразование Фурье и даже не унылое мигание светлодиодиком. Основная задача, занимающая 80% программы - измерение временных интервалов. Чаще всего требуется узнать, скока времени прошло перед/после какого-нить события, чтобы не пропустить и вовремя откликнуться на него. Кто-то (90% новичков) жизни своей не мыслят без функции delay(), кто-то постоянно теребонькает несчастную millis(), зачастую, делая это неправильно и со священным ужасом ожидая страшного переполнения. Сложность в том, что временных интервалов по ходу программы требуется много, часто и, как правило, разных. Например, время конверсии даччика DS18B20 при максимальном 12-битовом разрешении составляет 750 миллисекунд, и раньше, чем вычислится температура опрашивать снова его бессмысленно. Для других даччиков время опроса будет совершенно другое, и временной интервал для него, соотвецтвенно - тоже. На экран информацию чаще 1 раза в 50 миллисекунд выводить тоже неприлично, только лишняя трата ресурсов, нервов и самого экранчика, значит опять надо где-то хранить время, когда вывод осуществлялся последний раз, чтоб не обращаться к нему чаще положенного. Везде, куда не посмотришь - время, время и время...

Кто-то, не мудрствуя лукаво, использует для своих целей delay() и не парится, даже не понимая, что процессор во время выполнения этой функции просто висит в холостом цикле, не делая ничего полезного, и не способен исполнять что-то иное (на самом деле способен, канеш, но для новичков это тайна). В некоторых задачах, будь то простейший Blink или управление светлодиодной лентой это не критично, но если delay() используется в программе управления газовой горелкой, тут впору эвакуировать из дома родных и близких (и кота) на время эксплуатации такой горелки.

Более продвинутые открыли для себя функцию millis() и поглядывают/поплевывают на делейщиков с высоты своего воображаемого Олимпа как исполненные благодати Свидетели Переполнения. И пестрят их программы чуть более чем полностью конструкциями вида

if (millis()-lastmillis > myinterval) dosomething();

а то и

if (lastmillis+myinterval>millis()) dosomething();

но последние, обычно, к исходу 49-х суток взрываются вместе с переполнившимся millis-om() и угрозы больше не представляют.

delay() похож на дубину, которой нерадивый пользователь со всего маху шарашит бедный процессор по голове, после чего ему становится очень трудно стоять без сознания и он валяется в отключке некоторое заданное количество времени. Естественно, ничего другого он делать в этом состоянии не способен.

millis() в этом отношении гораздо гуманнее. Он похож на хозяина раба, который вручил ему наручные часы, и строго настрого наказал следить за временем, если не хочется получить дубиной по башке, как в прошлый раз. И вот человечек, выполняя свою нехитрую работу, всё время пялится на часы, чтоб узнать не прошло ли достаточно времени, чтоб включить/выключить что то важное. Иначе, не уследишь/забудешь и улетишь вабнимку с газовым котлом Марс заселять вместе с родными и близкими (и котом), а жалка. Такое можно, канеш, потерпеть, если временной интервал один, но как только их становится несколько, да еще и друг от друга зависящих, выполнение задания превращается в атнюдь не тривиальную задачу (мошт, лучше дубиной, а?).

То что предлагаю я, можно назвать будильником. Человек заводит себе несколько будильников на разное время и спокойно занимается своими делами. По мере срабатывания каждого, можно ненадолго отвлечься, включить/выключить то что нужно/ненужно и спокойно продолжить заниматься своими делами дальше. Если действие было однократное, будильник можно отключить, а если совсем-совсем однократное - то и выбросить. Если действие периодическое, а так чаще всего и бывает, ничего делать не нужно, через ранее заданный интервал будильник сам по себе сработает снова.

 

 

кого заинтересовало продолжение -> https://github.com/DetSimen/Arduino_TimerList

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, а где Consts.h ? Ругаеццо, шо ево нету!

А если include выбросить, то не ругаеццо :)

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Пакавырялся. Замечания надо?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

include Const.h можно безболезненно удалить. 

Замечания от Вас приму с искренней благодарностью, даже если Вы меня в пух и прах разнесете. Я свой уровень +1 см над плинтусом знаю. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Const.h убрал, спасибо. 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Ну, дед, очень не хватает примера или там хоть какой документации. Я вот сразу кинулся собственный лист создавать, а она у Вас только свой лист обслуживает.

А так, я пока не сильно много ковырялся, но первое. что в глаза бросилось - неверное условие в строке №182 (если я где случано номера строк не нарушил) файла TTimerList.h. Из-за него невозможно создать максимальное заявленное количество таймеров, а можно только на 1 меньше. Вот пример

#include "TTimerList.h"

void loop(void) {}

void setup(void) {
	Serial.begin(57600);
	for (int i = 0; i < MAXTIMERSCOUNT; i++) {
		Serial.print("Timer[");
		Serial.print(i);
		Serial.print("] - ");
		Serial.println(TimerList.Add(500, loop) != INVALID_HANDLE ? "Okay" : "Failed");
	}
}

//	РЕЗУЛЬТАТ
//
//	Timer[0] - Okay
//	Timer[1] - Okay
//	Timer[2] - Okay
//	Timer[3] - Okay
//	Timer[4] - Okay
//	Timer[5] - Okay
//	Timer[6] - Okay
//	Timer[7] - Okay
//	Timer[8] - Okay
//	Timer[9] - Failed

Видите, девять создал, а десятый - никак. Так и должно быть, посмотрите на условие. А память-то на все 10 хапнул :)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Cобственный лист создать нельзя, класс должен быть статическим, иначе аппаратный таймер не будет знать, что вызывать при срабатывании. Наерна?

Строку 182 поправил. Идиот я, естессна, чо с мня взять. :-)  Спасибо.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Документацию как-нить, напишу, пока на больничном. Протрезветь бы к завтрему. :-)

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А хто и за што мня в программирование перекинул? 

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

DetSimen пишет:
Cобственный лист создать нельзя, класс должен быть статическим

Сейчас как раз и можно

#include <TTimerList.h>
void setup() {
  TTimerList list1(2);
  TTimerList list2(list1);
}
void loop() {
}

Чего бы его в синглтон не обернуть

class MyClass {
public:
	static MyClass* instance() {
		static MyClass one(10);
		return &one;
	}
protected:
	MyClass(size_t a){}
	MyClass(const MyClass& org){}
};

 

bwn
Онлайн
Зарегистрирован: 25.08.2014

DetSimen пишет:

А хто и за што мня в программирование перекинул? 

Не я, я ток в песочницу умею.

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

А я никуда не умею :(

Алексей. это читерство! :)))))

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Дед, а вот  строке №33 TTimerList.cpp заводится, кроме всего прочего, ещё и "Set OC0B on Compare Match, clear OC0B at BOTTOM", а потом нигде не используется. На это есть какие-то соображения или просто от чего-то прежнего осталось?

Алексей.
Алексей. аватар
Offline
Зарегистрирован: 02.02.2018

ЕвгенийП пишет:

А я никуда не умею :(

Алексей. это читерство! :)))))

Просто реакция такая, как вредная привычка. Организм, измученный аудитом, иногда всякую мерзость норовит выкинуть ;)

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

Надо попробовать

-NMi-
Offline
Зарегистрирован: 20.08.2018

DetSimen пишет:

Cобственный лист создать нельзя, класс должен быть статическим, иначе аппаратный таймер не будет знать, что вызывать при срабатывании. Наерна?

Строку 182 поправил. Идиот я, естессна, чо с мня взять. :-)  Спасибо.

Уотт те делать нефиг... Я делаю флаговые битовые поля для калиброванных интервалов времени, допустим, под 18в20 в 750 мск и под дисплей 1/2 секунды. Тупо занимаюсь "своими" делами и посматриваю на флаги и по мере их поступления обрабатываю или "сплю". Делеи вООбще никогда не использовал от слова совсем. Тема, канеш, классная, но новички нипаймут... к сожалению.................)))

xDriver
xDriver аватар
Онлайн
Зарегистрирован: 14.08.2015

у мине пару замечаний :)

1) я так понимаю компиляция под другие чипы вывалится с ошибкой. ну например, ЕСП не знает что такое SREG.

2) в примерах каша с ledState.

 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

xDriver пишет:

у мине пару замечаний :)

1) я так понимаю компиляция под другие чипы вывалится с ошибкой. ну например, ЕСП не знает что такое SREG.

Да, проверено (и используется мной) только под Atmega8, 168, 328 и 2560

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Дед, а вот  строке №33 TTimerList.cpp заводится, кроме всего прочего, ещё и "Set OC0B on Compare Match, clear OC0B at BOTTOM", а потом нигде не используется. На это есть какие-то соображения или просто от чего-то прежнего осталось?

с аппаратными таймерами разбирался ровно два года назад,  с тех пор оставил как есть, думаю, работает и ладно. Сегодня-завтра переделаю по правильному.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Алексей. пишет:

Чего бы его в синглтон не обернуть

Столь далеко мои знания лжывого С++ не простираюца.  Я вообще не программист и никада на него не учился, и в сортах этих ваших богомерзких  сиглтонов не разбираюсь. :)  Если сообщество подскажет как - я сделаю.  

Только надо понять а надо ли?  Никому же не приходит в голову второй объект Serial создавать вручную? Или он тоже синглтоном сделан? 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

xDriver пишет:

2) в примерах каша с ledState.

Благодарю, поправил. 

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Дед, а вот  строке №33 TTimerList.cpp заводится, кроме всего прочего, ещё и "Set OC0B on Compare Match, clear OC0B at BOTTOM", а потом нигде не используется. На это есть какие-то соображения или просто от чего-то прежнего осталось?

посмотрел, не вижу ничего про OC0B

#elif defined(__AVR_ATmega328P__)
void TTimerList::Init()
{
	ATOMIC_BLOCK(ATOMIC_RESTORESTATE) {
		TCCR0A = TCCR0A & 0b11111100;  // Таймер в режиме Normal
		OCR0A = TIMER0_ONE_MS;		// загрузим регистр совпадения
		TIMSK0 |= 0x3;			// установить OCIE0A и TOIE0, разрешим совпадение А и переполнение
		TIFR0 |= 0x2;			// очистим флаг OCF0A если до этого он был установлен, ждём следущего совпадения
	}
}

 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

-NMi- пишет:

DetSimen пишет:

Cобственный лист создать нельзя, класс должен быть статическим, иначе аппаратный таймер не будет знать, что вызывать при срабатывании. Наерна?

Строку 182 поправил. Идиот я, естессна, чо с мня взять. :-)  Спасибо.

Уотт те делать нефиг... Я делаю флаговые битовые поля для калиброванных интервалов времени, допустим, под 18в20 в 750 мск и под дисплей 1/2 секунды. Тупо занимаюсь "своими" делами и посматриваю на флаги и по мере их поступления обрабатываю или "сплю". Делеи вООбще никогда не использовал от слова совсем. Тема, канеш, классная, но новички нипаймут... к сожалению.................)))

с чего это, понятно жеж что использовать в написании кода без блокирующих функций

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

DetSimen пишет:

посмотрел, не вижу ничего про OC0B

Это мне уже к вечеру поплохело.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

:) 

xDriver
xDriver аватар
Онлайн
Зарегистрирован: 14.08.2015

DetSimen пишет:

xDriver пишет:

2) в примерах каша с ledState.

Благодарю, поправил. 

деда !

не до конца поправил ! (3,5 строка)

void tmrGreenLed(void){
   static bool ledState=true;          	// состояние светодиода
   digitalWrite(greenLedPin, state); // вывести состояние в светодиод !!!!

   TimerList.setNewInterval(hgreenLed, state ? 200 : 4800); // !!!!

   ledState = !ledState;			// инвертировать состояние
}

и в первом примере тоже.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

xDriver пишет:

не до конца поправил ! (3,5 строка)

ну дак я еще ж и слепой. щас поправлю, канеш

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

а вот интересно, можно ли использовать таймер в частотомере для задания интервала измерения?

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

этот - нет,  аппаратный можно. 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

DetSimen пишет:

этот - нет,  аппаратный можно. 

Дак про аппаратный это понятно )))
 

-NMi-
Offline
Зарегистрирован: 20.08.2018

ua6em пишет:

с чего это, понятно жеж что использовать в написании кода без блокирующих функций

С того это. Вот смотри - используй ЛЮБОЙ таймер так, как тебе нужно, хоть ШИМ. Прикрути к нему прерывание и считай себе на здоровье любые интервалы и одновременно ШИМи. И никаких делаев в коде от слова совсем.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

За очередь сапщений v2.0 расказывать?

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

А то!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Я не верю, Евгений Петрович, что Вы ляпов больше не нашли. 

А про очередь, завтра выкладу. 

sadman41
Offline
Зарегистрирован: 19.10.2016

Это штоп ты сразу в запой не ушел...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Дак я и так в запое. 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

DetSimen пишет:
Я не верю, Евгений Петрович, что Вы ляпов больше не нашли.
Точно не нашёл. Правда? и не искал, день был дурной и тяжёлый, а сейчас уже башка на стол валится, только троллить кого-нибудь могу - не до ляпов :(

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

DetSimen пишет:

За очередь сапщений v2.0 расказывать?

Сорри, пока некада, до выходных по коновалам брожу...

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Правда, в нашей стране, если денег нет - то ты самый здоровый человек на свете. А если есть - то больной пока деньги не кончуцца, потом см. п.1. 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Отставить пессимизм! Выздоравливайте!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

ЕвгенийП пишет:

Отставить пессимизм! Выздоравливайте!

Самому жаль, но не смогу. :-)  Вы, кста, можете называть меня на ты, без церемоний, буду только рад. 

ЕвгенийП
ЕвгенийП аватар
Онлайн
Зарегистрирован: 25.05.2015

Это не церемонии. У меня наоборот "на ты" - это церемонии. Так я зову только членов своей семьи (включая кота) и ближайших друзей - 2-3 человека. Иногда в сети, я пытаюсь создать некоего аватара (типа известного Вам аспера), который чем-то от меня отличается, в частности "на ты" общается, но не выдерживаю долго.

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

Я могу быть Вашим сетевым котом. Матвеичем.  :-)

sadman41
Offline
Зарегистрирован: 19.10.2016

А как у тебя отношение к тапкам обстоит?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

Дед! Я вешу 152 кг (сын новые весы на НГ подарил), у меня диабет 2, сахар ниже 15 ваще никогда не бывает, вотки я жру не меньше 0.5 ежедневно.

Хошь расскажу, как жить с сахаром 15 и не париццо? ;)))) Просто не мерить его, гада! ;)))

И да - сёння у меня с супругой 29 лет венчания... я - ж веры самой шо ни есть православной ;))), хоть и .... ну да, и что?

Дык я тут Здоровое питание придумал: бананово-клубничный смузи!

1. 1 банан.

2. стакан замороженной клубники окатить кипятком.

3. лед - еще стакан.

4. вода - полстакана, для запаха.

5. водка - стакан с горкой ;))). (ром можно ежли с жабой договориться!)

6. долька лимона с кожурой.

-------------------

Всё скрутить в блендере в теч. минуты. Разлить по стаканам и пить с женой через толстую соломинку.

Лехаим!

DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

sadman41 пишет:

А как у тебя отношение к тапкам обстоит?

что мне какие-то тапки, в моём мире измочаленных скалок и сковородок с инверсным барельефом моего затылка? 

ua6em
ua6em аватар
Онлайн
Зарегистрирован: 17.08.2016

катушку Мишина не предлагаю )))