Энкодер и dc мотор

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

Имеется dc мотор с энкодером на датчиках холла . С помощью потенциометра управляю мотором- лево, право, стоп. С энкодера снимаю показания. При нажатии кнопки Save сохраняю в память данные с энкодера. При нажатии кнопки Go мотор движется в сохранённое положение.  Сейчас с направлением движения в сохранённое положение всё нормально (при разных комбинациях сохранённых значений и текущего положения направление движения правильное), а вот останавливаться не хочет - проскакивает. В чём ошибка.

void loop() {  
  if(inputModeX) { 
    potX = analogRead(potXPin);
    if (potX >= 465 && potX <= 565)
    {
      analogWrite(speedXPin, 0); 
    }
    if (potX < 465)
    {
      fspeedX = map(potX, 465, 0, 10, 255);
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);
      analogWrite(speedXPin, fspeedX); 
    }
    if (potX > 565)
    {
      bspeedX = map(potX, 565, 1023, 10, 255);
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);
      analogWrite(speedXPin, fspeedX);  
    }
  }
  attachInterrupt(0, UpdateRotation, FALLING);
  ///////////////////////////////////   сохраняю положение
  if (buttonStateSave == HIGH) {     
    posA = Rotor;
    EEPROM.write(10, posA);
  }
  /////////////////////////////////   движение в сохранённое положение
  if (buttonStateGo == HIGH) {     
    inputModeX = 0;
    valueA = EEPROM.read(10);
    if (valueA < Rotor)
    {
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);   
      analogWrite(speedXPin, 100); 
    }
    else if (valueA > Rotor)
    {
      digitalWrite(DirX1, LOW);
      digitalWrite(DirX2, HIGH);   
      analogWrite(speedXPin, 100); 
    }
    else if( (abs(valueA) - abs( Rotor)) == 0)
    {
      analogWrite(speedXPin, 0); 
    }
  }
}
void UpdateRotation() {
  if (digitalRead(B)) { 
    Rotor++;
  } 
  else {
    Rotor--;
  }
}

 

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

Что - то сам быстро разобрался. Но при минимальных скоростях останавливается чётко в сохранённом положении, а при средних начинаются проскоки , наверно из-за инерции ротора и редуктора. Прийдётся изучать PID регулятор, до этого с PID  никогда не сталкивался.

maksim
Offline
Зарегистрирован: 12.02.2012
// параметры ПИД-регулятора
#define Kp 1.0              // коэффициент усиления
#define Ki 0.015            // коэффициент интегрирования
#define Kd 0.005            // коэффициент дифференцирования
#define Tt 2500L            // постоянная времени, совпадает с интервалом опроса датчика

byte PID_control(int settemp, int currenttemp)
{
  static int last_error;
  static long I;
  int P = settemp - currenttemp;
  long D = (((settemp - currenttemp) - last_error) * 1000 / Tt); 
  last_error = settemp - currenttemp;
  long PID = Kp*P + Ki*I + Kd*D;
  PID = constrain(PID, 0, 255);
  if(PID > 0 && PID < 255) I = I + ((settemp - currenttemp) * Tt) / 1000;
  return PID;
}

 

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

Спасибо maksim за подсказку. Изучаю тему. Пока понял, что заставить пид регулятор работать довольно геморррррррно. Буду пробовать.

По поводу своего кода рано обрадовался. При отрицательных значениях valueA мотор крутится не как надо

void loop() {  
  if(inputModeX) { 
    potX = analogRead(potXPin);
    if (potX >= 465 && potX <= 565)
    {
      analogWrite(speedXPin, 0); 
    }
    if (potX < 465)
    {
      fspeedX = map(potX, 465, 0, 10, 255);
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);
      analogWrite(speedXPin, fspeedX); 
    }
    if (potX > 565)
    {
      bspeedX = map(potX, 565, 1023, 10, 255);
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);
      analogWrite(speedXPin, fspeedX);  
    }
  }
  attachInterrupt(0, UpdateRotation, FALLING);
  
  if(inputModeX == 0 && valueA ==  Rotor)
  {
   analogWrite(speedXPin, 0);
   inputModeX = 1;
  }
  ///////////////////////////////////   сохраняю положение
  if (buttonStateSave == HIGH) {     
    posA = Rotor;
    EEPROM.write(10, posA);
  }
  /////////////////////////////////   движение в сохранённое положение
  if (buttonStateGo == HIGH) {     
    inputModeX = 0;
    valueA = EEPROM.read(10);
    if (valueA < Rotor)
    {
      digitalWrite(DirX1, HIGH);
      digitalWrite(DirX2, LOW);   
      analogWrite(speedXPin, 20); 
    }
    else if (valueA > Rotor)
    {
      digitalWrite(DirX1, LOW);
      digitalWrite(DirX2, HIGH);   
      analogWrite(speedXPin, 20); 
    }
  }
}
void UpdateRotation() {
  if (digitalRead(B)) { 
    Rotor++;
  } 
  else {
    Rotor--;
  }
}

 

StrangerM
Offline
Зарегистрирован: 02.11.2013

А уж рассчитать ПИД регулятор в вашей системе... Вы чего хотите ПИД регулировать момент? угловую скорость? положение ротора? В коде ПИД регулятора меня особо порадовал комментарий - постоянная времени, совпадает с интервалом опроса датчика

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

Ну что ж тут радостного? Данный код писался под температуту, а датчик опрашивался раз в 2,5 секунды. Сделать меньше проблемы не вижу. Можете предложить лучше?

Если слова 

vvadim пишет:
... движется в сохранённое положение. ...  - проскакивает. 

вам ни о чем не говорят, то расшифрую - регулировать нужно положение ротора.

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

Я представляю себе ситуацию так - периодически проверяется положение ротора по отношению к разнице между valueA и Rotor, когда разница приближается к 0 скорость вращения ротора должна плавно снижаться тоже до 0. Или я ошибаюсь?

StrangerM
Offline
Зарегистрирован: 02.11.2013

Вы систему ТС рассмотрели. Что за датчик и как он работает? "Энкодер" - а где число импульсов на оборот? 2? или 3? А регулятор тока, а система подчиненного регулирования? В электроприводах с DSP время берут чаще всего от ШИМ прерывания. И за период ШИМ процессор должен обработать все вычисления для следующего шага. Кстати, нечто подобное (время от ШИМ) встречал и для Ардуино.

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

StrangerM, я не специалист, я из чайников, и получается разговор на разных языках. У меня есть ардуина, L293D драйвер, мотор-редуктор 12 вольт с энкодером (90 на оборот выходного вала) - всё. Да и первая попытка решить подобную задачу, при том что я не программист. В данном случае мне нужна понятно-доступная информация и направление в котором идти дальше. Теорию почитал. Кстати вот хорошая статья для чайников http://robot-develop.org/archives/2833 . Теперь нужно попытаться реализовать пид регулятор для моего случая. Мне на форуме много помогали и я всем отвечающим всегда благодарен.

StrangerM
Offline
Зарегистрирован: 02.11.2013

Эх писал, писал - а регистрацию не обновил. Пропал текст. Больше уж не смогу. По крайней мере сейчас. Извините.

MacSim
Offline
Зарегистрирован: 28.11.2012

maksim пишет:

// параметры ПИД-регулятора
#define Kp 1.0              // коэффициент усиления
#define Ki 0.015            // коэффициент интегрирования
#define Kd 0.005            // коэффициент дифференцирования

Пожалуйста подскажите как рисчитывали эти коэффициенты

Deamount
Offline
Зарегистрирован: 07.05.2012

Да, тоже интересует как рассчитать эти коэффициенты.

Есть ещё вопрос. Телега на двух колёсах с энкодером в виде колёсика с дырочками (от старой мышки).

Пытаюсь таким энкодером считать угол вращения колёс (а затем расстояние), чтобы после движения робот вернулся в исходную точку. Т.о. когда сам задаю направление движения, я знаю, что с оптопары сигналы нужно суммировать при движении вперед и вычитать при движении назад. НО, откуда ни возьмись маленький комарик садится на телегу и нечаянно сдвигает в неопределенном направлении...! данные с энкодера посчитались неверно... т.к. направление задавал не я, а комарик...

вопрос. реально ли таким супер энкодером определить правильное напрвление вращения колеса?

не понятно как мышка при помощи одной оптопары на одно колесо понимает куда движется... т.е. без доп средств это же как-то делается?

 

Deamount
Offline
Зарегистрирован: 07.05.2012

похоже сам нашёл ответ на свой вопрос. в мышках какой-то ДВОЙНОЙ фототранзистор...

к сожалению я в электронике хуже разбираюсь, чем в программировании... подскажите кто знает какой-нибудь готовый модуль или схему на распространенных ДЕШЕВЫХ элементах, для подключения к ардуино. что-то на али один такой энкодер от 400рублей, что очень дорого. можно два обычных энкодера поставить по 65руб )))

Добавлено: что-то я напутал, не нашёл таких энкодеров на али... только одинарные. помогите найти двойной

MacSim
Offline
Зарегистрирован: 28.11.2012

1 отковыряй со старой шариковой мыши. 2 посмотри на али концевые датчикb для репрапа около 50рублей.

http://ru.aliexpress.com/item/Free-Shipping-Optical-Endstop-Light-Contro...