Интервальный таймер на Arduino: Сомнения по поводу библиотеки TimerOne
Я хочу синхронизировать прерывание таймера с нажатием кнопки. Я хочу прочитать состояние кнопки через 3 секунды с момента первого импульса (чтобы идентифицировать долго нажатую кнопку, 3 секунды для этого примера). Я пытаюсь сделать это с помощью этого кода:
#include <TimerOne.h>
#define pinButton 3
#define POWER_ON_TIME 3 //Длительное нажатие в секундах
volatile unsigned long pressed_Time = 0;
volatile unsigned long myTime_button = 0;
volatile unsigned long myTimeOn_button = 0;
volatile unsigned long myTime_pressed = 0;
unsigned long holdTime = 0;
bool button_state = false;
void setup() {
// put your setup code here, to run once:
pinMode(pinButton, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
Timer1.initialize();
Timer1.attachInterrupt(pressed_check);
attachInterrupt(digitalPinToInterrupt(pinButton), button_act, CHANGE);
Serial.begin(9600);
}
void loop() {
Serial.println("myTime_pressed");
Serial.println(myTime_pressed);
if (!digitalRead(pinButton)){Timer1.attachInterrupt(pressed_check,POWER_ON_TIME*1000000 );}
else {Timer1.detachInterrupt();}
}
void button_act(){
if (!digitalRead(pinButton)){myTime_button = micros(); //Flanco de bajada
}
else{myTimeOn_button = micros(); } //Flanco de subida
}
void pressed_check(){
myTime_pressed = micros();
}
Таким образом, я могу запустить прерывание таймера при нажатии кнопки, но проблема в том, что время-это не время с момента подключения функции, а с самого начала. Есть ли какие-нибудь советы, чтобы изменить это?
@Juanma, 👍1
Обсуждение1 ответ
Лучший ответ:
Не знаю, понимаю ли я, что ты хочешь сделать. ИМХО TimerOne-хорошая библиотека для повторяющихся задач, а не для событий с одним выстрелом.
Вы должны использовать Timer1.stop и Timer1.resume (), чтобы начать отсчет 3 секунд при каждом нажатии кнопки. Но у TimerOne есть известная проблема: когда вы используете restart или start, ISR запускается немедленно
Вот моя версия вашего кода. Он ждет нажатия кнопки, а затем запускает таймер. Через 3 секунды срабатывает pressed_check и устанавливается longPressDetected flas. Надеюсь, я правильно истолковал ваш вопрос
#include <TimerOne.h>
#define pinButton 3
#define POWER_ON_TIME 3UL //Long press in seconds
volatile unsigned long pressed_Time = 0;
volatile unsigned long myTime_button = 0;
volatile unsigned long myTimeOn_button = 0;
volatile unsigned long myTime_pressed = 0;
volatile bool firstISR_Call = true;
volatile bool longPressDetected = false;
unsigned long holdTime = 0;
bool button_state = false;
void setup() {
// put your setup code here, to run once:
pinMode(pinButton, INPUT_PULLUP);
pinMode(LED_BUILTIN, OUTPUT);
Timer1.initialize();
// Create an ISR that is called every POWER_ON_TIME seconds
Timer1.attachInterrupt(pressed_check, POWER_ON_TIME * 1000000UL);
// Stop Timer1 now
Timer1.stop();
//Timer1.attachInterrupt(pressed_check);
attachInterrupt(digitalPinToInterrupt(pinButton), button_act, CHANGE);
Serial.begin(9600);
}
void loop() {
if (longPressDetected) {
longPressDetected = false;
Serial.println("Long press detected");
}
delay(100);
}
void button_act() {
if (!digitalRead(pinButton)) {
myTime_button = micros(); //Flanco de bajada
firstISR_Call = true; // Set to true toprevent "phantom" interrupt
longPressDetected = false; // Clear long press detection flag
Timer1.restart(); // Restart timer from 0 - ISSUE: this fires immediatly an interrupt
// causing a so called "phantom" interrupt
}
else {
myTimeOn_button = micros() - myTime_button;
Timer1.stop();
} //Flanco de subida
}
void pressed_check() {
// Detect "phantom" interrupt
if (firstISR_Call) {
firstISR_Call = false;
return;
}
longPressDetected = true;
myTime_pressed = micros() - myTime_button;
Timer1.stop();
}
Большое вам спасибо! Это ответ на мой вопрос! Я попробовал перезапустить и запустить, но это сработало не так, как я хотел. Большое вам спасибо!, @Juanma
@Juanma не за что, моя радость., @Marco Cogo
- ATmega328P - проблема с использованием таймера 2 для генерации тона
- Точность синхронизации Arduino nano
- Можно ли отсоединить прерывание на определенное время
- Заставить TCNT оставаться ниже OCRxA на ATmega328P
- Эмуляция Arduino Uno с помощью QEMU: прерывания не работают
- Arduino непрерывно считывает значение АЦП с помощью прерывания
- Генерация стабильной частоты
- 4-битный счетчик вверх и вниз
Функция
button_act()
отсутствует в опубликованном коде. Пожалуйста, добавьте его. Одна из проблем, вероятно, заключается в том, что вам нужно добавить " L " в конце большого целого числа. В противном случае компилятор по умолчанию будет рассматривать его как целое число (которое не может содержать значение 1 миллион). Но еще: я не понимаю логики вашей программы. Вpressed_check()
вы не проверяете кнопку, а только устанавливаетеmyTime_pressed
, который только когда-либо печатается, но никак не используется. Вloop()
вы прикрепляете и отсоединяете прерывание таймера при нажатии и отпускании кнопки, что на самом деле не имеет смысла для меня., @chrislИ почему вы хотите использовать дополнительный аппаратный таймер для записи продолжительности нажатия? Я не вижу причины, по которой
millis()
иmicros()
было бы недостаточно для этого. Нет необходимости проходить через хлопоты с использованием аппаратного таймера., @chrislПривет @chrisl . Извините, я перерезал код. Теперь все в порядке. У меня есть два прерывания: одно внешнее, подключенное к кнопке, другое по таймеру. В этом коде я тестирую захват micros() с прерыванием таймера, и я хотел увидеть результаты. Я думал, что micros() может захватить время от attachInterrupt action, а не от запуска Arduino., @Juanma
"micros ()" дает вам микросекунды с момента запуска. Когда вам нужна разница во времени, вам нужно зафиксировать начальное и конечное значения, а затем взять разницу. Хотя я до сих пор не понимаю, зачем вам нужен аппаратный таймер для различения коротких и длинных нажатий кнопок., @chrisl
Я сейчас я сейчас, возможно, что проще сделать это без таймеров, но теперь я хочу знать, почему прикрепленная функция таймера выполняется на интервале времени с самого начала, а не с определенного события., @Juanma
Почему вы вообще используете прерывания? Посмотрите на пример обнаружения изменения состояния в IDE (File->examples->02.digital->State Change Detection), чтобы узнать, как определить, когда кнопка нажата или отпущена, а затем записать время этого события. После того, как текущее время события времени превысит 3 секунды, прочитайте вашу кнопку еще раз. Или сделайте свою жизнь проще и используйте библиотеку Bounce2.h. У него есть класс Button, который будет отслеживать продолжительность пребывания кнопки в любом состоянии., @Arjun Suhass