Как отслеживать миллисекунды в спящем режиме
В моем приложении мне нужно отслеживать время работы приложения, а также использовать спящие режимы. Однако при использовании спящих режимов Timer0 отключается, и, следовательно, миллисекунды перестают считать.
Есть ли способ измерить/подсчитать, как долго Arduino находился в спящем режиме?
Чтобы дать вам дополнительную справочную информацию, вот чего я пытаюсь достичь: Я использую датчик давления, который отправляет прерывание на Arduino каждые 80 мс и пробуждает его. Программа выполняет различные процедуры для обработки данных, которые могут занимать от 2 мс до 60 мс. Затем он переходит в спящий режим, пока не произойдет другое внешнее прерывание, примерно через 20-78 мс. В приложении есть много процессов, зависящих от времени, таких как секундомер, таймер и будильник, поэтому мне нужно иметь возможность отслеживать их, желательно с помощью millis(). Устройство работает от одноячеечной батареи LiPo емкостью 250 мАч, которой в настоящее время хватает примерно на 4 часа. Я использую ATMega1284.
В большинстве спящих режимов Timer0 отключен. Это означает, что millis() перестает считать. Есть ли способ без использования RTC (и пространство, и вес в большом почете), чтобы поддерживать подсчет миллисекунд в спящем режиме?
Я заметил, что SLEEP_MODE_IDLE поддерживает работу Timer0, но это означает, что каждую миллисекунду прерывание пробуждает устройство. Пожалуйста, поправьте меня, если я ошибаюсь, но, учитывая, что мой цикл может выполняться около 60 мс, я не вижу большого преимущества в спящем режиме на 1 мс.
Возможные решения:
- Использовать Timer2 для функции millis?
- Используйте сторожевой таймер, чтобы подсчитать, сколько времени прошло во время спящий режим и добавить это в millis() при пробуждении?
- Если бы существовал ОЧЕНЬ маленький SMD RTC, который не нуждался бы во внешнем компоненты, такие как генераторы и т. д., то это может быть осуществимо.
@Glyn Davidson, 👍1
Обсуждение2 ответа
Единственный способ поддерживать работу millis()
— это спать в спящем режиме.
SLEEP_MODE_IDLE. Переключение на Таймер 2 ничего не изменит, т.к.
все таймеры, кроме сторожевого таймера, останавливаются в других спящих режимах.
сторожевой таймер ужасно неточен, поэтому вы не хотите полагаться на него для
любой хронометраж.
Я не вижу особых преимуществ в спящем режиме на 1 мс.
Переход в спящий режим на 1 мс позволяет немного сэкономить электроэнергию. Но если ты это сделаешь 60 раз каждые 80 мс вы сэкономите много энергии. Я предлагаю вы делаете именно это: ложитесь спать, когда закончите свои расчеты. Когда вы просыпаетесь, если видите, что пробуждение пришло извне прерывание, тем вы его обрабатываете. В противном случае вы просто снова заснете.
Обратите внимание, что если период 80 мс внешнего прерывания достаточно последовательно, вы можете использовать это в качестве источника времени.
Спасибо @Эдгар. Как только я разместил вопрос, я начал искать в библиотеке прерывание 80 мс, но оказалось, что библиотека просто запрашивает данные каждые 80 мс, а датчик отправляет прерывание, как только данные готовы., @Glyn Davidson
Я пробовал постоянно выключать таймер 1 и таймер 3, а также выключать АЦП и БПК на 59,95 секунды каждой минуты и использовать спящий режим бездействия. Основной цикл проверяет, не произошло ли прерывание, в противном случае он снова переходит в спящий режим. Влияние этого на энергопотребление было минимальным. Сейчас попробую с часами реального времени., @Glyn Davidson
Я нашел часы RealTimeClock, которые мог бы использовать: RV-8803. . Он имеет размеры всего 3,2 мм x 1,5 мм x 0,8 мм, имеет внутренний XTAL и может показывать время с точностью до сотой доли секунды. Sparkfun делает раздельную плату (BOB-16281) и сопровождает библиотека.
Учитывая, что в моей схеме уже есть несколько развязывающих конденсаторов и я могу использовать внутренние подтягивающие резисторы ATMega1284, я думаю, что, вероятно, смогу интегрировать RV-8803 без каких-либо дополнительных компонентов.
На макетной плате прерывания работают хорошо, и вместо этого я могу использовать спящий режим EXTENDED_STANDBY. Единственным недостатком является то, что RTC записывает время в сотых долях секунды, тогда как моя программа раньше использовала миллисекунды. Мне нужно убедиться, что сотые доли достаточно точны для моих нужд.
В противном случае я рассмотрю предложение @Gerben выше.
- Как справиться с rollover millis()?
- Использование millis() и micros() внутри процедуры прерывания
- Разница между «time_t» и «DateTime»
- Как перевести ATtiny/ATmega в режим глубокого сна (чтобы годами работать от батарей), но при этом обнаруживать нажатие кнопки?
- Кнопка с таймером переключения и функцией сброса времени + светодиод обратной связи
- Использовать timer0, не влияя на millis() и micros().
- Вывод ESP8266 из deepSleep с помощью кнопки
- Как найти разницу между двумя timestamp
[MAX31343](https://www.maximintegrated.com/en/products/analog/real-time-clocks/MAX31343.html) в 8-контактном корпусе WLP 2,1 мм x 2,3 мм...?, @Majenko
Я думаю, вам в любом случае понадобится RTC, если вы делаете будильники. Милли будет дрейфовать слишком сильно, чтобы быть очень полезным для точного хронометража. Если пространство является проблемой, вы можете использовать асинхронный режим timer2 и подключить кристалл 32 кГц к контактам TOSC. Затем вы можете использовать спящий режим «Энергосбережение». Я закончил проект часов, но немного потрудился, чтобы выяснить, как настроить код. После калибровки он стал точным с точностью до минуты в год., @Gerben
@Majenko - MAX31343 записывает только секунды, а не миллисекунды, @Glyn Davidson