Простой таймер без использования delay

ks_junio
Offline
Зарегистрирован: 03.07.2019

Всем привет.

Для своего проекта нужно было таймер, не нагружающий процессор.

using callback = void(*)();
enum class TimerMode
{
	SingleShot,
	Cyclic
};

class Timer
{
public:
	Timer(unsigned long timeout, TimerMode mode, callback func);
	void Ping(bool pred = true);

private:
	unsigned long m_timeout = 0;
	volatile unsigned long m_time = 0;
	callback m_callback = nullptr;
	TimerMode m_mode;
	bool m_started = false;
};

Timer::Timer(unsigned long timeout, TimerMode mode, callback func)
{
	m_timeout = timeout;
	m_callback = func;
	m_mode = mode;
	m_time = millis();
}

void Timer::Ping(bool pred)
{
	if (!pred)
	{
		if (m_mode == TimerMode::SingleShot && m_started)
			m_started = false;

		m_time = millis();
		return;
	}

	if (m_mode == TimerMode::SingleShot && m_started)
		return;

	if (millis() - m_time > m_timeout)
	{
		m_started = true;
		m_time = millis();
		return m_callback();
	}
}

Ну и использование:

Timer singleShotTimer(1000, TimerMode::SingleShot, []()
{
	digitalWrite(pin, 1);
});
Timer cyclicTimer(2000, TimerMode::Cyclic, []()
{
	digitalWrite(pin, 1);
});
DetSimen
DetSimen аватар
Offline
Зарегистрирован: 25.01.2017

А у мня таких целый TTimerList. :-)

https://github.com/DetSimen/Arduino_TimerList

Upd. А точно, мне можно же в туда лямбды прикрутить, по заветам великого Пуха. 

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

Позвольте узнать, каким образом соотносятся между собой "void(*)();" в строке №1 первого скетча, "void Timer::Ping(bool pred)" в 29-ой строке второго и "return m_callback();" в строке №47 второго?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

DetSimen пишет:

Upd. А точно, мне можно же в туда лямбды прикрутить, по заветам великого Пуха. 

Синей изолентой - нехай Пух от зависти лопнет!

Green
Offline
Зарегистрирован: 01.10.2015

И как только люди без millis() раньше жили? Да и сейчас... Ардуину то не везде втулишь.)

ks_junio
Offline
Зарегистрирован: 03.07.2019

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

Позвольте узнать, каким образом соотносятся между собой "void(*)();" в строке №1 первого скетча, "void Timer::Ping(bool pred)" в 29-ой строке второго и "return m_callback();" в строке №47 второго?

Собсвенно в моем случае не интересно, что там вернет функция. А если добавить звездочку, то можно получить вполне нужный результат

ks_junio
Offline
Зарегистрирован: 03.07.2019

DetSimen пишет:

А у мня таких целый TTimerList. :-)

https://github.com/DetSimen/Arduino_TimerList

Upd. А точно, мне можно же в туда лямбды прикрутить, по заветам великого Пуха. 

Да, хороший набор (пожалуй добавлю в закладки), но зачем? Будь я новичком, выбрал более читаемый и компактный вариант)

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

Собсвенно в моем случае не интересно, что там вернет функция.

эти слова наводят на мысль, что код не ваш - вы его где списали и даже не вполне поняли, как он работает. И возвращаемое значение у вас в коде есть, потому что в том, чужом коде - оно было...

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

но зачем? Будь я новичком, выбрал более читаемый и компактный вариант)

вот точно такой же вопрос возникает от вашей темы. Нафига отдельный класс с таймером, когда одна строчка

if (millis() - prev_mill > interval) 

делает ровно тоже самое, как весь ваш класс - да еще и нагружает процессор куда меньше

"Будь я новичком" - выбрал бы эту строчку, как собственно я и делаю в своих проектах, никогда никаких софтовых таймеров не использую. Если нужен таймер, совсем независимый от основного кода - делаю на хардовом таймере и прерываниях, в других случаях достаточно миллис

ks_junio
Offline
Зарегистрирован: 03.07.2019

b707 пишет:

ks_junio пишет:

Собсвенно в моем случае не интересно, что там вернет функция.

эти слова наводят на мысль, что код не ваш - вы его где списали и даже не вполне поняли, как он работает. И возвращаемое значение у вас в коде есть, потому что в том, чужом коде - оно было...

Как вы догадались?)

ks_junio
Offline
Зарегистрирован: 03.07.2019

b707 пишет:

ks_junio пишет:

но зачем? Будь я новичком, выбрал более читаемый и компактный вариант)

вот точно такой же вопрос возникает от вашей темы. Нафига отдельный класс с таймером, когда одна строчка

if (millis() - prev_mill > interval) 

делает ровно тоже самое, как весь ваш класс - да еще и нагружает процессор куда меньше

Сразу вспоминаю школьные олимпиады по робототехнике, где в функцию loop впихивают 100500 строчек кода. Им простительно, потому что они знают только функциональное программирование

У меня такое ощущение, что вы кроме arduino ничего не программировали, если структура может грузить процессор

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

Чотаржу. 

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio - а вас случаем не Архат зовут? - Или может он ваш учитель? есть тут такой персонаж, который ужом вывернется, но никогда  не признает промаха...

Вы наехали на Дед-Симена. сказав что у него сложно. А когда я обратил внимание, что и вашу задачку можно решить куда проще -вы спорите. Двойные стандарты?

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

Звучит так, как будто функциональное программирование сродни антисемитизму.

ks_junio
Offline
Зарегистрирован: 03.07.2019

b707 пишет:

ks_junio - а вас случаем не Архат зовут? - Или может он ваш учитель? есть тут такой персонаж, который ужом вывернется, но никогда  не признает промаха...

Вы наехали на Дед-Симена. сказав что у него сложно. А когда я обратил внимание, что и вашу задачку можно решить куда проще -вы спорите. Двойные стандарты?

Хорошо, это тот же

if (millis() - prev_mill > interval)

только который выполняется в лямбде.

Такой ответ описывает этот код?

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Нафига в 15-ой строке "volatile"?

Можно привести полный пример использования?

ks_junio
Offline
Зарегистрирован: 03.07.2019

sadman41 пишет:

Звучит так, как будто функциональное программирование сродни антисемитизму.

Нет, они решают разные задачи

b707
Онлайн
Зарегистрирован: 26.05.2017

sadman41 пишет:

Звучит так, как будто функциональное программирование сродни антисемитизму.

Гриш, не знаю, кому это адресовано. В равной степени могу принять и на свой счет. Я вовсе не против классов, да и вообще считаю. что каждый пишет так, как ему удобнее - лишь бы работало.  Подход ТС имеет право на жизнь, но его юношеская уверенность, что только он знает, "как надо" вызывает улыбку... снисходительную старческую улыбку :)))))

 

ks_junio
Offline
Зарегистрирован: 03.07.2019

Ворота пишет:

Нафига в 15-ой строке "volatile"?

Можно привести полный пример использования?

Вот это я не знаю, я недавно начал изучать программирование МК и выложил свой коод на критику

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

Хорошо, это тот же

if (millis() - prev_mill > interval)

только который выполняется в лямбде.

вот именно. Вопрос - нафига его запихивать в лямбду из 50 лишних строк кода, если оно и так неплохо работает?

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

sadman41 пишет:

Звучит так, как будто функциональное программирование сродни антисемитизму.

Нет, они решают разные задачи

функциональное программирование и антисемитизм ?

 

ks_junio
Offline
Зарегистрирован: 03.07.2019

b707 пишет:

sadman41 пишет:

Звучит так, как будто функциональное программирование сродни антисемитизму.

Гриш, не знаю, кому это адресовано. В равной степени могу принять и на свой счет. Я вовсе не против классов, да и вообще считаю. что каждый пишет так, как ему удобнее - лишь бы работало.  Подход ТС имеет право на жизнь, но его юношеская уверенность, что только он знает, "как надо" вызывает улыбку... снисходительную старческую улыбку :)))))

 

Почему "как надо"? Я предложил свой вариант на критику.

Но я вот не знаю, то ли это консервативные взгляды, толи в этой области программируют по другому

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

Когда у меня таймеров меньше 3 и они не зависят друг от друга, я свой таймерлист даже не достаю из пыльного мешка, теребонькаю миллис вручную. Бо, память так коротка...

ks_junio
Offline
Зарегистрирован: 03.07.2019

DetSimen пишет:

Когда у меня таймеров меньше 3 и они не зависят друг от друга, я свой таймерлист даже не достаю из пыльного мешка, теребонькаю миллис вручную. Бо, память так коротка...

 

А у меня их больше 10, и loop выглядит красиво

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ks_junio пишет:

Ворота пишет:

Нафига в 15-ой строке "volatile"?

Можно привести полный пример использования?

Вот это я не знаю, я недавно начал изучать программирование МК и выложил свой коод на критику

Так полный пример использования будет?

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

b707 пишет:
вас случаем не Архат зовут?
Скорее уж AlexGyver - ошибки ровно те же, что в классе gyvertimer.

ks_junio
Offline
Зарегистрирован: 03.07.2019

Статистика: из 20 ответов по теме только 2,  от Ворота и ЕвгенийП

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

А у меня их больше 10, и loop выглядит красиво

"только начинаю изучать МК" - и сразу 10 таймеров? Мне еще ни в одном проекте больше 3-4х не понадобилось :)

 

Хотя пишу активно и для себя и на заказ

bwn
Offline
Зарегистрирован: 25.08.2014

ks_junio пишет:

Вот это я не знаю, я недавно начал изучать программирование МК и выложил свой коод на критику

Ток изначально, вы его еще и в готовые проекты запостили.

ks_junio
Offline
Зарегистрирован: 03.07.2019

Я в начале приложил

Timer singleShotTimer(1000, TimerMode::SingleShot, []()
{
    digitalWrite(pin, 1);
});

void loop()
{
    singleShotTimer.Ping(1==1);
}

 

ks_junio
Offline
Зарегистрирован: 03.07.2019

bwn пишет:

ks_junio пишет:

Вот это я не знаю, я недавно начал изучать программирование МК и выложил свой коод на критику

Ток изначально, вы его еще и в готовые проекты запостили.

Ничего не понял

ks_junio
Offline
Зарегистрирован: 03.07.2019

b707 пишет:

ks_junio пишет:

А у меня их больше 10, и loop выглядит красиво

"только начинаю изучать МК" - и сразу 10 таймеров? Мне еще ни в одном проекте больше 3-4х не понадобилось :)

 

Хотя пишу активно и для себя и на заказ

Да, у меня висит 7 устройств, которые нужно включать/выключать. И у каждого свое условие

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ks_junio пишет:

Я в начале приложил

Слушай, ну зачем так? Всё вроде нормально начиналось. Зачем врать-то? В каком именно посте "в начале" у тебя есть loop? Правда, на архата смахиваешь - тот ни в жисть свою ошибку не признает, и ты туда же.

А теперь, прошу, приведи полный пример. Ты понимаешь смысл слова "полный"? Полный - это такой, который я мог бы запустить и исполнить, а не ловить сообщения, что в программе setup отсустсвует. Уж будь так любезен.

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

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

b707 пишет:
вас случаем не Архат зовут?
Скорее уж AlexGyver - ошибки ровно те же, что в классе gyvertimer.

Петрович, не колись за ошибки, я раньше начал к этому подводить. Я же не зря примера требую.

ks_junio
Offline
Зарегистрирован: 03.07.2019

..

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio - код вставлять разучились? В сообщении 29 правильно было, вставьте так же

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Это, что пример?

Во-первых, ты неправильно вставил код, а во-вторых, ты, похоже на знаешь что такое пример.

Ладно сам привду, ты лишь подтверди - правильно ли я использую или ошибся в чём?

Итак, пример:

#include <Printing.h>

using callback = void(*)();

enum class TimerMode
{
	SingleShot,
	Cyclic
};

class Timer
{
public:
	Timer(unsigned long timeout, TimerMode mode, callback func);
	void Ping(bool pred = true);

private:
	unsigned long m_timeout = 0;
	volatile unsigned long m_time = 0;
	callback m_callback = nullptr;
	TimerMode m_mode;
	bool m_started = false;
};

Timer::Timer(unsigned long timeout, TimerMode mode, callback func)
{
	m_timeout = timeout;
	m_callback = func;
	m_mode = mode;
	m_time = millis();
}

void Timer::Ping(bool pred)
{
	if (!pred)
	{
		if (m_mode == TimerMode::SingleShot && m_started)
			m_started = false;

		m_time = millis();
		return;
	}

	if (m_mode == TimerMode::SingleShot && m_started)
		return;

	if (millis() - m_time > m_timeout)
	{
		m_started = true;
		m_time = millis();
		return m_callback();
	}
}


Timer cyclicTimer(500, TimerMode::Cyclic, []() {
		Serial.println(millis());
	}
);


void setup(void) {
	Serial.begin(57600);
}

void loop(void) {
	cyclicTimer.Ping();
}

Пойдёт так? Правильно использую?

ks_junio
Offline
Зарегистрирован: 03.07.2019

В Ping поставьте 1

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Куда, в какую строку?

ks_junio
Offline
Зарегистрирован: 03.07.2019

Вы программист или кто? Ping(1)

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

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

Вот результат:

501
1002
1503
2004
2505
3006
3507
4008
4509
5010
5511
6012
6513
7014
7515
8016
8517
9018
9519

 

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ks_junio пишет:

Вы программист или кто? Ping(1)

Не знаю, кто ты (программист или кто) - там умолчание есть ("void Ping(bool pred = true);") и эта 1 - мёртвому припарка.

ks_junio
Offline
Зарегистрирован: 03.07.2019

Ворота пишет:

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

Вот результат:

501
1002
1503
2004
2505
3006
3507
4008
4509
5010
5511
6012
6513
7014
7515
8016
8517
9018
9519

 

Вангую что 1мс уходит на вывод

ks_junio
Offline
Зарегистрирован: 03.07.2019

Ворота пишет:

ks_junio пишет:

Вы программист или кто? Ping(1)

Не знаю, кто ты (программист или кто) - там умолчание есть ("void Ping(bool pred = true);") и эта 1 - мёртвому припарка.

Вот как раз для таких как ТЫ она и стоит

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

Неправильно вангуешь. Вывод как таковой работает после вычисления параметра print.

Если не ванговать, а посмотреть на код и исправить ошибку в классе, то всё будет нормально.

b707
Онлайн
Зарегистрирован: 26.05.2017

Ворота, это не ошибка... ну не грубая

Ворота
Ворота аватар
Offline
Зарегистрирован: 10.01.2016

ks_junio пишет:

Вот как раз для таких как ТЫ она и стоит

Спасибо, потому я ею и воспользовался. Надеюсь, правильно воспользовался? Возражений нет?

ks_junio
Offline
Зарегистрирован: 03.07.2019

Ворота пишет:

Неправильно вангуешь. Вывод как таковой работает после вычисления параметра print.

Если не ванговать, а посмотреть на код и исправить ошибку в классе, то всё будет нормально.

Поставить >=? Да, хорошее замечание

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

Вот как раз для таких как ТЫ она и стоит

ого как мы заговорили? похоже, ТС надо только по шерстке гладить, критику оно не любит.

Деда, где там картинка с указателем? - положи поближе, похоже, скоро понадобится.

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

b707 пишет:

Ворота, это не ошибка... ну не грубая

Т.е. то, что специалированный класс таймера всегда врёт на 1мс - не ошибка? А что же тогда ошибка? Можете дать определение?

И, да, таже самая ошибка была у гивера, как я уже говорил.

b707
Онлайн
Зарегистрирован: 26.05.2017

ks_junio пишет:

Поставить >=? Да, хорошее замечание

вапщето тривиальное...