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

Таймеры

aZholtikov

Active member
Однако проблема.
На выходе что попало, но очень похоже на примерно ежесекундное вклинивание более приоритетного неизвестного прерывания.
Ну не знаю...
Прицепил светодиод. Залил код. Правда промежутки увеличил до секунд (использовал once для наглядности) и пребывание эмулировал в loop (нету кнопки под рукой). Вроде работает.
 

ART_HA

Member
Что у Вас в качестве платы с МК в описанном выше тесте выбрано?
 

ART_HA

Member
У меня nodemcu-32s.
Похоже мне все-таки придется близко знакомиться с таймерами ESP32, благо на них, в отличие от ESP8266 и документации много, и возможностей больше.
 

ART_HA

Member
aZholtikov, прошу прощения за дотошность.
А почему в Вашей программе (и моей соответственно тоже) используются два таймера, а не один?
Почему нельзя использовать такую схему:
аппаратное прерывание вызывает однократный запуск таймера 1, который по окончании счета выдает на порт 1 и вызывает программное прерывание, которое однократно запускает его же, но на другое время, по окончании которого на порт выдается 0?
Прошу не пинать, если написал глупость. :)
 

aZholtikov

Active member
aZholtikov, прошу прощения за дотошность.
А почему в Вашей программе (и моей соответственно тоже) используются два таймера, а не один?
Почему нельзя использовать такую схему:
аппаратное прерывание вызывает однократный запуск таймера 1, который по окончании счета выдает на порт 1 и вызывает программное прерывание, которое однократно запускает его же, но на другое время, по окончании которого на порт выдается 0?
Прошу не пинать, если написал глупость. :)
Логически противоречий вроде нет. Должно работать. Проверить физически не могу в ближайшие 3 дня. Попробуйте это:

#include "Ticker.h"
#include "arduino.h"
Ticker timer;
void IRAM_ATTR ISR_StartT1();
void ISR_StopT1();
void ISR_StartT2();
void IRAM_ATTR ISR_StartT1()
{
timer.once_ms(5, ISR_StopT1);
}
void ISR_StopT1()
{
digitalWrite(33, HIGH);
timer.once_ms(1, ISR_StartT2);
}
void ISR_StartT2()
{
digitalWrite(33, LOW);
}
void setup()
{
pinMode(27, INPUT);
pinMode(33, OUTPUT);
attachInterrupt(digitalPinToInterrupt(27), ISR_StartT1, CHANGE);
}
void loop()
{
}
 

ART_HA

Member
Короче такая история...
Загрузил я программу выше и... не обнаружил на выходе ничего.
Обрезал до минимума в виде генератора в loop безо всяких прерываний и... на выходе ничего.
Испугался, что спалил, но потом догадался очистить флеш и... всё заработало и, главное, никаких дерганий импульсов я не вижу.
Буду потихоньку в проект этот вариант с одним таймером ставить... :)
 

aZholtikov

Active member
Короче такая история...
Загрузил я программу выше и... не обнаружил на выходе ничего.
Обрезал до минимума в виде генератора в loop безо всяких прерываний и... на выходе ничего.
Испугался, что спалил, но потом догадался очистить флеш и... всё заработало и, главное, никаких дерганий импульсов я не вижу.
Буду потихоньку в проект этот вариант с одним таймером ставить... :)
:)
 

ART_HA

Member
По ходу дела возник вопрос.
Ticker.h использует библиотеку esp_timer.h , которая есть в SDK.
Но ни в одной из этих библиотек нет ни слова о настройке таймера, в частности его прескалера (divider).
Вопрос возник с тем, что согласно документации esp_timer имеет точность в микросекунды (с оговорками), а ticker - миллисекунды.
Где спрятана 1000?
 

aZholtikov

Active member
По ходу дела возник вопрос.
Ticker.h использует библиотеку esp_timer.h , которая есть в SDK.
Но ни в одной из этих библиотек нет ни слова о настройке таймера, в частности его прескалера (divider).
Вопрос возник с тем, что согласно документации esp_timer имеет точность в микросекунды (с оговорками), а ticker - миллисекунды.
Где спрятана 1000?
В самой библиотеке.
При вызове например once в итоге запускается esp_timer_start_once(_timer, milliseconds * 1000ULL) из SDK.

 

ART_HA

Member
esp_err_tesp_timer_start_once(esp_timer_handle_ttimer, uint64_t timeout_us);
us - это, насколько я понимаю, микросекунды.
Да и в самом тексте:
esp_timer set of APIs provide such facility. Internally, esp_timer uses a 32-bit hardware timer (FRC1, “legacy” timer). esp_timer provides one-shot and periodic timers, microsecond time resolution, and 64-bit range.
 

aZholtikov

Active member
esp_err_tesp_timer_start_once(esp_timer_handle_ttimer, uint64_t timeout_us);
us - это, насколько я понимаю, микросекунды.
Да и в самом тексте:
esp_timer set of APIs provide such facility. Internally, esp_timer uses a 32-bit hardware timer (FRC1, “legacy” timer). esp_timer provides one-shot and periodic timers, microsecond time resolution, and 64-bit range.
Да.
 

ART_HA

Member
Но в Ticker мы должны указывать не микросекунды, а миллисекунды.
Отсюда и вопрос: где спрятан множитель 1000?
 

ART_HA

Member
Т.е. вместо
esp_timer_start_once(_timer, milliseconds * 1000ULL)
следует читать
esp_timer_start_once(_timer, microseconds * 1000ULL);
?
 

aZholtikov

Active member
Т.е. вместо
esp_timer_start_once(_timer, milliseconds * 1000ULL)
следует читать
esp_timer_start_once(_timer, microseconds * 1000ULL);
?
Нет. Библиотека принимает время только в секундах и миллисекундах. "Внутри" переводит в микросекунды и запускает таймер.
Если нужно запустить таймер в микросекундах эта библиотека не подходит.
 

ART_HA

Member
Попытка самопального исправления библиотеки - это нонсенс или глупая идея?
 

aZholtikov

Active member
Попытка самопального исправления библиотеки - это нонсенс или глупая идея?
Нисколько! Сам иногда "грешу".
Но... Лучше взять существующую за основу и написать свою под другим названием и расположением. Ибо если править существующую в существующем месте, при обновлении ядра она может вернуться в первоначальное состояние... ;-)
 
Сверху Снизу