Нашел интересную
библиотеку для обработки нажатий кнопок в Ардуино. Попробовал "привязать" к своему энкодеру - получилось не плохо. Можно назначить сколько угодно нажатий (одно нажатие, два, короткие, длинные) кнопки энкодера для запуска чего-либо... Это пример скетча для управления одной сервой (немного подправил).
PHP код:
#define pinA 3 //Первый PIN Сигнала с энкодера
#define pinB 4 //Второй PIN Сигнала с энкодера
#include "ClickButton.h"
#include <Servo.h>
#include <EEPROM.h>
Servo myservo; //Название сервомашины
int servoPin = 8; //Сервомотор подключен на PIN 8
int angle; //Текущий угол поворота (при запуске программы будет автоматический вставать в указаное положение)
int maxAngle = 90; //Максимальный угол поворота сервомотора (градусов)
int minAngle =45; //Минимальный угол поворота сервомотора (градусов)
int angleStep = 2; //Угол единичного шага (градусов)
int stepSpeed = 2; //Скорость шага (Время задержки шага)
boolean valA=0; //Текущее переменное значение энкодера на выходе энкодера А
boolean valB=0; //Текущее переменное значение энкодера на выходе энкодера В
boolean Estate=0; //Вспомогательная переменная необходимая для определения направления вращения
boolean pulse = 0; //Импульс шага в любом направлении, не стабилизированный
boolean Dir =0; //Переменная направления вращения (Если=1 то влево, если=0 то вправо)
boolean zapret=HIGH; //Вспомогательная переменная необходимая для стабилизации импульса шага
boolean outsig=HIGH; //Импульс шага в любом направлении, стабилизированный
long time; //Переменная таймера задержки в функции стабилизации
// Светодиод
const int ledPin = 13;
int ledState = 0;
// Кнопка
const int buttonPin1 = 10;
ClickButton button1(buttonPin1, LOW, CLICKBTN_PULLUP);
// Назначаем функцию переключателя
int LEDfunction = 0;
void setup()
{
angle = EEPROM.read(0);//Считываем из памяти угол поворота сервы
pinMode(ledPin,OUTPUT);
button1.maxPresses = 9; // Количество программируемых нажатий для кнопок
button1.debounceTime = 20; // Таймер дребезга в мс
button1.multiclickTime = 350; // Пауза между нажатиями кнопки
button1.heldDownTime = 1000; // длительность нажатия и удержания кнопки
pinMode(pinA,INPUT_PULLUP); //Цифровой вход A c энкодера
pinMode(pinB,INPUT_PULLUP); //Цифровой вход В c энкодера
}
void loop()
{
// Обновлям состояние кнопки
button1.Update();
if (button1.click != 0)
LEDfunction = button1.click;
if(button1.click == 1)
ledState = !ledState;
//Два коротких нажатия
if(LEDfunction == 2)
{
myservo.attach(servoPin);
myservo.write(maxAngle); // Серва вернулась в исходное состояние
delay(stepSpeed);// Скорость поворота сервы
}
// три коротких нажатия
if(LEDfunction == 3)
{
myservo.attach(servoPin);
change_ugol(); // Режим установки наклона с помощью энкодера
}
// длительное однократное нажатие (более 1 секунды)
if(LEDfunction == -1)
{
myservo.attach(servoPin);
myservo.write(angle); // Серва повернулась на сохраненный в Eeprom угол
delay(stepSpeed);// Скорость поворота сервы
}
// одно короткое + одно длительное нажатие (более 1 секунды)
if(LEDfunction == -2)
{}//можно что-то вставить
// два коротких + одно длительное нажатие (более 1 секунды)
if(LEDfunction == -3)
{}//можно что-то вставить
// update the LED
digitalWrite(ledPin,ledState);
}
//*********** РЕЖИМ УСТАНОВКИ УГЛА НАКЛОНА С ПОМОЩЬЮ ЭНКОДЕРА **************//
void change_ugol()
{
valA=digitalRead(pinA); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)
valB=digitalRead(pinB); //Читает и запоминает текущее состояние на выходе энкодера (Выход В)
//РАСПОЗНАНИЕ ШАГА
if(valA+valB==HIGH){pulse=1;} //Определяет шаг и дает не стабилизированный импульс шага
else{pulse=0;}
//СТАБИЛИЗАТОР ИМПУЛЬСА ШАГА
if((pulse==HIGH)&&(zapret==LOW))//Условие работы стабилизатора выходного импульса
{
time = millis(); //Запуск таймера
outsig = HIGH; //Стабилизированый выходной импульс шага
}
zapret=HIGH;
if(outsig && (millis() - time) > 1) //(2)-Временная длинна выходного импульса
{
outsig = LOW;//Остановка таймера
}
if(pulse==LOW)
{
zapret=LOW; //Антидребезг
}
//ОПРЕДЕЛЕНИЕ ВСПОМОГАТЕЛЬНОЙ ПЕРЕМЕННОЙ
//ДЛЯ ОПРЕДЕЛЕНИЯ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
if((valA==LOW)&&(valB==LOW)&&(valA<1)&&(valB<1))
{
Estate=1;//Вспомогательная переменная для определения направления вращения энкодера на (+)
}
if((valA==HIGH)&&(valB==HIGH)&&(valA>0)&&(valB>0))
{
Estate=0;//Вспомогательная переменная для определения направления вращения энкодера на (-)
}
//ОПРЕДЕЛЕНИЕ НАПРАВЛЕНИЯ ВРАЩЕНИЯ
if(((Estate==1)&&(valA==LOW)&&(valB==HIGH))||((Estate==0)&&(valA==HIGH)&&(valB==LOW))) //Условия направления вращения(+)
{
Dir=1;//Направление вращения (+)
}
if(((Estate==1)&&(valA==HIGH)&&(valB==LOW))||((Estate==0)&&(valA==LOW)&&(valB==HIGH))) //Условия направления вращения(-)
{
Dir=0;//Направление вращения(-)
}
//ВЫХОДНОЙ СИГНАЛ
if((Dir==1)&&(outsig==HIGH)) //Условие поворота в одну из строн (Направление + стабилизированый сигнал шага)
{
angle=angle+angleStep; //угол поворота сервомотора меняется по шагово на заданную величину шага
if (angle > maxAngle)
{
angle=maxAngle;//Ограничитель угла поворота исполнительного устройства (Рабочий диапозон)
}
}
if((Dir==0)&&(outsig==HIGH)) //Все тоже самое как для предидущей функции но с !инверсией
{
angle=angle-angleStep; //угол поворота сервомотора меняется по шагово на заданную величину шага
if (angle < minAngle)
{
angle = minAngle; //Ограничитель угла поворота исполнительного устройства (Рабочий диапозон)
}
}
{
myservo.write(angle); //Входной сигнал на сервомотор
delay(stepSpeed);//Скорость шага (время задержки шага)
}
EEPROM.write(0, angle); //Сохраним в памяти угол поворота
}