• Система автоматизации с открытым исходным кодом на базе esp8266/esp32 микроконтроллеров и приложения IoT Manager. Наша группа в Telegram

Нужна помощь Таймер паузы для ESP8266.

Cadil

New member
Библиотека таймера TimerOne.h для контроллеров Arduino позволяет задать не только периодичность вызова функции, но и временный промежуток выполнения функции.
Для понимания привожу фрагмент скетча для Arduino с таймером TimerOne.h:
Код:
#include <TimerOne.h> // прерывания по таймеру1
#define TstatTimerMax 120 //минимальная пауза между включениями горелки, сек
unsigned int TstatTimer = 20; //таймер паузы между включениями/выключениями, начальная установка 20 сек для устаканивания системы после сброса
void setup() {
  Timer1.initialize(500000); // Timer0 interrupt - set a timer of length 500000 microseconds
  Timer1.attachInterrupt( timerIsr ); // attach the service routine here
   //...
}
void loop() {
//...
if ( digitalRead(Relay) == RelayOn ) // если горелка включена -
      {
        digitalWrite(Relay, !RelayOn); // выключить горелку
        TstatTimer = TstatTimerMax; // горелку держать выключенной не менее заданного в TstatTimerMax времени
      }
//...
}
К сожалению, ничего похожего для ESP8266 не могу найти или не там ищу.
Помогите организовать аналогичную "многозадачность" для ESP8266, чтобы "горелку держать выключенной не менее заданного в TstatTimerMax времени".
 

=AK=

New member
Библиотека таймера TimerOne.h для контроллеров Arduino позволяет задать не только периодичность вызова функции, но и временный промежуток выполнения функции.
...
К сожалению, ничего похожего для ESP8266 не могу найти или не там ищу.
Помогите организовать аналогичную "многозадачность" для ESP8266, чтобы "горелку держать выключенной не менее заданного в TstatTimerMax времени".
Вот библиотека простой кооперативной операционки. Она позволяет организовыватъ квази-независимые задачи, где задачи могут "спать" в течении заданного промежутка времени (в миллисекундах). Пока задача "спит", выполняются другие задачи. Задача может использовать сколко угодно интервалов "сна" произвольной длительности, что позволяет строть сложные циклограммы с ветвлениями и т.п.

Работает в среде Ардуино с любым процессором, у которого имеются стандартная либа setjmp. В том числе с ESP8266.

Надо только помнить, что вызовы "сна" (COOS_DELAY) должны делаться в основном теле задачи, их нельзя делать в функциях, которые задача вызывает. И еще, в момент вызова COOS_DELAY локальные переменные текущей задачи портятся. Чтобы они не портились, их надо обьявлять как static. Или использовать глобальные.
 

Cadil

New member
есть TICKER - esp8266/Arduino
пример Blink без delay на ticker- esp8266/Arduino
Спасибо за ссылки. Примеры работают, но мои попытки организовать вызов функции в теле loop() и без delay() пока безуспешны.
Посмотрите, пожалуйста, скетч во вложении. Как в цикле этого скетча задать мигание светодиода с периодом 5 сек и длительностью 1 сек?
 

Вложения

Сергей_Ф

Moderator
Команда форума
в момент вызова COOS_DELAY локальные переменные текущей задачи портятся. Чтобы они не портились, их надо обьявлять как static. Или использовать глобальные.
что то как-то странно. Разве нельзя эти переменные объявить как static внутри конструктора и не накладывать ограничений на основной код?
 

enjoynering

Well-known member
уважаемый Cadil просите за резкость, но вам надо учиться, учиться и еще раз учится.

вот как надо мигать светодиодом с TICKER:
Код:
#include <Ticker.h>

Ticker tickerSetLedLow;
Ticker tickerSetLedHigh;

void setLed(bool state)
{
  digitalWrite(LED_BUILTIN, state);
}

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, HIGH);               //turn off led

  tickerSetLedLow.attach_ms(500,  setLed, LOW);  //every 500ms call setLed(LOW)
  tickerSetLedHigh.attach_ms(900, setLed, HIGH); //every 900ms call setLed(HIGH), 900ms-500ms=400ms led is on
}

void loop()
{

}
заметьте loop() остается пустым. ваши два тикера tickerSetLedLow и tickerSetLedHigh работают сами по себе и не зависят от того что происходит в главном цикле.
 

Вложения

Последнее редактирование:

=AK=

New member
что то как-то странно. Разве нельзя эти переменные объявить как static внутри конструктора и не накладывать ограничений на основной код?
Какого конструктора? Задача не является классом, у нее конструктора нет. Это просто функция.
 

Cadil

New member
уважаемый Cadil просите за резкость, но вам надо учиться, учиться и еще раз учится.
вот как надо мигать светодиодом с TICKER:
заметьте loop() остается пустым. ваши два тикера tickerSetLedLow и tickerSetLedHigh работают сами по себе и не зависят от того что происходит в главном цикле.
Повторюсь - мне не надо мигать светодиодом. Я пытаюсь организовать функцию паузы - аналог функции TstatTimer = TstatTimerMax; (библиотека TimerOne.h для Ардуино) только для ESP8266 (см. фрагмент скрипта первом посте).
Там таймер инициализируется и задается периодичность вызова в сетапе, а функция паузы (TstatTimer) выполняется в лупе.
Заранее прошу прощения, если невнятно объяснил свою задачу.
 
Последнее редактирование:

=AK=

New member
Повторюсь - мне не надо мигать светодиодом. Я пытаюсь организовать функцию паузы - аналог функции TstatTimer = TstatTimerMax; (библиотека TimerOne.h для Ардуино) только для ESP8266 (см. фрагмент скрипта первом посте).
Там таймер инициализируется и задается периодичность вызова в сетапе, а функция паузы (TstatTimer) выполняется в лупе.
Заранее прошу прощения, если невнятно объяснил свою задачу.
Вот ваш фрагмент, реализованный про помощи A_COOS

Код:
void coos_task0(void) // эта задача вместо вашего основного цикла loop()
{
  COOS_DELAY(20000); //  начальная пауза 20 сек для устаканивания системы после сброса
  while(1)
  {
    if ( digitalRead(Relay) == RelayOn ) // если горелка включена -
    {
      digitalWrite(Relay, !RelayOn); // выключить горелку
      COOS_DELAY(50);                 // горелку держать выключенной не менее 50 ms
    }
    //...
    COOS_DELAY(0);   // ненадолго отдать управление ОС чтобы другие задачи тоже могли выполняться
  }
}
void coos_task1(void) // эта зададача вместо вашего прерывания от таймера, написана при помощи телепатии
  while(1)
  {
    COOS_DELAY(5000);  // период повторения 5 сек
    digitalWrite(Relay, RelayOn); // включить горелку
  }
}
Через 5 сек после начального пуска горелка включится, через 20 сек - выключится, после этого каждые 5 сек горелка будет включаться в задаче 1 и выключаться на 50 мс в задаче 0. Остальное - как напишите код.

Пример получился достаточно вырожденный и придурочный поскольку задача полностью не описана. Бог вас знает, где какие интервалы и задержки вам нужны и почему. Я просто попытался имитировать ваш кусок кода, на практике A_COOS наверняка позволит написать все проще и изящнее.
 
Последнее редактирование:

Сергей_Ф

Moderator
Команда форума
Какого конструктора? Задача не является классом, у нее конструктора нет. Это просто функция.
Не кипятитесь. В этом и был вопрос - почему не сделали классом со статическими переменными внутри? Тогда никаких ограничений снаружи бы не было, имхо. Это же ваша разработка, как я понял.
 

=AK=

New member
В этом и был вопрос - почему не сделали классом со статическими переменными внутри? Тогда никаких ограничений снаружи бы не было, имхо.
Это ни на что не влияет. Перечисленные выше ограничения определяются тем, что для смены контекста используются функции setjmp/longjmp. Классы к этому не имеют никакого отношения. Если хотите, можете оформлять задачи как функции void task(void) в каких-то ваших классах, если вам так удобнее.
 

enjoynering

Well-known member
Повторюсь - мне не надо мигать светодиодом. Я пытаюсь организовать функцию паузы - аналог функции TstatTimer = TstatTimerMax; (библиотека TimerOne.h для Ардуино) только для ESP8266 (см. фрагмент скрипта первом посте).
Там таймер инициализируется и задается периодичность вызова в сетапе, а функция паузы (TstatTimer) выполняется в лупе.
Заранее прошу прощения, если невнятно объяснил свою задачу.
вам же показали как моргать светодиодом с помощью ticker. этот пример легко переделывается под вашу задачу
 

Cadil

New member
Вот ваш фрагмент, реализованный про помощи A_COOS
Благодарю за обстоятельный ответ.
Я не воспользовался предложенным решением, поскольку по подсказке Сергей_Ф использовал функцию millis() с очень простым синтаксисом.
Успехов!
 

nikolz

Well-known member
удалось написать механизм ожидания событий в заданном интервале без остановки процессора
минимальный интервал 10 мкс.
реализовал на этом протокол 1-Wire.
На основе этого механизма можно реализовать многопотоковость (многозадачность) но с квантом не 1 ms, а раз в 50 меньше.
 
Сверху Снизу