Хочу знать когда сработает таймер!

Adolf_Balalaykin
Offline
Зарегистрирован: 01.02.2021

Всем не равнодушным привет!
Решил реанимировать старый вопрос. Задача такова, нужно что бы отображался остаток времени до включения таймера, в формате чч:мм:cc Не спрашивайте зачем. Пока что выдаю в сериал монитор, там дальше будет видно. Графически себе представляю это примерно так.

 

 

 

 

 

 

 

 

 

 

 

Наваял такой не замысловатый код.

uint32_t previousMillis = 0; // время, когда таймер последний раз сработал.
const long interval = 1;     // цикличность обратного отсчета времени 1 сек.
bool triggerActive = false;  //переменные для отслеживания, были ли активированы триггеры или нет.
uint32_t timer;              // Переменные хранения времени
uint8_t t1 = 13              // 13 период включения 13 сек.
uint8_t t3 = 5               // длительность 5 сек.

void loop()
{
	// ############# Вывод остатка времени до включения таймера ##############
	
	uint32_t currentMillis = millis() / 1000;    // объявляем переменную currentMillis в секундах
	if (currentMillis - previousMillis >= interval)
	{
		uint32_t remains = t1 * 3600 - currentMillis; // переменная остатка в секундах
		uint8_t H = remains / 3600;        // остаток часов
		uint8_t M = (remains % 3600) / 60; // остаток минут
		uint8_t S = (remains % 3600) % 60; //остаток секунд
		
		if (ledState == "1") // если таймер сработал то выполняем код ниже...
		{
			char buffer1[9];
			sprintf(buffer1, "%02d:%02d:%02d", H, M, S);
			Serial.println(buffer1); // отобразим обратный отсчет времени
			} else {
			Serial.println("ON");
		} 
		previousMillis = currentMillis;
	}
	
	// ################# Собственно сам таймер ####################
	
	if (currentMillis - timer >= (ledState ? t3 : t1) && !triggerActive)
	{
		timer = currentMillis;
		ledState = !ledState;
		Serial.println("timer ON");
	}	
}

Как видим, таймер построен на millis, работает нормально. Но обратный отсчет работает криво. Включаю контроллер пошел обратный отсчет времени. Через заданное время таймер срабатывает и отсчет прекращается, в сериал монитор как и положено выдало статус "ON". По достижению времени отключения таймер отключается и тут снова должен начаться обратный отсчет с нуля, до
следующего включения таймера. Вместо этого начинает казать какое-то левое время. Мне кажется в строке 15 что то криво у меня посчитано.  Поможите выйти из штопора затупления?

ua6em
ua6em аватар
Offline
Зарегистрирован: 17.08.2016

ну да, очень быстро стала бы отрицательной )))

DIVGENY
Offline
Зарегистрирован: 23.08.2016
20         if (ledState == "1")

  а это сколько ?  

b707
Offline
Зарегистрирован: 26.05.2017

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

например в строке 15 какая-то бредятина написана

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

b707, там много бредятины. Чтобы ее избежать (как b707 выше писал) - нужно использовать измерения одного типа. И если используется миллис - проще всего в миллисекундах. Если сложно считать - используй макросы по полной. Например:

#define onesec   1 * 1000 // 1 секунда
#define onehours  1000 * 60 * 60 // 1 час

 

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

onehours 1000UL * 60 * 60

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Да да, упустил этот момент. Спасибо.

mykaida
mykaida аватар
Offline
Зарегистрирован: 12.07.2018

Бр...р - а где ledState объявлена? Может у меня косоглазие?

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

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

Вот прямо первое, Ваш рисунок

Adolf_Balalaykin пишет:

 

 

 

 

 

 

 

 

 

 

 

Не бывает на одной оси две разные точки t1! Видимо, вторая t1 равно t2 + некая константа? Так вот, если бы Вы так и написали - это помогло бы Вам делать программу. А так, как у Вас - только запутывает и сбивает с толку.

Начните с начала. И для начала, сделайте внятный рисунок и внятное описание задачи.

Adolf_Balalaykin
Offline
Зарегистрирован: 01.02.2021

ua6em пишет:

ну да, очень быстро стала бы отрицательной )))

Так и есть. Первый период отрабатывает нормально. Второй и последующий периоды кажет левое время.

00:00:08
00:00:07
00:00:06
00:00:05
00:00:04
00:00:03
00:00:02
00:00:01
00:00:00
timer ON
timer OFF
86:28:10
86:28:09
86:28:08
и.и.д...

BOOM пишет:

b707, там много бредятины. Чтобы ее избежать (как b707 выше писал) - нужно использовать измерения одного типа. И если используется миллис - проще всего в миллисекундах. Если сложно считать - используй макросы по полной. Например:

#define onesec   1 * 1000 // 1 секунда
#define onehours  1000 * 60 * 60 // 1 час

Дык там и так всё лишь в секундах. В 12 строке обявлена переменну currentMillis, дальше работаем только с ней . Переменная remains опирается на currentMillis, которая так-же в секундах. В упор не вижу миллисекунд. Дефайны не использовал, потому что это просто автоподмена. Если просто значение в дефайнах, то да. А тут везде где встретится в коде onesec (onehours), будет считать. Лучше уж один раз посчитать, чем постоянно контроллер грузить расчетами.

Ладно, это всё косметика. Суть в другом. Мне кажется если бы после t2 обнулить millis() , то последущие вычеслиния уже шли бы с учетом этого обнудения. Нет?

 

b707
Offline
Зарегистрирован: 26.05.2017

Adolf_Balalaykin пишет:

там и так всё лишь в секундах.

а вот это в чем? В секундах? А 3600 что такое?

uint32_t remains = t1 * 3600 - currentMillis;

Цитата:
Суть в другом. Мне кажется если бы после t2 обнулить millis() , то последущие вычеслиния уже шли бы с учетом этого обнудения. Нет?

как только начинаются предложения "обнулить миллис" - я закрываю ветку. Не хочу слушать бред.

Если вы уверены, что у вас все в программе сделано правильно - то пользуйтесь ей, зачем вы в конфу то пришли?

 

b707
Offline
Зарегистрирован: 26.05.2017

Adolf_Balalaykin - и еще вам подсказка.

Подумайте, что вы пытаетесь вычислить? - Время, оставшееся от ТЕКУЩЕГО МОМЕНТА до следующего включения таймера, так?

ТЕКУЩИЙ МОМЕНТ - это currentmillis. Покажите мне это время на вашей схеме:

Его тут нет! Схема неверная, remains - это вовсе не та разница между t1 и t2. как у вас на рисунке.

Может именно поэтому вы и не можете его верно подсчитать?

BOOM
BOOM аватар
Offline
Зарегистрирован: 14.11.2018

Адольф, меньше ерепенься, больше слушай (читай) что говорят (пишут). Ты же сюда за помощью пришёл или просто показать «какой крутой»? Если первое, то вникай. Если второе - то так и скажи, поржем вместе и разойдёмся.
b707 часто резковат, но в основном пишет по делу.

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

b707 пишет:

Может именно поэтому вы и не можете его верно подсчитать?

Да, похоже бестолку. Мой пост о том же самом (#8) проигнорирован. ТС, похоже, надо не думать, а трясти.

Adolf_Balalaykin
Offline
Зарегистрирован: 01.02.2021
 
Да ладно вам обижаться. Я то думал что я один тут, человек тонкой душевной организации )). Конечно же я всё читаю что мне вы тут советуете. Только вот доступ к железкам не всегда есть, что бы поколдовать, поэксперементировать согласно рекомендаций. И потом в мои 69, не все усваивается с лёту. Но я стараюсь как могу. Так что судите строго. Не всё коментирую, но ко всем прислушиваюсь.
 
ЕвгенийП пишет:
Давайте, Вы начнёте с начала и нормально сами для себя уясните задачу. Сейчас Вы задачу не понимаете, а просто делаете пассы руками, внутренн убеждая себя, что всё понятно. У Вас каша в голове и Вы пытатесь из этой каши что-то вылепить Вот прямо первое, Ваш рисунок Не бывает на одной оси две разные точки t1! Видимо, вторая t1 равно t2 + некая константа? Так вот, если бы Вы так и написали - это помогло бы Вам делать программу. А так, как у Вас - только запутывает и сбивает с толку. Начните с начала. И для начала, сделайте внятный рисунок и внятное описание задачи.
 
 
Петрович, рисунком я хотел показать цикличность, возможно не совсем внятно. Т.е таймер включается когда наступает время t1 и выключается когда наступает время t2. Remains - это интервал между включениями. Вот в нём то и должен идти обратный отсчет времени. Далее просто следует повторение цикла и так до бесконечности.
 
 
b707 пишет:
Подумайте, что вы пытаетесь вычислить? - Время, оставшееся от ТЕКУЩЕГО МОМЕНТА до следующего включения таймера, так?
 
Верно.
 
b707 пишет:
Его тут нет! Схема неверная, remains - это вовсе не та разница между t1 и t2. как у вас на рисунке.
 
Вы меня не поняли, разница t1 и t2 это интервал в котором таймер остается включенным.
 
BOOM пишет:
Адольф, меньше ерепенься, больше слушай (читай) что говорят (пишут). Ты же сюда за помощью пришёл или просто показать «какой крутой»? Если первое, то вникай. Если второе - то так и скажи, поржем вместе и разойдёмся.
Бум дружище, а где мне еще вникать как не тут? А если поржать, я всегда за! )) Говорят мой код можно читать вместо юмора.
 
Для удобства, выложил эмуляцию https://wokwi.com/projects/333892206403256916
Чуть позже сяду поиграюсь с кодом. О результатах отпишусь.
 
mifar
Offline
Зарегистрирован: 07.04.2021

Adolf_Balalaykin пишет:

 Remains - это интервал между включениями. Вот в нём то и должен идти обратный отсчет времени. Далее просто следует повторение цикла и так до бесконечности.

Машину времени изобретаешь? Как можно узнать сколько осталось, если не знаешь сколько было изначально? Задай значение этого Remains и уменьшай его на единицу каждую секунду. Дошел до 0 - счет остановил, включил таймер. Таймер выключился - опять присвоил то же значение Remains и считаешь дальше.

Adolf_Balalaykin
Offline
Зарегистрирован: 01.02.2021

Спасибо всем большое за потраченное время. Таки победил эту заразу. Постарался учесть все рекомендации.

#define ledPin 25            // Светодиод повесим на 25 пин.
bool ledState = false;       // по дефолту в 0.
uint32_t previousMillis = 0; // запоминаем время, последнего срабатывания таймера.
const long interval = 1;     // цикличность обратного отсчета времени 1 сек.
bool triggerActive = false;  // переменная для отслеживания, был ли активирован триггер или нет.
uint32_t timer;              // Переменная хранения времени
uint32_t t1 = 7200;          // период включения в секундах (2 часа)
uint32_t t3 = 3600;          // длительность в секундах (1 час)

void setup() {
  Serial.begin(9600);
  delay(1000);
  pinMode(ledPin, OUTPUT);
}

void loop()
{
  uint32_t currentMillis = millis() / 1000;      // аптайм в секундах.

  // ####################### Таймер #######################

  if (currentMillis - timer >= (ledState ? t3 : t1) && !triggerActive) // Условие включения таймера
  {
    timer = currentMillis;
    ledState = !ledState;
    digitalWrite(ledPin, ledState);
    Serial.println("ON");
  }

  // ############# Вывод остатка времени до включения таймера ##############

  if (currentMillis - previousMillis >= interval)
  {
    if (!ledState)
    {
      uint32_t countdown = t1 - (currentMillis - timer);
      uint8_t H = countdown / 3600;       // остаток часов
      uint8_t M = countdown / 60 % 60;    // остаток минут
      uint8_t S = countdown % 60;         // остаток секунд

      char buffer[9];                              // кол-во знаков
      sprintf(buffer, "%02d:%02d:%02d", H, M, S);  // в буфер формат чч:мм:cc
      Serial.println(buffer);                      // в сериал порт
    }
    previousMillis = currentMillis;
  }
}

На эмуляторе всё работает. https://wokwi.com/projects/333892206403256916

Форум великая сила! :)