"Слепил" скетч управления сервомашинкой с помощью механического энкодера. Энкодер использовал первый попавшийся- выпаял из платы управления магнитолой. За основу взял скетч с
этого ресурса. Алгоритм такой:
1.Нажали кнопку один раз-серва повернулась на максимальный угол (сохраненный в памяти).
1.1.Зашли в режим настройки угла сервы (энкодер).
2.Нажали еще раз-серва вернулась в начальную точку.
Угол сохраняется в памяти (Eeprom) и при следующем включении серва повернется на выставленный угол.
Удивительно, но работает...
PHP код:
#define pinA 3 //Первый PIN Сигнала с энкодера
#define pinB 4 //Второй PIN Сигнала с энкодера
#define pinC 10 //PIN кнопки запуска системы
#include <Servo.h>
#include <EEPROM.h>
Servo myservo; //Название сервомашины
int servoPin = 8; //Сервомотор подключен на PIN 8
int angle; //Текущий угол поворота (при запуске программы будет автоматический вставать в указаное положение)
int maxAngle = 90; //Максимальный угол поворота сервомотора (градусов)
int minAngle = 6; //Минимальный угол поворота сервомотора (градусов)
int angleStep = 2; //Угол единичного шага (градусов)
int stepSpeed = 3; //Скорость шага (Время задержки шага)
boolean valA=0; //Текущее переменное значение энкодера на выходе энкодера А
boolean valB=0; //Текущее переменное значение энкодера на выходе энкодера В
boolean valC=0; //Переменная функции запуска системы
boolean Estate=0; //Вспомогательная переменная необходимая для определения направления вращения
boolean pulse = 0; //Импульс шага в любом направлении, не стабилизированный
boolean Dir =0; //Переменная направления вращения (Если=1 то влево, если=0 то вправо)
boolean zapret=HIGH; //Вспомогательная переменная необходимая для стабилизации импульса шага
boolean outsig=HIGH; //Импульс шага в любом направлении, стабилизированный
long time; //Переменная таймера задержки в функции стабилизации
int flag = 0; // Флаг состояния
int regim = 0; // Переключалка
void setup()
{
angle = EEPROM.read(0);//Считываем из памяти угол поворота сервы
pinMode(pinC,INPUT_PULLUP); //Цифровой вход С кнопки запуска системы
pinMode(pinA,INPUT_PULLUP); //Цифровой вход A c энкодера
pinMode(pinB,INPUT_PULLUP); //Цифровой вход В c энкодера
}
void loop()
{
if(digitalRead(pinC) == LOW && flag == 0)//Если кнопка нажата
// и перемення flag равна 0 , то ...
{
regim ++;
flag = 1;//Это нужно для того что бы с каждым нажатием кнопки
//происходило только одно действие
if(regim > 4) // Если номер режима превышает требуемого
{ // то отсчет начинается с 1
regim = 1;
}
}
if(digitalRead(pinC) == HIGH && flag == 1)//если кнопка НЕ нажата
//и переменная flag равна - 1 ,то ...
{
flag = 0;
}
// РЕЖИМ 1:
if(regim == 1)// Нажали кнопку один раз...
{
myservo.attach(servoPin);
myservo.write(angle); // Серва повернулась на сохраненный в Eeprom угол
delay(stepSpeed);// Скорость поворота сервы
}
// РЕЖИМ 2:
if(regim ==2 )// Нажали кнопку второй раз...
{
change_ugol(); // Режим установки наклона с помощью энкодера
}
// РЕЖИМ 3:
if(regim == 3)// Нажали кнопку в третий раз...
{
}// ничего не происходит...
// РЕЖИМ 4:
if(regim == 4)// Нажали кнопку в четвертый раз...
{
myservo.write(maxAngle); // Серва вернулась в исходное состояние
delay(stepSpeed);// Скорость поворота сервы
}
}
// РЕЖИМ УСТАНОВКИ УГЛА НАКЛОНА С ПОМОЩЬЮ ЭНКОДЕРА
void change_ugol()
{
valA=digitalRead(pinA); //Читает и запоминает текущее состояние на выходе энкодера (Выход А)
valB=digitalRead(pinB); //Читает и запоминает текущее состояние на выходе энкодера (Выход В)
valC=digitalRead(pinC); //Читает и запоминает текущее состояние кнопки быстрой центровки
//РАСПОЗНАНИЕ ШАГА
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); //Сохраним в памяти угол поворота
}