Сервы и ServoTimer2

popUP
Offline
Зарегистрирован: 09.10.2014

Доброго времени суток! Вопрос- как при использовании библиотеки  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 ?

 

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Есть в среде Ардуино маленький секрет.  Образцы->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 сигнал, который и заменяет его.

popUP
Offline
Зарегистрирован: 09.10.2014

qwone - спасибо Вам за проявлый интерес к вопросу, но, либо я не понял Ваш ответ, либо вы вопрос не поняли.

С библиотекой Servo.h я уже знаком и выставить там угол поворота сервы таки да, не проблема.

Вопрос по ServoTimer2.h , тут не так, как в Вашем примере

pos_1 = map (val_1, 0, 1024 , 700, 2200);   Не в градусах а в милисекундах?

При такой формуле Серва начинает двигаться в диапазоне значений pos_1 от 800 до 2100. но опять не поворачивается ни к 0, ни к 180. 

 

popUP
Offline
Зарегистрирован: 09.10.2014

Попробовал еще и такой код

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 не становится.

Может библиотека левая? Руки и мозх понятно, но уже должно было получиться.

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

У серв есть разброс параметров.

Нередко - весьма значительный.

Вам нужно всего навсего подобрать экспериментально, какие числа нужно подавать на вход конкретной сервы, чтобы она повернулась на нужный угол.

Рассчитать это в принципе невозможно.

И для другой сервы числа придется подбирать другие.

popUP
Offline
Зарегистрирован: 09.10.2014

Но ведь с библиотекой Servo.h все работает на этих же сервах !

я подключал 2 разные

qwone
qwone аватар
Offline
Зарегистрирован: 03.07.2016

Если ориентироваться на это 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); 

// то аналоговый сигнал на сервы делается программно. От туда и косяки

 

vvadim
Offline
Зарегистрирован: 23.05.2012

не совсем понятно - если с одной библиотекой работает зачем лезть в другую ?

popUP
Offline
Зарегистрирован: 09.10.2014

В другую библиотеку пришлось залезть из-за того, что стандартная Servo конфликтует с VirtualWire , так как используют один и тот же таймер. А мне нужны обе.

По существу вопроса, к сожалению подсказки нет :(

Надо в теме писать "Помогите..."

Вопрос по форуму: возможно ли изменить стартовое сообщение? что бы там накапливать все возникшие вопросы и, возможно, финальный правильный ответ, чтобы не листать весь топик, в котором ответ может быть где-то посередине.

vvadim
Offline
Зарегистрирован: 23.05.2012

popUP пишет:

Доброго времени суток! Вопрос- как при использовании библиотеки  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

popUP
Offline
Зарегистрирован: 09.10.2014

Да. Указанный интервал я определил экспериментально. Но и с ним в начальной и конечную позиции снова не приходит. Буду пробовать с другими сервами. Т.е. если интервал значений от 750 до 2250, то 90 градусов это 1500. А 45 это 1125. Во! Сам понял :)

а от 1000 до 2000 быыло в примере библиотеки

popUP
Offline
Зарегистрирован: 09.10.2014

ПАМАГИТЕ ! :)

Серва все равно движется в диапазоне от 30 до 150 градусов. На 0 и 180 не доходит.

Поставил обратно Servo.h и все кул. от 0 до 175 отлично ходит (хотя вручную бе питания можно довернуть где-то до 200)

Таки дело в калеченной библиотеке :(

ВН
Offline
Зарегистрирован: 25.02.2016

для 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);
}  

 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Ну да.

Когда подружить библиотеки не удается, самый простой способ - отказаться от них совсем.

popUP
Offline
Зарегистрирован: 09.10.2014

Спасибо !

Буду пробовать! А то я даже не сообразил в принципе поискать как управлять сервой без библиотеки .

Не, я вчера хотел попробовать, но сегодня открыл файл библиотеки, мало что понял и решил что это должно быть дюже сложно, управлять напрямую.

Спасибо за ценный совет. Библиотеки наверное удобно, но тут лучше ручками попробую.

popUP
Offline
Зарегистрирован: 09.10.2014

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();
//}


Все равно проблема осталась, экран в такой конфигурации библиотек  не работает. 

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

Значит, нужно избавиться от следующей библиотеки. :)

popUP
Offline
Зарегистрирован: 09.10.2014

Ага, удалить библиотеку. Да и саму ардуинку в ящик и на балкон.

Я в этих таймерах (и не только) дуб-дубом. Вот на другой странице  ЕвгенийП  разъясняет, но там не для чайников, наверное. 

Тоже про адафрутную библиотеку и RadioHead.

Таймер нашел, поменял в RH_ASK.cpp, но вот  что там пишут про Header file  - не понял.     

// Should be moved to header file   

#define RH_ASK_ARDUINO_USE_TIMER2

Экранчик запустился, но фигню показывает. С другой стороны, зачем на пульте с односторнней связью экран? только для отладки. Выбросил.

 

popUP
Offline
Зарегистрирован: 09.10.2014

Спаисбо,  ВН, Ваша рекомендация работает. Серва безупречна!