Счетчик импульсов на прерываниях в режиме сна Arduino

MIK_Invisible

✩✩✩✩✩✩✩
26 Июл 2022
5
0
Доброго времени суток читающим!
Собираю счетчик импульсов на Arduino pro-mini на 328 атмеге, а точнее измеритель скорости вращения вентилятора. Для опытов взял обычный 4х пиновый куллер от компьютера на датчике холла.
Задача: просто фиксировать каждое срабатывание датчика холла в куллере.
Подключил его на пин D3 ардуины и настроил на этом пине прерывание по ниспадающему фронту, включил подтяжку к плюсу на пине.
Обработчик в прерывании минимален, просто прибавляет единицу к переменной.
Вопрос дребезга контактов решен фильтром RC, та и нет его в датчике холла.
Так же подключил библиотеку GyverPower.h для организации сна Ардуины. Режим сна глубокий "POWERDOWN_SLEEP"
Период сна задал 1025 мс (~1 сек), разрешение сна для библиотеки задал 16 мс.
Логика следующая: Ардуина спит ~1 сек. и в это время фиксирует импульсы датчика в куллере. Затем Ардуина просыпается, выполняет какие-то действия, в том числе вывод в монитор количества импульсов и обнуляет переменную этих импульсов по прерыванию от куллера. Затем опять уходит в сон на ~1 сек.
И вот столкнулся с проблемой, в активном режиме (НЕ в режиме сна) Ардуина считает большее количество импульсов чем в режиме сна, то есть пока нет сна количество импульсов похоже на реальное количество оборотов, но в режиме сна теряется где-то 20% импульсов, причем глубокий или легкий режим сна на это не влияет.
Помогите понять почему и что с этим делать?
Спасибо.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
Вопрос: а нафига режим сна? Сон нужен для минимизации энергозатрат, но при работе с кулером это бессмысленно.
 

MIK_Invisible

✩✩✩✩✩✩✩
26 Июл 2022
5
0
@Геннадий П, в дальнейшем планируется сделать измеритель скорости ветра на батарейках. Куллер взят для опытов, планируется использовать датчик ветра на герконе, который просто будет замыкаться на минус при вращении.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
@MIK_Invisible, Уменьшаете частоту и напряжение питания и радуетесь низкому потреблению. При 2 МГц на 3.3 В она чтото около 1 мА будет потреблять. Для счета импульсов это за глаза, можно и до 1 МГц опустить.
 

rkit

★★★✩✩✩✩
5 Фев 2021
508
127
Прерывание прерывает сон. И выход из сна - не моментальная операция. Читай даташит внимательно.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
@MIK_Invisible, Не исключено, проверь на больших и малых оборотах. Но лучше отказаться от сна. Вход и выход из сна это затраты энергии, а пониженное тактирование может наоборот оказаться выгодней.
 
  • Лойс +1
Реакции: MIK_Invisible

rkit

★★★✩✩✩✩
5 Фев 2021
508
127
Ничего не думаю. У меня нету информации о том, что ты там натворил, чтобы выводы какие-то делать. (кроме того, что натворить ты мог что угодно, так как фундаментально не понимаешь, как это работает).
 
  • Лойс +1
Реакции: te238s

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@Геннадий П, в дальнейшем планируется сделать измеритель скорости ветра на батарейках. Куллер взят для опытов, планируется использовать датчик ветра на герконе, который просто будет замыкаться на минус при вращении.
Как то давным давно пытался сделать счётчик оборотов на герконе (для намотки трансформаторов), столкнулся с тем, что после достижения определённых оборотов (кажется не таких уж и больших) геркон не успевал замыкаться-размыкаться. Я бы лучше смотрел в сторону датчика Холла.

И да, было бы не плохо выложить свой код (ещё лучше в оформленном виде). Реально понимаю настроение @rkit
 

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
С датчиком Холла тоже есть проблемы. И еще есть проблемы даже с оптическим датчиком. На крайних положениях может срабатывать несколько раз.
 

DAK

★★★✩✩✩✩
8 Окт 2020
517
137
@Старик Похабыч, Спасибо!
Вот я дожил, раньше думал что именно эти датчики применяются в системах ABS и в режиме датчиков положения Коленчатого вала и распредвала.... Надо прям взять готовый индуктивный датчик с крыльчаткой... Наверное с ними точно проблем не будет. Хотя хочется взять обычный куллер от проца, вытащить от туда магнитный сердечник и датчик, судя по тем оборотам, на которых тот работает с ним тоже не возникнет проблем.
 

Геннадий П

★★★★★★✩
14 Апр 2021
1,969
632
44
@DAK, Абсолютный энкодер в отличии от относительного обычно не имеет подобных проблем, но он сам по себе сложней.
Ну, или как вариант, динамически подстраивать антидребезговую задержку. Т.к. система имеет определенную инерцию, то раскрутиться/затормозить моментально не может.
 
Изменено:

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
@Геннадий П,
Точно, я например знаю , что у меня мотор крутит 3000 оборотов в минуту, и исходя из этого использую определенную программную задержку. А т.к. обороты подсчитываются практически постоянно, то и задержку можно считать исходя из текущих оборотов.
 

MIK_Invisible

✩✩✩✩✩✩✩
26 Июл 2022
5
0
@rkit, да, вы правы, похоже непонимание является причиной проблемы, потому я сюда и пришел ))))
Вот я написал скетч, максимально простой и демонстрирующий ситуацию которая получается с подсчетом импульсов:
#include <GyverPower.h>

// Класс таймера
class Timer {
public:
Timer(uint32_t nprd = 0) {
setPeriod(nprd);
}
void setPeriod(uint32_t nprd) {
prd = nprd;
}
bool ready() {
return (prd && millis() - tmr >= prd) ? (tmr = millis(), 1) : 0;
}
private:
uint32_t tmr = 0, prd = 0;
};

Timer tmr1(1025); //таймер 1 для вывода и обмнуления импульсов раз в 1025 мс
Timer tmr5(10250); //таймер 5 для вывода и обмнуления импульсов раз в 10250 мс
volatile int Wind_counter = 0; //счетчик импульсов
bool flag = LOW; //флаг перехода в сон и из сна

// обработчик аппаратного прерывания
void isr() {
Wind_counter++;
// дёргаем за функцию "проснуться"
// без неё проснёмся чуть позже (через 0-8 секунд)
//power.wakeUp();
}

// функция вывода и обнуления импульсов
void wcPrint() {
//Serial.println();
Serial.print("Imp- ");
Serial.println(Wind_counter);
Wind_counter = 0;
}

void setup() {
Serial.begin(9600);
power.autoCalibrate(); // автоматическая калибровка таймера сна
// глубокий сон
power.setSleepMode(POWERDOWN_SLEEP);
power.setSleepResolution(SLEEP_16MS);
// отключили АЦП, таймеры 1 и 0
//power.hardwareDisable(PWR_ADC | PWR_TIMER1 | PWR_TIMER0);
// включили ADC обратно
//power.hardwareEnable(PWR_ADC);
// кнопка подключена к GND и D3
pinMode(3, INPUT_PULLUP);
// подключаем прерывание на пин D3 (Arduino NANO)
attachInterrupt(1, isr, FALLING);
Serial.println("Start !!!");
}

void loop() {

if (tmr1.ready()) wcPrint(); // вывод количества импульсов раз в 1025 мс
if (tmr5.ready()) { //смена флага сна раз в 10250 мс
flag = !flag;
Serial.println();
}

if (flag) { // переключение сон / не сон
Serial.print("sleep ");
Serial.flush(); // ожидание очистки монитора перед сном
// спим 1.5 секунды (1500 мс)
power.sleepDelay(1025);
// проснулись
// миллис корректируется автоматически!
//Serial.println("wake!");
}
}

А это результат работы:
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 39
Imp- 41
Imp- 39
Imp- 40
Imp- 40
Imp- 40

sleep Imp- 31
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30

Imp- 39
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 40
Imp- 40

sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30
sleep Imp- 30

Но теперь у меня кажется есть теория, в описании библиотеки GyverPower, написано что сон реализован циклами по 16,32,64...мс, похоже после срабатывания прерывания, остаток такого периода теряется, похоже реальное время сна выходит меньше чем я задаю, отсюда и меньшее количество импульсов.
Кто что скажет?

UPD:
Проверил временные периоды терминальной программой
Terminal log file
Date: 27.07.2022 - 15:23:54
-----------------------------------------------
312182 Imp- 40
15:23:54.949>
313207 Imp- 40
15:23:56.004>
314232 Imp- 41
15:23:57.006>
315257 Imp- 40
15:23:58.009>
316282 Imp- 41
15:23:59.064>
317307 Imp- 40
15:24:00.068>
318332 Imp- 40
15:24:01.128>
319357 Imp- 41
15:24:02.137>
320382 Imp- 40
15:24:03.139>

15:24:03.139>
sleep 321427 Imp- 31
15:24:03.940>
sleep 322469 Imp- 30
15:24:04.684>
sleep 323512 Imp- 30
15:24:05.438>
sleep 324555 Imp- 30
15:24:06.257>
sleep 325598 Imp- 30
15:24:07.003>
sleep 326640 Imp- 30
15:24:07.750>
sleep 327683 Imp- 30
15:24:08.512>
sleep 328727 Imp- 30
15:24:09.314>
sleep 329769 Imp- 30
15:24:10.057>
sleep 330812 Imp- 30
15:24:10.814>

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

bort707

★★★★★★✩
21 Сен 2020
3,058
910
думаете импульсы теряются пока МК засыпает/просыпается?
думаю у тебя МК реально вообще не спит, а только и делает что засыпает-просыпается.

Во сне твое прерывание не работает и ничего не считает. По приходу первого импульса МК начинает просыпаться, этот импульс теряется. Далее в течении 16мс импульсы считаются, потом МК уходит в сон. На следующем импульсе картина повторяется.

Вывод - для твоего случая сон бесполезен вовсе.
 
  • Лойс +1
Реакции: MIK_Invisible

Старик Похабыч

★★★★★★★
14 Авг 2019
4,263
1,302
Москва
Тут просто другой подход нужен. Засыпать скажем на несколько секунд (1, 2 или больше, какие цели ). Просыпаться. Замерять скорость, другие данные. Отправлять куда надо и опять засыпать.
А "кто надо" пусть вычисляет среднюю скорость по показаниям.
Ветер это не мотор, он не будет дуть постоянно и его измерять не надо так точно, как какие либо приборы. Если решишь, что скорость ветра не 10 мс, а 9.5 большой беды не будет.
 
  • Лойс +1
Реакции: MIK_Invisible

rkit

★★★✩✩✩✩
5 Фев 2021
508
127
  • Лойс +1
  • Аррр! -2
Реакции: MIK_Invisible и Bruzzer

MIK_Invisible

✩✩✩✩✩✩✩
26 Июл 2022
5
0
думаю у тебя МК реально вообще не спит, а только и делает что засыпает-просыпается.

Во сне твое прерывание не работает и ничего не считает. По приходу первого импульса МК начинает просыпаться, этот импульс теряется. Далее в течении 16мс импульсы считаются, потом МК уходит в сон. На следующем импульсе картина повторяется.

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

Тут просто другой подход нужен. Засыпать скажем на несколько секунд (1, 2 или больше, какие цели ). Просыпаться. Замерять скорость, другие данные. Отправлять куда надо и опять засыпать.
Так же верно, теперь буду придумывать удобный для себя алгоритм работы.

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

Всем участникам огромное спасибо, пойду ракажопить дальше)))))
 

te238s

★★✩✩✩✩✩
14 Ноя 2021
374
97
Думаю по ТЗ алгоритм нужен другой: импульсы подавать на вход асинхронного таймера,пока мк спит,счетчик тикает. Периодически просыпаясь считает что нужно и отправляет куда нужно.
По памяти не помню только какой режим сна не выключает периферию. Ну и с периодом сна определится чтоб переполнения не было.