BlynkTimer

Поскольку в Blynk встроена своя функция таймера, то ее и использую, не привлекая дополнительных библиотек, вроде TimerOne.
Допустим, по таймеру мигает светодиод. Все в принципе работает. Но время от времени, мигание “замораживается”, а после начинает очень быстро мигать, как бы догоняя упущенное.
В чем может быть причина - работа других таймеров (их несколько), загрузка системы другими функциями? Как бороться?

First… make sure you are fully updated with the latest Library App and Local Server (if used) versions as there were some “fixes” made to BlynkTimer that helps stop rogue timers from acting up.

Otherwise…

Multiple timers all calling functions at the same time, or iteration timers being used for short term use, but not canceled/deleted when done, and possibly other conflicting libraries that use the same internal timer as Blynk/Simpletimer can all cause these types of issues.

  • Space out timers so they do not interact with each other. E.g

The Ugly

Three timers all set for 1000L (1 second) All called at the same time

1s - timer 1 & 2 & 3
2s - timer 1 & 2 & 3
3s - timer 1 & 2 & 3
4s - timer 1 & 2 & 3
5s - timer 1 & 2 & 3
6s - timer 1 & 2 & 3

The Bad

Changing a couple of timers from 1000 to 2000 or 2500 still causes them to interfere with each other every 2nd and 5th iteration

1s - timer 1
2s - timer 1 & 2
2.5s - timer 3
3s - timer 1
4s - timer 1 & 2
5s - timer 1 & 2 & 3
6s - timer 1

The Good

Three timers all set for non-intersecting times (as best as possible)

1st timer - 1000L (1 second),

2nd timer - 2033L (2 seconds and 33ms - add more ms you think your function takes longer than 33s and thus might be overrun by another timer)

3rd timer - 5155 (5 seconds and 155 ms - I generally start pulling random ms numbers out and trying to make sure they are not easily divisible… thus unlikely to intersect over time, or at least very rarely)

https://playground.arduino.cc/Code/SimpleTimer#Functions

BlynkTimer still works the same way… so learning the usages of the differing timers types and little things like setting ID so as being able to enable/disable, delete, reset, etc. can come in very handy.

Спасибо. Попробую сделать непересекающиеся таймеры.
Еще подскажите пожалуйста, как лучше организовать двухтактный таймер. В некоторых библиотеках такая возможность предусмотрена.
Например светодиод в течение 8 секунд х секунд горит / у секунд не горит. Значения могут х и у могут меняться пользователем с точностью до 0.1 секунды. Сейчас это организовано с помощью таймера на 0.1 секунду, но это создает видимо большую нагрузку, тогда как срабатывать надо только два раза за 8 секунд.

Спасибо.
Значит, если мне нужно менять время включения светодиода, то как то так.

BLYNK_WRITE(V40){ //  Вводим значение от 0 до 100
   klapan_value = param.asInt() ;
  klapan();
}

    void klapan(){
    timer.deleteTimer( timer_klapan );
    timer_klapan = timer.setInterval(8000, []() {  // 1st Timed Lambda Function - Turn ON LED every second (repeating)
    Blynk.virtualWrite(V37, 255);  // Turn Virtual LED ON
    timer.setTimeout(klapan_value*80, []() {  // 2nd Timed Lambda Function - Turn OFF LED 1/2 second later (once per loop)
    Blynk.virtualWrite(V37, 0);  // Turn Virtual LED OFF
    });  // END 2nd Timer Function
      });  //
    }

Только это не будет корректно работать при крайних значениях klapan_value 0 и 100. Надо видимо эти значения отдельно обрабатывать.

The two timers have to work together. If you want a 50% duty cycle then the 1st Interval Timer is X and the 2nd Timeout Timer is 1/2 of X

  • The 1st Interval timer (which is a repeating timer) starts both the “thing” and the 2nd Timeout timer (which is a one shot timer)…

  • The 2nd Timeout timer runs once to stop the “thing”…

  • Then the whole cycle repeats…

So if you want the time of the cycle to be adjustable, then you need to adjust both the timers accordingly…

However, you should probably change the 1st timer to a Timeout timer as well, so that the entire cycle only runs once, then scans for any change in the adjustable time setting and starts the cycle again… this may require a 3rd overseer interval timer… Timerception :stuck_out_tongue:

Приведенный код работает как надо. Мне нужно было регулировать включение светодиода в процентах от 0 до 100 с периодом в 8 секунд. Первый таймер мне регулировать не надо. То есть если задано 25 процентов, то 2 секунды горит, 6 не горит.
Таймер наблюдателя делать не стал, просто в момент изменения числа процентов старый таймер удаляется и запускается новый с введенными параметрами. Мне кажется это оптимальный вариант. :slight_smile:
Я правильно понимаю, что таймеры работают только во время действия loop()? Если долго выполняется подпрограмма, таймер в этот момент не работает.

BlynkTimer is independent of server connection, so as long as there is nothing blocking the underlying void loop() processes, like delay(), then timers should “interrupt” other code as needed.

Доброй ночи, собственно зачем такое сложное управление светодиодом?

Ну, в реальности это не светодиод, а соленоидный клапан. Регулировка скорости вытекания жидкости.

1 Like

И все таки.
Есть функция восстановления связи с сервером при обрыве.

void reconnectBlynk(){       // функция которая проверяет соединение

  if (!Blynk.connected()) { //если соединения нет то 
    if (Blynk.connect()) {  // конектимся
      BLYNK_LOG("Reconnected"); Serial.println ("---rec---");   // выводим в лог   
      } else {
      BLYNK_LOG("Not reconnected"); // выводим в лог     
             
    }
  }

Если произошел разрыв, то эта функция может выполнятся несколько секунд. В это время все таймеры не работают. Это понятно.
Но, когда функция завершится, все пропущенные срабатывания таймеров стремятся выполнится мгновенно. А этого можно избежать?

Why not? BlynkTimer is a “clone/port” of SimpleTimer and is NOT affected with a server disconnection… as long as timer.run() is still in the void loop()

Сервер не при чем. Несколько секунд выполняется только функция reconnectBlynk(), управление на loop() не передается. Таймеры не работают.

Well, whatever your function is trying to determine is related to the server… at least that is what those commands are in reference to… boolean checks of server status.

You topic is getting confusing… you wanted to know why the timer seemed to be having pauses before acting like it was catching up. That can be explained by bad code, improper use of timers or even older library versions.

Then you wanted to know about ways to flash an LED then later a solenoid valve.

But now you are working with some form of strange connection management that may be locking up your sketch? While I am not clear on what that function is supposed to do, aside from print connection status (which I think can be done simpler) I do not see any cyclical conditions that could cause any blocking issues.

Я буду вам очень благодарен, если вы дадите ссылку на пример правильной организацией подключения Blynk к wifi. С проверкой и переподключением, если произошел разрыв связи.
С таймерами суть в том, что если какая-то функция выполняется долго (например функция вывода на экран занимает у меня 500мс), то во время выполнения этой функции, все функции, которые выполняются по таймерам, работать не будут. Далее, как я уже писал.
Библиотеку Blynk обновил.
Попробую показать. Вод код:

    void setup() {
      Serial.begin(9600);
      Serial.println(" ");
      Serial.println("Launch");


      setSyncInterval ( 10 * 60 );
      timer.setInterval(5000L, t3000ms);
      timer.setInterval(50L, t50ms);
        
    }
    void t3000ms() {
     Serial.println( "-----");
     unsigned long t = millis();
     while (( millis() - t ) < 3000 );
     Serial.println( "----3000ms");
    }
    void t50ms() {
      unsigned long t = millis();
      Serial.println( "50ms");
    }
    void loop() {
       if (Blynk.connected()) {
        Blynk.run(); // Запускаем Блинк
       }
       timer.run(); // Запускаем таймер
     unsigned long t = millis();
     while (( millis() - t ) < 10 );
     Serial.print( millis() - t );
     Serial.println( " loop");
    }

Вот вывод:

>         50ms
>         10 loop
>         10 loop
>         10 loop
>         10 loop
>         10 loop
>         -----
>         ----3000ms
>         50ms
>         10 loop
>         50ms
>         10 loop
>         10 loop
>         10 loop
>         10 loop
>         50ms
>         10 loop
>         10 loop
>         10 loop
>         10 loop
>         11 loop
>         50ms

Видно, что во время выполнения функции t3000ms() функция t50ms() не выполняется.
После выполнения функции t3000ms() функия t50ms() выполняется начинает “догонять”.

I already did provide a link (at the start of this topic) to one such option that I have made.

The issue is that a while() loop is a blocking loop, as in nothing else is allowed to happen until it finishes whatever it is doing… the solution is to find other ways to do the job with non-blocking programming methods.

A crude option is to include Blynk.run() and timer.run() commands within the while() loop… but doing so, at least with the Blynk.run() can apparently cause other memory issues if abused.

Вот это вариант, спасибо.
А если такой возможности нет, как в приведенной функции reconnectBlynk() (она реально может выполняться секунд 10). Тогда наверно имеет смысл останавливать таймеры в начале функции, и запускать их в конце? Но команды остановить все таймеры сразу нет. Только по одному.

В вашем примере не увидел как Blynk будет восстанавливать связь при ее обрыве.
Если я уберу из своего кода reconnectBlynk() (вызывается тоже по таймеру 30 сек), то при обрыве связи связь сама не восстановится. Если можно, приведите код.

with the command…

Blynk.connect();  // Try to reconnect to the server

If for some reason it is the WiFi that is not reconnecting (but I haven’t had that issue, even with router reboots) then one could also ad a preceding command like…

WiFi.begin(ssid, pass);  // Non-blocking if no WiFi available

Спасибо.
У меня используется ESP8266_Lib.h, BlynkSimpleShieldEsp8266.h
Какой неблокирующий код для WiFi будет для этих библиотек?
Сейчас в setup() использую

EspSerial.begin(ESP8266_BAUD);
Blynk.config(wifi,auth);
Blynk.connectWiFi(ssid, pass);
Blynk.connect();

И еще. Я понимаю, что этого не может быть, но проверял много раз.
Вот код в setup(), где устанавливаются таймеры.

setSyncInterval ( 10 * 60 );
timer_reconnectBlynk = timer.setInterval(30155L, reconnectBlynk);
timer_showvaluse = timer.setInterval(2031L, showvaluse);
timer_induction = timer.setInterval (3600387L, induciton);
timer.setInterval (501, read_sensor);
timer.setInterva`l (203, blynkprint);

Любой таймер, который указан в списке первым ( в данном случае timer_reconnectBlynk ), работать не будет.

You have to connect to WiFi before you can connect to Blynk :stuck_out_tongue_winking_eye:

I do seem to recall issues with named timers (using ID) but that seems to no longer be an issue for me…

Make sure you are fully updated with latest versions of ESP Core (stable is 2.4.2), Blynk Library (0.5.4), App and if used Local Server.