Датчик касания — определение длительности нажатия/удержания и соответствующее изменение хода программы
Приведенный ниже код используется для управления реле с помощью Arduino. Нажатие на сенсорный датчик подключает и отключает реле.
Если пользователь нажимает/касается/удерживает палец на датчике касания дольше двух секунд, как мне настроить программу так, чтобы она выполняла что-то иное, кроме подключения или отключения реле?
#define TouchSensor 9 // Контакт для емкостного сенсорного датчика
int relay = 2;
boolean currentState = LOW;
boolean lastState = LOW;
boolean RelayState = LOW;
void setup() {
Serial.begin(9600);
pinMode(relay, OUTPUT);
pinMode(TouchSensor, INPUT);
}
void loop() {
currentState = digitalRead(TouchSensor);
if (currentState == HIGH && lastState == LOW){
Serial.println("pressed");
delay(1);
if (RelayState == HIGH){
digitalWrite(relay, LOW);
RelayState = LOW;
} else {
digitalWrite(relay, HIGH);
RelayState = HIGH;
}
}
lastState = currentState;
}
@hameds1, 👍1
3 ответа
Лучший ответ:
Вам необходимо определить, как долго датчик был нажат до момента отпускания. Когда он отпущен, вы можете предпринять соответствующие шаги. Если нажатие было короче, скажем, 1,5 с, вы можете переключить реле. В противном случае вы можете сделать что-то еще.
Есть много способов добиться этого. Вы можете запрограммировать это самостоятельно, используя функцию millis()
. Вам придется установить временную метку, когда состояние датчика изменится на высокое, затем дождаться, пока оно станет низким, и вычесть временную метку из текущего значения millis()
. Это даст вам длительность нажатия, которую вы можете использовать в соответствующем операторе if
.
Или вы можете использовать библиотеку Debounce
, которая немного упрощает задачу (не намного, но вам следует рассмотреть возможность устранения дребезга в зависимости от типа используемого вами датчика). Посмотрите на ответ VE7JRO на этот вопрос. Функция debouncer.update()
проверяет, изменилось ли состояние кнопки. Если это так и значение было LOW (в вашем случае его нужно изменить на HIGH), устанавливается временная метка со значением millis()
. Когда происходит обновление с LOW, вычисляется разница во времени между двумя событиями и выполняется соответствующее действие. Я добавлю код из ответа для справки здесь:
// Подключите один конец кнопочного переключателя NO к GND, а другой
// конец к выводу 4 Arduino.
// ПРИМЕЧАНИЕ: Если кнопка удерживается нажатой меньше времени, чем задержка устранения дребезга
// время, прошедшее время отобразит время задержки устранения дребезга.
#include <Debounce.h>
const byte SWITCH = 4;
unsigned long startTime = 0;
unsigned long endTime = 0;
unsigned long elapsedTime = 0;
const byte debounceDelayTime = 50;
Debounce debouncer = Debounce(debounceDelayTime, SWITCH);
void setup(){
Serial.begin(9600);
pinMode(SWITCH, INPUT_PULLUP);
}
void loop(){
if(debouncer.update()){
if(debouncer.read() == 0){
startTime = millis();
Serial.println("Button Pressed");
}
else if(debouncer.read() == 1){
endTime = millis();
Serial.println("Button Released");
elapsedTime = endTime - startTime;
Serial.print("Button Held Down For ");
Serial.print(elapsedTime);
Serial.println(" ms.");
}
}
}
Этот скетч использует таймер millis() для добавления концепции времени к устранению дребезга кнопки с помощью библиотеки Bounce2 (эта библиотека может быть включена в текущую версию Arduino IDE). Этот скетч не содержит никакого кода для включения и выключения реле.
// Подключите один конец кнопочного переключателя NO к GND
// а другой конец — к контакту 4 Arduino.
#include <Bounce2.h>
byte buttonState = 0;
byte lastButtonState = 0;
const byte buttonPin = 4;
const byte debouncerInterval = 50; // Время в мс.
unsigned long buttonHeldThreshold = 2000; // Время в мс.
unsigned long buttonPressTimeStamp;
Bounce debouncer = Bounce();
void setup(){
Serial.begin(9600);
pinMode(buttonPin, INPUT_PULLUP);
debouncer.attach(buttonPin);
debouncer.interval(debouncerInterval);
}
void loop(){
if(debouncer.update()){
if(debouncer.read() == 0){
buttonState = 1;
buttonPressTimeStamp = millis();
Serial.println("Button Pressed");
}
else if(debouncer.read() == 1){
buttonState = 0;
Serial.println("Button Released");
}
}
if(buttonState == 1){
if(millis() - buttonPressTimeStamp >= buttonHeldThreshold){
buttonState = 2;
Serial.println("Button Held for 2+ seconds");
}
}
// Выводить содержимое переменной buttonState только при его изменении.
if(buttonState != lastButtonState){
Serial.print("Button state = ");
Serial.println(buttonState);
Serial.println();
lastButtonState = buttonState;
}
}
Помните, что в этой библиотеке есть функции debouncer.rose()
и debouncer.fell()
, которые могут быть вам полезны. Всегда полезно посмотреть файлы *.h и *.cpp в устанавливаемых библиотеках. Может быть несколько функций, которые не показаны в примерах библиотеки. Иногда автор(ы) используют комментарии к коду в библиотеке, которые могут помочь вам устранить любые возникающие проблемы.
Для такого рода сценария «активация» кнопки никогда не происходит при ее нажатии. Да, при «нормальных» обстоятельствах вы нажимаете кнопку, цепь замыкается, и что-то происходит.
Однако, если вам нужно больше, чем просто эта простая операция, вы никогда ничего не делаете, просто нажав ее.
Например, если вы нажимаете на ссылку на веб-странице, при нажатии кнопки мыши ничего не происходит. Да, ссылка «выбрана», но это все. Ничего активного не происходит, пока вы не отпустите кнопку мыши. Именно действие «нажать-отпустить» представляет собой «щелчок» — и то только в том случае, если отпускание происходит в течение определенного времени после нажатия.
Это позволяет реализовать другие варианты, например, «нажать-перетащить-отпустить» для перетаскивания или «нажать-подождать-отпустить» для выбора без активации и т. д.
Итак, для вашего сценария у вас есть два желаемых варианта «запуска»:
- пресс-релиз
- нажмите и удерживайте
Если «выпуск» «пресс-релиза» происходит за более короткое время, чем время «удержания» «пресс-удержания», вы можете различать их.
Итак, ваша методология будет выглядеть примерно так:
- Кнопка нажата — засекаем время
- Либо:
- Кнопка отпущена, и время истекло < 2 секунд, или
- Прошедшее время >= 2 секунды
Как код, который может выглядеть примерно так:
static uint32_t ts = 0;
static uint8_t buttonState = HIGH;
uint8_t buttonValue = digitalRead(ButtonPin);
if (buttonValue != buttonState) { // Состояние изменилось.
buttonState = buttonValue; // Запишите его
if (buttonState == LOW) { // Кнопка была нажата
ts = millis(); // Записываем время
} else if (ts > 0) { // Отпущено - ts должно быть установлено нажатием
if (millis() - ts < 2000) { // Прошло менее 2 секунд
// Запустите процедуру «пресса»
ts = 0; // Очищаем нашу временную метку.
}
}
} else if (ts > 0) { // Состояние не изменилось, но кнопка была нажата
if (buttonState == LOW) { // Он удерживается. Не является строго необходимым, но не повредит
if (millis() - ts >= 2000) { // прошло 2 секунды
// Запустите процедуру «удержания»
ts = 0; // Очищаем нашу временную метку.
}
}
}
Переменная отметки времени ts
используется как для записи времени нажатия кнопки, так и в качестве флага, указывающего, что мы в данный момент находимся в «неактивированном» состоянии. То есть, для состояния «hold» для указания, нужно ли нам все еще запускать нашу «hold»-процедуру или нет. Без этой проверки после 2 секунд удержания кнопки «hold»-процедура будет продолжать выполняться снова и снова, пока кнопка не будет отпущена. Это похоже на реализацию «принудительного» отпускания кнопки после того, как она запустила «hold»-процедуру. После этого первого срабатывания «hold» нам больше не важно, что делается с кнопкой. Мы игнорируем все до следующего ее нажатия, когда мы снова устанавливаем ts
.
- Несколько неблокирующих таймеров обратного отсчета?
- Функция digitalRead() ардуино не считывает входное значение, отправленное датчиком после обнаружения объекта
- Использование значения MAX30100 SpO2 для включения светодиода
- Arduino Uno - Raspberry PI - Поплавковые датчики - Водяные насосы
- Все ли контакты Arduino Uno выводят 5 В?
- Проблема с последовательностью воздушных поршней
- Какова работа pulseIn?
- Сколько датчиков может поддерживать один модуль Arduino?