Сервы и ServoTimer2
- Войдите на сайт для отправки комментариев
Пнд, 19/09/2016 - 20:52
Доброго времени суток! Вопрос- как при использовании библиотеки ServoTimer2 задать серве конкретный угол?
Прежде чем задать вопрос тут я прочел http://arduino.ru/forum/obshchii/prezhde-chem-sprosit-pro-servomashinku-servo-posmotri-tut. Ответа не нашел.
На одном из источников я нашел:
"Положение выходного вала сервомотора определяется длиной импульса. Серва может получать импульсы каждые 20 миллисекунд. Если импульс high длится 1 миллисекунду, угол поворота сервы будет равен нулю. Если 1.5 миллисекунды, тогда серва выйдет в свое центральное положение, а если 2 миллисекунды - выйдет в положение, которое соответствует 180 градусам"
Основываясь на этом написал такой скеч
void Rotate(){
val_1 = analogRead(joy1);
delay(10); //recomanen posar-ho
val_2 = analogRead(joy2);
pos_1 = map (val_1, 0, 1024 , 1000, 2000);
pos_2 = map (val_2, 0, 1024 , 1000, 2000);
myservo_1.write(pos_1);
myservo_2.write(pos_2);
Серва вращается, но не от 0 до 180 а примерно с 30 до 130 градусов.
Есть еще вот такой алгоритм:
void Rotate(){
val_1 = analogRead(joy1);
delay(10); //recomanen posar-ho
val_2 = analogRead(joy2);
pos_1 = 3000 - (500 + val_1 * 1.8);
pos_2 = 500 + val_2 * 1.8;
myservo_1.write(pos_1);
myservo_2.write(pos_2);
Я его не понимаю, но серва ходит в пределах от 10 до 170 градусов.
Как правильно дать команду. как расчитать и задать угол поворота сервы с библиотекой ServoTimer2 ?
Есть в среде Ардуино маленький секрет. Образцы->Servo->Knob. А там есть код
#include <Servo.h> Servo myservo; int potpin = 0; int val; void setup() { myservo.attach(9); } void loop() { val = analogRead(potpin); val = map(val, 0, 1023, 0, 180); // обрати на 0 и 180. Вот это и есть угол поворота myservo.write(val); delay(15); }Но ардуина не может выдавать аналоговый сигнал на выход. Она выдает PWM сигнал, который и заменяет его.
qwone - спасибо Вам за проявлый интерес к вопросу, но, либо я не понял Ваш ответ, либо вы вопрос не поняли.
С библиотекой Servo.h я уже знаком и выставить там угол поворота сервы таки да, не проблема.
Вопрос по ServoTimer2.h , тут не так, как в Вашем примере
pos_1 = map (val_1, 0, 1024 , 700, 2200); Не в градусах а в милисекундах?
При такой формуле Серва начинает двигаться в диапазоне значений pos_1 от 800 до 2100. но опять не поворачивается ни к 0, ни к 180.
Попробовал еще и такой код
for (int i=0; i <= 600; i++) { val = val +5; servoRoll.write(val); Serial.print("Val 1 = " ); Serial.print(val); Serial.print("\n " ); delay(100); }все равно серва на 0 и 180 не становится.
Может библиотека левая? Руки и мозх понятно, но уже должно было получиться.
У серв есть разброс параметров.
Нередко - весьма значительный.
Вам нужно всего навсего подобрать экспериментально, какие числа нужно подавать на вход конкретной сервы, чтобы она повернулась на нужный угол.
Рассчитать это в принципе невозможно.
И для другой сервы числа придется подбирать другие.
Но ведь с библиотекой Servo.h все работает на этих же сервах !
я подключал 2 разные
Если ориентироваться на это http://github.com/nabontra/ServoTimer2/blob/master/examples/threeservos/threeservos.ino
#define rollPin 2 //без PWM #define pitchPin 3//c PWM #define yawPin 4 //без PWM ServoTimer2 servoRoll; // declare variables for up to eight servos ServoTimer2 servoPitch; ServoTimer2 servoYaw; void setup() { servoRoll.attach(rollPin); // attach a pin to the servos and they will start pulsing servoPitch.attach(pitchPin); servoYaw.attach(yawPin); // то аналоговый сигнал на сервы делается программно. От туда и косякине совсем понятно - если с одной библиотекой работает зачем лезть в другую ?
В другую библиотеку пришлось залезть из-за того, что стандартная Servo конфликтует с VirtualWire , так как используют один и тот же таймер. А мне нужны обе.
По существу вопроса, к сожалению подсказки нет :(
Надо в теме писать "Помогите..."
Вопрос по форуму: возможно ли изменить стартовое сообщение? что бы там накапливать все возникшие вопросы и, возможно, финальный правильный ответ, чтобы не листать весь топик, в котором ответ может быть где-то посередине.
Доброго времени суток! Вопрос- как при использовании библиотеки ServoTimer2 задать серве конкретный угол?
void Rotate(){ val_1 = analogRead(joy1); delay(10); //recomanen posar-ho val_2 = analogRead(joy2); pos_1 = map (val_1, 0, 1024 , 1000, 2000); pos_2 = map (val_2, 0, 1024 , 1000, 2000); myservo_1.write(pos_1); myservo_2.write(pos_2);Серва вращается, но не от 0 до 180 а примерно с 30 до 130 градусов.
Как правильно дать команду. как расчитать и задать угол поворота сервы с библиотекой ServoTimer2 ?
в библе написано
#define MIN_PULSE_WIDTH 750 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2250 // the longest pulse sent to a servo
а вы влепили от 1000 до 2000
Да. Указанный интервал я определил экспериментально. Но и с ним в начальной и конечную позиции снова не приходит. Буду пробовать с другими сервами. Т.е. если интервал значений от 750 до 2250, то 90 градусов это 1500. А 45 это 1125. Во! Сам понял :)
а от 1000 до 2000 быыло в примере библиотеки
ПАМАГИТЕ ! :)
Серва все равно движется в диапазоне от 30 до 150 градусов. На 0 и 180 не доходит.
Поставил обратно Servo.h и все кул. от 0 до 175 отлично ходит (хотя вручную бе питания можно довернуть где-то до 200)
Таки дело в калеченной библиотеке :(
для 995 сервы встречал такие парметры: 0-500мкс, а 180-2500 мкс, так примерно и поворачивается 1 градус где-то 10-11мкс
вот такие параметры
#define MIN_PULSE_WIDTH 750 // the shortest pulse sent to a servo
#define MAX_PULSE_WIDTH 2250 // the longest pulse sent to a servo
как раз и отсекают около 25 град туда сюда
для проверки заливаешь скетч, взят где-то на просторах инета, и смотришь, как оно работает без вясяких библиотек.
Подбираешь свои времена, если требуется
int servoPin = 9; // порт подключения сервы int myAngle; // будет хранить угол поворота int pulseWidth; // длительность импульса void servoPulse(int servoPin, int myAngle) { pulseWidth = (myAngle * 10) + 500; // конвертируем угол в микросекунды digitalWrite(servoPin, HIGH); // устанавливаем серве высокий уровень delayMicroseconds(pulseWidth); // ждём digitalWrite(servoPin, LOW); // устанавливаем низкий уровень delay(20); // } void setup() { pinMode(servoPin, OUTPUT); // конфигурируем пин сервы, как выход } void loop() { // медленно поворачиваем серву от 0 до 180 градусов for (myAngle=0; myAngle<=180; myAngle++) { servoPulse(servoPin, myAngle); } delay(500); // а теперь обратно for (myAngle=180; myAngle>=0; myAngle--) { servoPulse(servoPin, myAngle); } delay(500); }Ну да.
Когда подружить библиотеки не удается, самый простой способ - отказаться от них совсем.
Спасибо !
Буду пробовать! А то я даже не сообразил в принципе поискать как управлять сервой без библиотеки .
Не, я вчера хотел попробовать, но сегодня открыл файл библиотеки, мало что понял и решил что это должно быть дюже сложно, управлять напрямую.
Спасибо за ценный совет. Библиотеки наверное удобно, но тут лучше ручками попробую.
pulseWidth = (myAngle * 10) + 500;// конвертируем угол в микросекундыпоставил +400 и все сошлось. почти полные от 0 до 180/* Пульт радиоуправляемой машинки - Arduino NANO Подключены устройства вывода - LCD 128x64 i2c - серво ввода - Джойстик 2 шт - Кнопка */ /* Подключаем передатчик и библиотеку RadioHead - не пашет совместно с Adafruit_SSD1306. как и VirtualWire Добавим Серво без библиотек, уберем дисплей */ //подключаем библиотеки //////////////////////////// #include <Wire.h> #include <SPI.h> //Библиотека (Serial Peripheral Interface), или последовательный периферийный интерфейс //#include <Servo.h> int servoPin_1 = 6; float pos_1 ; float pos_2 ; int myAngle; // будет хранить угол поворота int pulseWidth; // длительность импульса //#include <Adafruit_GFX.h> //Библиотека экрана //#include <Adafruit_SSD1306.h> //Библиотека экрана #include <RH_ASK.h> #include <SPI.h> RH_ASK driver; ////Определение Экрана //#define OLED_RESET 4 //Adafruit_SSD1306 display(OLED_RESET); //#define NUMFLAKES 10 //#define XPOS 0 //#define YPOS 1 //#define DELTAY 2 //#if (SSD1306_LCDHEIGHT != 64) //#error("Height incorrect, please fix Adafruit_SSD1306.h!"); //#endif // Пины и переменные #define Joy_1_Pin_X A0 // Джойстик 1 Ось Х #define Joy_1_Pin_Y A1 // Джойстик 1 Ось Y #define Joy_1_Pin_Sw 7 // Джойстик 1 SW #define Joy_2_Pin_X A2 // Джойстик 2 Ось Х #define Joy_2_Pin_Y A3 // Джойстик 2 Ось Y #define Joy_2_Pin_Sw 8 // Джойстик 2 SW #define Sw_1_Pin 10 // Кнопка 1 int Joy_1_Val_X ; int Joy_1_Val_Y ; int Joy_1_Val_Sw ; int Joy_2_Val_X ; int Joy_2_Val_Y ; int Joy_2_Val_Sw ; int Sw_1_Val ; /// Определяем передатчик struct SEND_DATA_STRUCTURE{ int Joy_1_Val_X ; int Joy_1_Val_Y ; int Joy_1_Val_Sw ; }; SEND_DATA_STRUCTURE mydata; byte tx_buf[sizeof(mydata)] = { 0}; ////******убираем к чертям DELAY****Спасибо г-н Клапауций 322 http://arduino.ru/forum/programmirovanie/klass-titanovyi-velosiped-dlya-... long previousMillis = 0; // храним время последнего действия чтением датчиков long interval = 200; // интервал между чтением датчиков void setup() { Serial.begin(9600); Serial.println("test start!"); // только для отладки if (!driver.init()) Serial.println("init failed"); // myservo_1.attach(servoPin_1); // attaches the servo on pin 6 pinMode(servoPin_1, OUTPUT); // конфигурируем пин сервы, как выход pinMode (Joy_1_Pin_Sw, INPUT); pinMode (Joy_2_Pin_Sw, INPUT); digitalWrite(Joy_1_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор digitalWrite(Joy_2_Pin_Sw, HIGH); // включаем встроенный подтягивающий резистор pinMode (Sw_1_Pin, INPUT); digitalWrite(Sw_1_Pin, HIGH); // включаем встроенный подтягивающий резистор // display.begin(SSD1306_SWITCHCAPVCC, 0x3C); // initialize with the I2C addr 0x3С (for the 128x64) // display.display(); // delay(200); // display.clearDisplay(); // display.setTextSize(1); // display.setTextColor(WHITE); // display.clearDisplay(); } /* --(end setup )-- */ void loop() { unsigned long currentMillis = millis(); if(currentMillis - previousMillis > interval) { READ_DATA(); previousMillis = currentMillis; // сохраняем время последнего переключения } // LCD_PRINT (); myAngle = map (Joy_1_Val_X, 0, 1021 , 0, 180); servoPulse(servoPin_1, myAngle); mydata.Joy_1_Val_X = Joy_1_Val_X; mydata.Joy_1_Val_Y = Joy_1_Val_Y; mydata.Joy_1_Val_Sw = Joy_1_Val_Sw; memcpy(tx_buf, &mydata, sizeof(mydata) ); byte size_mydata = sizeof(mydata); driver.send((uint8_t *)tx_buf, size_mydata); driver.waitPacketSent(); Serial.print ("Joy_1_Val_X :"); Serial.print (Joy_1_Val_X); Serial.print ("Joy_1_Val_Y :"); Serial.print (Joy_1_Val_Y); Serial.print ("myAngle :"); Serial.print (myAngle); Serial.print ("pulseWidth :"); Serial.print (pulseWidth); Serial.print ("\n"); // delay (200); } /* --(end main loop )-- */ ////////////////////////////////////////////////////////////////////////////////////////////////// /*-----( Declare User-written Functions )-----*/ void servoPulse(int servoPin_1, int myAngle) { pulseWidth = (myAngle * 10) + 400; // конвертируем угол в микросекунды digitalWrite(servoPin_1, HIGH); // устанавливаем серве высокий уровень delayMicroseconds(pulseWidth); // ждём digitalWrite(servoPin_1, LOW); // устанавливаем низкий уровень delay(20); // } void READ_DATA () { Joy_1_Val_X = analogRead(Joy_1_Pin_X); //// Джойстик 1 Ось Х delay(10); //recomanen posar-ho Joy_1_Val_Y = analogRead(Joy_1_Pin_Y); //// Джойстик 1 Ось Х delay(10); //recomanen posar-ho Joy_1_Val_Sw = digitalRead (Joy_1_Pin_Sw); //Джойстик 1 SW // Joy_2_Val_X = analogRead(Joy_2_Pin_X); //// Джойстик 2 Ось Х // delay(10); //recomanen posar-ho // Joy_2_Val_Y = analogRead(Joy_2_Pin_Y); //// Джойстик 2 Ось Х // delay(10); //recomanen posar-ho // Joy_2_Val_Sw = digitalRead (Joy_2_Pin_Sw); //Джойстик 2 SW // // Sw_1_Val = digitalRead (Sw_1_Pin); //Кнопка 1 } //void LCD_PRINT () //{ // display.setCursor(0,0); // display.print("Joy_1_X: "); // display.print(Joy_1_Val_X); // display.setCursor(0,15); // display.print("Joy_1_Y: "); // display.print(Joy_1_Val_Y); // display.setCursor(80,15); // display.print("SW_1: "); // display.print(Joy_1_Val_Sw); // // display.setCursor(0,30); // display.print("Joy_2_X: "); // display.print(Joy_2_Val_X); // display.setCursor(0,45); // display.print("Joy_2_Y: "); // display.print(Joy_2_Val_Y); // display.setCursor(80,45); // display.print("SW_2: "); // display.print(Joy_2_Val_Sw); // // display.setCursor(0,55); // display.print("Swich_1: "); // display.print(Sw_1_Val); // // display.display(); // display.clearDisplay(); //}Все равно проблема осталась, экран в такой конфигурации библиотек не работает.
Значит, нужно избавиться от следующей библиотеки. :)
Ага, удалить библиотеку. Да и саму ардуинку в ящик и на балкон.
Я в этих таймерах (и не только) дуб-дубом. Вот на другой странице ЕвгенийП разъясняет, но там не для чайников, наверное.
Тоже про адафрутную библиотеку и RadioHead.
Таймер нашел, поменял в RH_ASK.cpp, но вот что там пишут про Header file - не понял.
// Should be moved to header file
#define RH_ASK_ARDUINO_USE_TIMER2
Экранчик запустился, но фигню показывает. С другой стороны, зачем на пульте с односторнней связью экран? только для отладки. Выбросил.
Спаисбо, ВН, Ваша рекомендация работает. Серва безупречна!