Автопилот
- Войдите на сайт для отправки комментариев
Пт, 17/01/2014 - 16:42
Пишу небольшой автопилот. Возникла небольшая проблема с подергиванием серв. Вот код:
#include <TinyGPS++.h> #include <SoftwareSerial.h> #include <Servo.h> //объекты серво Servo servo_1; Servo servo_2; //объявление постоянных констант static const int RXPin = 11, TXPin = 12; //пины для serial gps static const unsigned long GPSBaud = 9600; //baudrate для gps static const unsigned long COMBaud = 9600; //baudrate для com //объявление константных переменных финальной точки const double fin_lat = 54.512431; //финальные координаты LAT const double fin_lon = 36.274083; //финальные координаты LON //переменные double lat, lon; //текущие lat, lon double course, azimuth; //курс, азимут float alt, speed; //высота, скорость int er_com = 10; //переменная погрешность при сравнивании углов int servo_pos;//текущая позиция сервы //объекты TinyGPSPlus gps; //новый объект для GPS SoftwareSerial gpsSerial(RXPin, TXPin); //программное сериал соединение для GPS void setup() { Serial.begin(COMBaud); //открываем serial с компьютером gpsSerial.begin(GPSBaud); //serial для GPS //объекты серв servo_1.attach(9); servo_2.attach(10); //полет по прямой до получения координат GPS servo_1.write(90); servo_2.write(90); Serial.println("START"); //отсылаем финальные координаты Serial.print("F_LAT="); Serial.print(fin_lat, 6); Serial.print(" "); Serial.print("F_LON="); Serial.print(fin_lon, 6); Serial.print(" "); Serial.println(); } void loop() { unsigned long start = millis(); if (gpsSerial.available() > 0) if (gps.encode(gpsSerial.read())){ get_gps_info(); //получение данных GPS servo_set(); //выбор направления } }//endloop //функция получения данных по GPS void get_gps_info() { lat = gps.location.lat(); //определение LAT lon = gps.location.lng(); //определение LON alt = gps.altitude.meters(); //высота speed = gps.speed.kmph(); //скорость course = gps.course.deg(); //курс unsigned long date = gps.date.value(); //дата unsigned long time = gps.time.value(); //время azimuth = gps.courseTo(gps.location.lat(), gps.location.lng(), fin_lat, fin_lon); } //перевод серв void servo_set(){ //выставление серв if (abs(course - azimuth) <= er_com / 2){ servo_1.write(90); servo_2.write(90); Serial.println("SERVO_POS=middle;"); // Отладка } else if (sin((azimuth - course)*PI/180.0) <= 0.0000001){ servo_1.write(180); servo_2.write(90); Serial.println("SERVO_POS=left;"); // Отладка }else{ servo_1.write(90); servo_2.write(180); Serial.println("SERVO_POS=right;"); // Отладка } }
Вот видео работы:
http://www.youtube.com/watch?v=yoa7B7GMUyc
каждую секунду приходит пакет и серва дергается, почему так?
Все упирается в использовании программного UARTa потому как при передаче или приеме данных библиотека SoftwareSerial глобально запрещает прерывания, в результате останавливается и генерация сигнала для сервы. Выход - подключить GPS-модуль к аппаратному UARTу (Serial), то бишь к выводам 0(RX) и 1(TX).
а если использовать NewSoftSerial вместо SoftwareSerial проблема сохраниться?
или как еще можно это решить, а то очень уж нужен программый Serial
Все упирается в использовании программного UARTa потому как при передаче или приеме данных библиотека SoftwareSerial глобально запрещает прерывания, в результате останавливается и генерация сигнала для сервы. Выход - подключить GPS-модуль к аппаратному UARTу (Serial), то бишь к выводам 0(RX) и 1(TX).
Приём, насколько я вижу, там в прерывании сделан, а вот передача делает cli(), да.
yah библиотека NewSoftSerial уже является частью стандартной библиотеки ардуино, начиная с версии 1.0, насколько я могу прочитать на сайте и в гитхабе.
Один из камментов к NewSoftSerial может навести на мысль:
Mike, yeah, I’m afraid both [New]SoftSerial and the current Servo motor library use interrupts in ways that are not mutually compatible. However, if your design has two or fewer servos and you can tolerate them being fixed to certain pins, the OLD servo library (posted on this site as PWMServo) might solve your problem…
Приём, насколько я вижу, там в прерывании сделан
Так что тоже блокинг.
или как еще можно это решить, а то очень уж нужен программый Serial
Либо писать неблокирующий программный UART на таймере, либо сервами управлять не в прерывании, а генерить ШИМ на аппаратных выводах таймера.
А вот и одно готовое решение - http://playground.arduino.cc/ComponentLib/Servotimer1, но так как подключать можно сервы только к 9 и 10 выводам, то данный вариант подходит только если у вас всего 2 сервы.
С Servotimer1 ничего не получилось выдает одни ошибки
вот нашел описание такой же ошибок http://pharos.ece.utexas.edu/wiki/index.php/Conflict_Between_Servo_and_Software_Serial_Libraries_-_02/15/2012#Solutions
но решения своей так и не нашел
С Servotimer1 ничего не получилось выдает одни ошибки
но решения своей так и не нашел
- У меня проблема - не заводится машина
- Надо залить бензин
- Не, бензин залить не получилось - не знаю как и куда, вот у кого то тоже не заводится (ссылка),
но решения своей так и не нашел