Ошибка в коде на управление Серво
- Войдите на сайт для отправки комментариев
Вс, 25/12/2016 - 10:17
Такая проблема, слепил 2 кода для плавных поворотов серво, по отдельности работают отлично, но вместе очень глючино... Когда в void setup() комментируешь любую из двух строчек для назначения серво, то один код работает стабильно, то же самое наоборот.
Не могу совместить оба кода, что бы работали одновременно. Принцип кода: при длительном зажатии кнопов Влево-Вправо серво поворачивается пока не отпустишь, а при коротком нажатии кнопки вверх на пульте включаются автоповороты серво, при нажатии кнопки вниз - автоповороты откл.
Вот сам код:
#include <VarSpeedServo.h> // Библиотека для Servo-Мотора с регулировкой скорости
#include <IRremote.h> // Библиотека для ИК приёмника
byte RECV_PIN = 11; // вход ИК приемника
IRrecv irrecv(RECV_PIN); // Объект ИК
decode_results results;
VarSpeedServo servoPovorot; //даём имя servo
// переменные для контроля за процессом поворотов Servo
bool Right_Pin_1 = false; //для ручного поворота вправо при зажатии кнопки
bool Left_Pin_1 = false; //для ручного поворота влево при зажатии кнопки
bool Auto_Povorot = false; //для Автоповорота при кратковременном нажатии
class Sweeper
{
VarSpeedServo servoAutoPovorot; // сервопривод для автоповорота
int pos; // текущее положение сервы
int increment; // увеличиваем перемещение на каждом шаге
int updateInterval; // промежуток времени между обновлениями
unsigned long lastUpdate; // последнее обновление положения
public:
Sweeper(int interval)
{
updateInterval = interval;
increment = 1;
}
void attach(int pin)
{
servoAutoPovorot.attach(pin);
}
void detach()
{
servoAutoPovorot.detach();
}
void Update()
{
if ((millis() - lastUpdate) > updateInterval) // время обновлять
{
lastUpdate = millis();
pos += increment;
servoAutoPovorot.write(pos);
if ((pos >= 130) || (pos <= 0)) // конец вращения
{
// обратное направление
increment = -increment;
}
}
}
};
Sweeper servoAutoPovorot(35); // скорость Авто-вращения серво
/* Переменная для плавного вращения servo,чтобы не использовать delay.
промежуточная переменная для хранения (увеличенного диапазона от 0 до 20000)значений (увеличения или уменьшения)PWM,
с последующей конвертации в переменную(val_1) диапазон градусов поворота доступных для servo.*/
int L = 0;
//переменная для конвертации (увеличенного диапазона значений от 0 до 20000) (L),в значения требуемые для поворота servo.
int val_1;
//переменная для (увеличения или уменьшения)скорости поворота servo.
int speed_PWM = 1;
//переменная eventTime, для паузы, вместо delay,будем использовать функцию millis.
unsigned long eventTime = 0;
void setup()
{
irrecv.enableIRIn(); // включить ИК приёмник
servoPovorot.attach(9); // Servo подключён на цифровой вход (pin 9)
servoAutoPovorot.attach(9); // для автоповоротов класса Sweeper
}
void loop()
{
if (Auto_Povorot == true) { //Если Auto_Povorot истина...
servoAutoPovorot.Update(); // ...тогда включаем автоповорот серво
}
/* Делаем, что бы система работала в режиме удержания кнопки для Серво.
После приёма определённого кода кнопки,сразу перехватывать идущий за ним (кодом), (пустой инфракрасный сигнал)
и считать его - (пустой инфракрасный сигнал), за код кнопки.
После пропадания (пустого инфракрасного сигнала) - будем считать, что код перестал слаться.*/
/* 1. После приёма определённого кода кнопки, перехватывать (пустой инфракрасный сигнал).
2. Конвертировать пульсирующий (-) с (ИК) преемника сигнал в постоянный.
После появления и пропадания сигнала, состояние сразу не меняется! а ждет 100 миллисекунд.
Если 100 миллисекунд не прошло, и поступил еще один ИК сигнал с пульта,
тогда таймер заново запускается на 100 миллисекунд.*/
if (digitalRead(RECV_PIN) == LOW)
eventTime = millis();
if (millis() - eventTime > 100) (Right_Pin_1 = false), (Left_Pin_1 = false);
/* Если Right_Pin_1) ==, выставляем ограничение для переменной(L) до (&& L<20000) и начинаем увеличивать
значения переменной(L), на значение переменной speed_PWM,
и также выставляем ограничение при убывании (&& a>0).*/
if (Right_Pin_1 == true && L < 20000 ) L = L + speed_PWM;
if (Left_Pin_1 == true && L > 0 ) L = L - speed_PWM;
//читаем значение (L) и конвертируем его в значение val_1, то бишь в значение поворота в градусов доступных для servo.
val_1 = L;
val_1 = map(val_1, 0, 20000, 1, 130); // Задаём диапазон скорости и поворота Серво (углы поворота от 1 до 130 градусов)
servoPovorot.write(val_1); // Положение Серво в соответствии с val_1.
if (irrecv.decode(&results)) {
// 2 Команды с пульта отвечающие за ручные повороты Серво.
if (results.value == 0xFFC23D) Right_Pin_1 = true; // Поворот Вправо
if (results.value == 0xFF22DD) Left_Pin_1 = true; // Поворот Влуво
if (results.value == 0xFF629D) Auto_Povorot = true; //Автоповорот вкл.
if (results.value == 0xFFA857) Auto_Povorot = false; //Автоповорот откл.
irrecv.resume(); // получаем следующие значения
}
}
Ну это разумеется не то , но может пригодится.
/* Принцип кода: нажатие на кнопку 1 вкл авторотации сервы нажатие на кнопку 2 выкл авторотации сервы #2 Серва упр. выв -> 9 (servo_pin) +5В -> +5В GND -> GND #3 кнопка 1 -> 2 (btn1_pin) Влево 0 нажата /1 нет #4 кнопка 2 -> 3 (btn2_pin) Вправо 0 нажата /1 нет */ // #2 #include <Servo.h> Servo servo; const int servo_pin = 9 ;// нога сервы const int angle_min = 0 ;// 0 угол сервы const int angle_max = 180 ;// 180 угол сервы int angle = angle_min ;// angle_min..angle_max угол сервы const int angle_step = 5 ;// шаг поворота сервы bool auto_rotation = 0 ;// автоповорот 1 -включен / 0 -выключен bool dir = 0 ; // направление вращение автоповорота 0 -влево / 1 -вправо // #3 // короткое нажатие автоповорот вкл const int btn1_pin = 2; // вывод кнопки 1 Влево bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn1 = 0; // антидребезговый флаг // #4 // короткое нажатие автоповорот выкл const int btn2_pin = 3; // вывод кнопки 2 Вправо bool btn2, btn2_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn2 = 0; // антидребезговый флаг void setup() { Serial.begin(9600); // #2 servo.attach(servo_pin) ; // подключить серву servo.write(angle); ; // серву установить на нужный угол // #3 pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn1 = digitalRead(btn1_pin); // #4 pinMode(btn2_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn2 = digitalRead(btn2_pin); } void loop() { //#2 200 миллисекунд вычислит. поток 2 static uint32_t past_2 = 0 ; if (millis() - past_2 >= 200) { past_2 = millis() ; if (auto_rotation) { // если автоповорот включен if (dir) { // если вращение направо angle += angle_step; if (angle > angle_max) { angle -= angle_step; dir = 0; } } else { // если вращение налево angle -= angle_step; if (angle < angle_min) { angle += angle_step; dir = 1; } } servo.write(angle); } } // #3 static uint32_t past_3 = 0 ; if (! bounce_btn1 && btn1 != digitalRead(btn1_pin)) { // если прошел фронт изм на выводн bounce_btn1 = 1; // выставить флаг past_3 = millis(); // сделать временую засветку } else if ( bounce_btn1 && millis() - past_3 >= 40 ) { // если прошло антидребезговое время bounce_btn1 = 0; // то снять флаг btn1_old = btn1; btn1 = digitalRead(btn1_pin) ; // прочитать реальное значение на выводе if (btn1_old && ! btn1) { // если обнаружилось что это было нажатие auto_rotation = 1; // включить авторотацию Serial.println("Press btn1 down"); } } // #4 static uint32_t past_4 = 0 ; if (! bounce_btn2 && btn2 != digitalRead(btn2_pin)) { // если прошел фронт изм на выводн bounce_btn2 = 2; // выставить флаг past_4 = millis(); // сделать временую засветку } else if ( bounce_btn2 && millis() - past_4 >= 40 ) { // если прошло антидребезговое время bounce_btn2 = 0; // то снять флаг btn2_old = btn2; btn2 = digitalRead(btn2_pin) ; // прочитать реальное значение на выводе if (btn2_old && ! btn2) { // если обнаружилось что это было нажатие auto_rotation = 0; // выключить авторотацию Serial.println("Press btn2 down"); } } }Вот еще вариант
/* Принцип кода: нажатие на кнопку 1 поворот налево до упора нажатие на кнопку 2 поворот направо до упора #2 Серва упр. выв -> 9 (servo_pin) +5В -> +5В GND -> GND #3 кнопка 1 -> 2 (btn1_pin) Влево 0 нажата /1 нет #4 кнопка 2 -> 3 (btn2_pin) Вправо 0 нажата /1 нет */ // #2 #include <Servo.h> Servo servo; const int servo_pin = 9 ;// нога сервы const int angle_min = 0 ;// 0 угол сервы const int angle_max = 180 ;// 180 угол сервы int angle = angle_min ;// angle_min..angle_max угол сервы const int angle_step = 5 ;// шаг поворота сервы bool auto_rotation = 0 ;// автоповорот 1 -включен / 0 -выключен bool dir = 0 ;// направление вращение автоповорота 0 -влево / 1 -вправо // #3 // короткое нажатие автоповорот вкл const int btn1_pin = 2; // вывод кнопки 1 Влево bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn1 = 0; // антидребезговый флаг // #4 // короткое нажатие автоповорот выкл const int btn2_pin = 3; // вывод кнопки 2 Вправо bool btn2, btn2_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn2 = 0; // антидребезговый флаг void setup() { // #2 servo.attach(servo_pin) ; // подключить серву servo.write(angle); ; // серву установить на нужный угол // #3 pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn1 = digitalRead(btn1_pin); // #4 pinMode(btn2_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn2 = digitalRead(btn2_pin); } void loop() { //#2 200 миллисекунд вычислит. поток 2 static uint32_t past_2 = 0 ; if (millis() - past_2 >= 200) { past_2 = millis() ; if (! btn1 && btn2) { // если нажата кнопка 1 а кнопка 2 отпущена angle += angle_step; if (angle > angle_max) { angle -= angle_step; } servo.write(angle); } if (btn1 && ! btn2) { // если нажата кнопка 2 а кнопка 1 отпущена angle -= angle_step; if (angle < angle_min) { angle += angle_step; } servo.write(angle); } } // #3 static uint32_t past_3 = 0 ; if (! bounce_btn1 && btn1 != digitalRead(btn1_pin)) { // если прошел фронт изм на выводн bounce_btn1 = 1; // выставить флаг past_3 = millis(); // сделать временую засветку } else if ( bounce_btn1 && millis() - past_3 >= 40 ) { // если прошло антидребезговое время bounce_btn1 = 0; // то снять флаг btn1 = digitalRead(btn1_pin) ; // прочитать реальное значение на выводе } // #4 static uint32_t past_4 = 0 ; if (! bounce_btn2 && btn2 != digitalRead(btn2_pin)) { // если прошел фронт изм на выводн bounce_btn2 = 2; // выставить флаг past_4 = millis(); // сделать временую засветку } else if ( bounce_btn2 && millis() - past_4 >= 40 ) { // если прошло антидребезговое время bounce_btn2 = 0; // то снять флаг btn2 = digitalRead(btn2_pin) ; // прочитать реальное значение на выводе } }И 3 скетч совмещенный
/* Принцип кода: короткое нажатие на кнопку 1 вкл авторотации сервы короткое нажатие на кнопку 2 выкл авторотации сервы длиное нажатие на кнопку 1 медленный поворот направо до упора длиное нажатие на кнопку 2 медленный поворот налево до упора #2 Серва упр. выв -> 9 (servo_pin) +5В -> +5В GND -> GND #3 кнопка 1 -> 2 (btn1_pin) Влево 0 нажата /1 нет #4 кнопка 2 -> 3 (btn2_pin) Вправо 0 нажата /1 нет */ // #2 #include <Servo.h> Servo servo; const int servo_pin = 9 ;// нога сервы const int angle_min = 0 ;// 0 угол сервы const int angle_max = 180 ;// 180 угол сервы int angle = angle_min ;// angle_min..angle_max угол сервы const int angle_step = 2 ;// шаг поворота сервы bool auto_rotation = 0 ;// автоповорот 1 -включен / 0 -выключен bool dir = 0 ; // направление вращение автоповорота 0 -влево / 1 -вправо // #3 // короткое нажатие автоповорот вкл const int btn1_pin = 2; // вывод кнопки bool btn1, btn1_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn1 = 0; // антидребезговый флаг uint32_t time_btn1 ; // длительность нажатия const uint32_t const_time_btn1 = 200 ; // константа длительности нажатия ниже короткое нажатие выше длиное,миллисек // #4 // короткое нажатие автоповорот выкл const int btn2_pin = 3; // вывод кнопки bool btn2, btn2_old; // значение на кнопке без дребезга, тоже но стар значение bool bounce_btn2 = 0; // антидребезговый флаг uint32_t time_btn2 ; // длительность нажатия const uint32_t const_time_btn2 = 200 ; // константа длительности нажатия ниже короткое нажатие выше длиное,миллисек void setup() { // #2 servo.attach(servo_pin) ; // подключить серву servo.write(angle); ; // серву установить на нужный угол // #3 pinMode(btn1_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn1 = digitalRead(btn1_pin); // #4 pinMode(btn2_pin, INPUT_PULLUP); // подключить кнопку 1 с подтяжкой btn2 = digitalRead(btn2_pin); } void loop() { //#2 200 миллисекунд вычислит. поток 2 static uint32_t past_2 = 0 ; static uint32_t past1_3 = 0 ; // перенесена из потока #3 static uint32_t past1_4 = 0 ; // перенесена из потока #4 if (millis() - past_2 >= 100) { past_2 = millis() ; if (! btn1 && ( millis() - past1_3 > const_time_btn1 ) && btn2) { // если долго нажата кнопка 1, а кнопка 2 отпущена dir = 1; angle += angle_step; if (angle > angle_max) { angle -= angle_step; } servo.write(angle); } if (btn1 && ! btn2 && ( millis() - past1_4 > const_time_btn2 )) { // если долго нажата кнопка 2, а кнопка 1 отпущена dir = 0; angle -= angle_step; if (angle < angle_min) { angle += angle_step; } servo.write(angle); } if (auto_rotation) { // если автоповорот включен if (dir) { // если вращение направо angle += angle_step; if (angle > angle_max) { angle -= angle_step; dir = 0; } } else { // если вращение налево angle -= angle_step; if (angle < angle_min) { angle += angle_step; dir = 1; } } servo.write(angle); } } // #3 static uint32_t past_3 = 0 ; if (! bounce_btn1 && btn1 != digitalRead(btn1_pin)) { // если прошел фронт изм на выводн bounce_btn1 = 1; // выставить флаг past_3 = millis(); // сделать временую засветку } else if ( bounce_btn1 && millis() - past_3 >= 40 ) { // если прошло антидребезговое время bounce_btn1 = 0; // то снять флаг btn1_old = btn1; btn1 = digitalRead(btn1_pin) ; // прочитать реальное значение на выводе if (btn1_old && ! btn1) { // если обнаружилось что это было нажатие past1_3 = millis(); } if (! btn1_old && btn1) { // если обнаружилось что это было отжатие time_btn1 = millis() - past1_3; if (time_btn1 < const_time_btn1) // если было до этого короткое нажатие кнопки 1 auto_rotation = 1; // выключить авторотацию; } } // #4 static uint32_t past_4 = 0 ; if (! bounce_btn2 && btn2 != digitalRead(btn2_pin)) { // если прошел фронт изм на выводн bounce_btn2 = 2; // выставить флаг past_4 = millis(); // сделать временую засветку } else if ( bounce_btn2 && millis() - past_4 >= 40 ) { // если прошло антидребезговое время bounce_btn2 = 0; // то снять флаг btn2_old = btn2; btn2 = digitalRead(btn2_pin) ; // прочитать реальное значение на выводе if (btn2_old && ! btn2) { // если обнаружилось что это было нажатие past1_4 = millis(); } if (! btn2_old && btn2) { // если обнаружилось что это было отжатие time_btn2 = millis() - past1_4; if (time_btn2 < const_time_btn2) // если было до этого короткое нажатие кнопки 2 auto_rotation = 0; // выключить авторотацию; } } }