Проблемы с motor shield V3 и Servo

techmike
Offline
Зарегистрирован: 27.02.2013

Добрый день.

Имеется:

Arduino uno v3

motor shield V3 http://www.ebay.com/itm/V3-Motor-controller-Shield-L298N-2-motors-Arduino-compatible-/180882914565?pt=LH_DefaultDomain_0&hash=item2a1d763d05

Sensor Shield V4.0 http://www.odduino.com/shop/82/desc/arduino-sensor-shield-v4-0

Еще дополнительно подключен HC-SR04, с ним проблем нет.

Если использовать ШИМ для управления DC моторами то проблем нет, скорость регулируется, направления вращения меняются.

Если же задействовать библиотеку Servo.h, то двигатели перестают стартовать. Отловил это специально, отключая все используемые надстройки.

Т.е. проблемы в конфликте ШИМ для motor shield и библиотеки Servo.

Пробовав вешать сервомашинку на другие порты, результата не дало. В датащите на ATmega328 и описании Arduino Uno черным по английски три независимых таймера и возможностью генерировать ШИМ на 6 выходах.

motor shield V3 использует выходы с 13 по 8 включительно, ШИМ подается на 9 и 10. Сервомашинка работает на пинах с 1 по 7 но при этом не работают DC моторы.

Весь код скетча ниже, что предложите для запуска управления DC моторами с регулировкой скорости и использования одной сервомашинки?

// motor A
int dir1PinA = 13;
int dir2PinA = 12;
int speedPinA = 10;
// motor B
// motor A
int dir1PinB = 11;
int dir2PinB = 8;
int speedPinB = 9;
unsigned long time;
int speed;
int dir;
int delay_count;
int left_distance;
int rigth_distance;
int front_distance;

#include <Servo.h> 
#include <Ultrasonic.h> 

Servo myservo;  // create servo object to control a servo 
                // a maximum of eight servo objects can be created 
Ultrasonic ultrasonic(6, 5); // номера пинов к которым подключены выводы Trig и Echo, соответственно


void setup() {
  pinMode(dir1PinA, OUTPUT);
  pinMode(dir2PinA, OUTPUT);
  pinMode(speedPinA, OUTPUT);
  pinMode(dir1PinB, OUTPUT);
  pinMode(dir2PinB, OUTPUT);
  pinMode(speedPinB, OUTPUT);
  time = millis();
  speed = 0; // максимум 255
  dir = 1;
 delay_count=0;
 myservo.attach(1);  // attaches the servo on pin 7 to the servo object 
 myservo.write(90);  // ставим сервопривод смотрящим вперед
 Serial.begin(9600);                           // start the serial port
 Serial.println("START");                     
}

void forward() {
 digitalWrite(dir1PinA, HIGH);
 digitalWrite(dir2PinA, LOW);
 digitalWrite(dir1PinB, HIGH);
 digitalWrite(dir2PinB, LOW);
}

void back() {
 digitalWrite(dir1PinA, LOW);
 digitalWrite(dir2PinA, HIGH);
 digitalWrite(dir1PinB, LOW);
 digitalWrite(dir2PinB, HIGH);
}

void stop_dc() {
analogWrite(speedPinA,0);
analogWrite(speedPinB,0);
// digitalWrite(dir1PinA, LOW);
// digitalWrite(dir2PinA, LOW);
// digitalWrite(dir1PinB, LOW);
// digitalWrite(dir2PinB, LOW);
}

void left() {
 digitalWrite(dir1PinA, HIGH);
 digitalWrite(dir2PinA, LOW);
 digitalWrite(dir1PinB, LOW);
 digitalWrite(dir2PinB, HIGH);
}

void rigth() {
 digitalWrite(dir1PinA, LOW);
 digitalWrite(dir2PinA, HIGH);
 digitalWrite(dir1PinB, HIGH);
 digitalWrite(dir2PinB, LOW);
}

void loop() {
//delay(1000); 
analogWrite(speedPinA,speed);
analogWrite(speedPinB,speed);

  // set direction
  if (1 == dir) {
   forward();
  } 
  else if (0 == dir) {
   back();
  }
  else if (2 == dir) {
   left();
  }
  else if (3 == dir) {
   rigth();
  }

if (millis() - time > 5000) {
time = millis();
speed += 20;
 if (speed > 255) {
  speed = 0;
 }
}

front_distance=ultrasonic.Ranging(CM); // получаем расстояние до объекта в сантиметрах
Serial.write("FRONT: ");
Serial.println(front_distance);                      // print the distance

  if ((front_distance<=30) && (front_distance!=0)) {
   Serial.write("SPEED: ");
   Serial.println(speed);
   stop_dc(); // останавливаем робота 
   myservo.write(0);  // ставим сервопривод смотрящим влево
   delay(500); 
   left_distance=ultrasonic.Ranging(CM); // получаем расстояние до объекта в сантиметрах
   //delay(30); 
   Serial.write("LEFT: ");
   Serial.println(left_distance);                      // print the distance
   myservo.write(180);  // ставим сервопривод смотрящим влево
   delay(500); 
   rigth_distance=ultrasonic.Ranging(CM); // получаем расстояние до объекта в сантиметрах
   //delay(30); 
   Serial.write("RIGTH: ");
   Serial.println(rigth_distance);                      // print the distance
   myservo.write(90);  // ставим сервопривод смотрящим вперед
   delay(500); 
  if (left_distance>rigth_distance) {
   Serial.println("TURN_LEFT START");
    left(); //поворачиваем влево
    delay(1000); 
    stop_dc(); // останавливаем робота 
    dir=1; // едем прямо
    Serial.println("TURN_LEFT STOP");
  }else {
    Serial.println("TURN_RIGTH START");
    rigth(); //поворачиваем влево
    delay(1000); 
    stop_dc(); // останавливаем робота 
    dir=1; // едем прямо
    Serial.println("TURN_RIGTH STOP");
  }
 }

}

 

maksim
Offline
Зарегистрирован: 12.02.2012

Так почему бы не соеденить 10 вывод с любым другим ШИМ выводом?

techmike
Offline
Зарегистрирован: 27.02.2013

maksim пишет:

Так почему бы не соеденить 10 вывод с любым другим ШИМ выводом?

Я же не против соеденить, только как?

При настройке бибилиотек или создании классов "соединение" уже прописано в коде, у меня почемуто возникает конфликт и понять что не так делаю не получается.

techmike
Offline
Зарегистрирован: 27.02.2013

Еще забыл написать, что в текущей ситуации можно включить DC двигатели на максимум оборотов или выключить совсем, например вот так:

// включить двигатели на максимум оборотов
analogWrite(speedPinA,255);
analogWrite(speedPinB,255);

// выключить двигатели
analogWrite(speedPinA,0);
analogWrite(speedPinB,0);

Т.е. не рабтаешь ШИМ регулирование оборотов на motor shield V3 и пины на неё переназначить нельзя.

maksim
Offline
Зарегистрирован: 12.02.2012

Не программно соединить, а физически - проводами. Соединяете проводами 6 вывод с 10 выводом и 5 с 9. Переподключаете сонар на другие выводы.

// motor A
int dir1PinA = 13;
int dir2PinA = 12;
int speedPinA = 6;
// motor B
int dir1PinB = 11;
int dir2PinB = 8;
int speedPinB = 5;

Ultrasonic ultrasonic(4, 3);

Есть конечно и программные решения, но они более сложные и не желательные:
1. Найти (или написать) библиотеку типа Servo для 8-ми битного таймера - что снизит точность позиционирования сервы.
2. Сгенерить программный ШИМ на другом таймере - что тоже не есть хорошо ,так как такой ШИМ на больших частотах съедает очень много процессорного времени - http://arduino.ru/forum/programmirovanie/analogwrite-na-lyubom-vyvode данная либа использует TIMER2 и не конфликтует с библиотекой Servo.

techmike
Offline
Зарегистрирован: 27.02.2013

maksim пишет:

Есть конечно и программные решения, но они более сложные и не желательные:

1. Найти (или написать) библиотеку типа Servo для 8-ми битного таймера - что снизит точность позиционирования сервы.
2. Сгенерить программный ШИМ на другом таймере - что тоже не есть хорошо ,так как такой ШИМ на больших частотах съедает очень много процессорного времени - http://arduino.ru/forum/programmirovanie/analogwrite-na-lyubom-vyvode данная либа использует TIMER2 и не конфликтует с библиотекой Servo.

в wiring_analog.c для функции analogWrite используется функция digitalPinToTimer(pin), где посомтреть её код и что она делает?

Для servo.h нашел запуск таймера timer16_Sequence_t timer = SERVO_INDEX_TO_TIMER(servoIndex);

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

 

techmike
Offline
Зарегистрирован: 27.02.2013

maksim пишет:

Не программно соединить, а физически - проводами. Соединяете проводами 6 вывод с 10 выводом и 5 с 9. Переподключаете сонар на другие выводы.

// motor A
int dir1PinA = 13;
int dir2PinA = 12;
int speedPinA = 6;
// motor B
int dir1PinB = 11;
int dir2PinB = 8;
int speedPinB = 5;

Ultrasonic ultrasonic(4, 3);

Пины перекомутировал, в результате заработало, но осталось 3 цифровых порта, энкодеры на 4 колеса или компас уже не подключить.

maksim
Offline
Зарегистрирован: 12.02.2012

Если вы не знали, то на Uno все аналоговые выводы могут работать как цифровые, и более того компасы обычно общаются по I2C.

techmike
Offline
Зарегистрирован: 27.02.2013

maksim пишет:

Если вы не знали, то на Uno все аналоговые выводы могут работать как цифровые, и более того компасы обычно общаются по I2C.

С этим разобрался. Остается вопрос по теме: как понять какие ШИМ на каких пинах работают от каких таймеров?

Чтобы больше на такие грабли не наступать.

maksim
Offline
Зарегистрирован: 12.02.2012
techmike
Offline
Зарегистрирован: 27.02.2013

У mega328 такая же последовательность подключения к arduino, т.е. слева на право, сверху в низ?

step962
Offline
Зарегистрирован: 23.05.2011

ATmega48, ATmega88, ATmega168, ATmega328 - суть одна и та же модель микроконтроллера. Отличаются друг от друга они лишь размером Flash/EEPROM/RAM. Отличия в распиновке - по вполне естественной причине - имеются между различными вариантами корпусов: DIP28/MLF28/MLF32/TQFP32.

Так что для DIP-корпуса ответом будет - да.

techmike
Offline
Зарегистрирован: 27.02.2013

Последний вопрос, но не в тему: как правльнее отпределить, что робот повернулся на нужный угол, беря в расчет разнородность поверхности и возможность проскальзывания/стопора колес?

Энкодеры на всех четырех колесах не дадут нужного результата, так как колеса проскалзывают или наоборот стопорятся.

Почитал про компас (HMC5883L), пишут что не хватит разрешение и позицировать компас нужно строго вертикально.

GPS не предлагать, робот только для дома.

Клапауций
Offline
Зарегистрирован: 10.02.2013

techmike пишет:

Последний вопрос, но не в тему: как правльнее отпределить, что робот повернулся на нужный угол, беря в расчет разнородность поверхности и возможность проскальзывания/стопора колес?

гироскоп

techmike
Offline
Зарегистрирован: 27.02.2013

Клапауций пишет:

techmike пишет:

Последний вопрос, но не в тему: как правльнее отпределить, что робот повернулся на нужный угол, беря в расчет разнородность поверхности и возможность проскальзывания/стопора колес?

гироскоп

Одного гироскопа будет недостаточно. Скинте почитать если есть соответствующие топики, желательно с отлаженой реализацией.

Клапауций
Offline
Зарегистрирован: 10.02.2013

techmike пишет:
Скинте почитать если есть соответствующие топики, желательно с отлаженой реализацией.

Вот уж, нет - тыкайте палкой дохлого админа сего форума, пусть делает нормальный поиск... или

https://www.google.com/search?hl=ru&q=arduino+%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D1%8F+%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0+%D0%B2+%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%B5

techmike
Offline
Зарегистрирован: 27.02.2013

Клапауций пишет:

techmike пишет:
Скинте почитать если есть соответствующие топики, желательно с отлаженой реализацией.

Вот уж, нет - тыкайте палкой дохлого админа сего форума, пусть делает нормальный поиск... или

https://www.google.com/search?hl=ru&q=arduino+%D0%BE%D1%80%D0%B8%D0%B5%D0%BD%D1%82%D0%B0%D1%86%D0%B8%D1%8F+%D0%BE%D0%B1%D1%8A%D0%B5%D0%BA%D1%82%D0%B0+%D0%B2+%D0%BF%D1%80%D0%BE%D1%81%D1%82%D1%80%D0%B0%D0%BD%D1%81%D1%82%D0%B2%D0%B5

ок. на этом форуме и такой гуг я уже читал.

vadim.tusur
Offline
Зарегистрирован: 04.01.2014

Добрый день! Наткнулся на эту тему. У меня проблема с тем же оборудованием - Серво и мотор шилд.

Я убрал шилд с ардуинки УНО, кинул на него 8, 11, 12, 13 пины на двигатели, а шим взял с 3 и 5 пина. Еще перебросил землю.

Запитал Уно и шилд параллельно с аккумуляторов 7,2 В.

Двигатели заработали нормально, а вот серва глючит - уперлась в крайнее положение 180 и стоит.

Причем, в отдельных скетчах все нормально.

Вот отдельный скетч для сервы:

#include <Servo.h> 
 
Servo myservo;  // Создание экземпляра объекта для сервы
                // a maximum of eight servo objects can be created 
 
int pos = 0;    // Позиция сервы 
 
void setup() 
{ 
  myservo.attach(A1, 900, 2100);  // Назначение пина А1 для сервы и диапазона управления
} 
  
void loop() {
  
  for(pos = 0; pos < 180; pos += 18) // Сканирование всего диапазона сервы 
  {                                   
    myservo.write(pos);              // Установка позиции сервы
    delay(45);                       //  Пауза для отработки позиции 
  } 
  for(pos = 180; pos>=1; pos-=18)     // goes from 180 degrees to 0 degrees 
  {                                
    myservo.write(pos);             
    delay(45);                       
  } 
  
}

В скетче с двигателями  (использована библиотека #include "MotorDriver.h")  все работает до и после слияния.

Когда соединяю, серва нервно дергается и сразу падает в сторону 180 градусов, после этого стоит. После перезагрузки не шевелится. Загружаю отдельный скетч для нее - работает.

Что тут может быть? Мотор шилд же не работает с таймером 1 напрямую? Ему только шим нужен.

Да, серва у меня 120 градусная, диапазон управления 900- 2100мкс указан верный, думаю ничего страшного, если ей программно задаются углы более 120 градусов, библиотека Серво все равно же пересчитывает диапазоны.