Вопрос по управлению двигателей с помощью L298N ШИМом.

alexkov87
Offline
Зарегистрирован: 04.10.2013

Добрый вечер! Я тут новенький во всём этом.

Делаю "робомашинку". Подключил Китайский модуль L298N. Вот такой: 

Он работает, но на мой взгляд как-то странно. А именно:

если подаю 0 (на направление), то скорость работает нормально (0..255)
если подаю 1 (на направление), то скорость работает наоборот (255..0)
то есть подаю 1 (направление) и 255 (скорость ШИМ) - стоит
подаю 1 (направление) и 0 (скорость ШИМ) - крутит на всю.
 
Подскажите, это нормально или нет, если нет - то буду приводить скетчи и т.д.
 
Спасибо.
 
vvadim
Offline
Зарегистрирован: 23.05.2012

cхема подключения и скетч

alexkov87
Offline
Зарегистрирован: 04.10.2013
#define leftMotorDirectOut 2 // Left motor direction
#define leftMotorSpeedOut 3 // PWM
#define rightMotorDirectOut 4 // Right motor direction
#define rightMotorSpeedOut 5 // PWM

void setup() {
  
  Serial.begin(115200);
  Serial.write("Ready");

pinMode(leftMotorDirectOut, OUTPUT);
pinMode(rightMotorDirectOut, OUTPUT);
}

// пропущу часть, всё в очень черновом варианте

void motorCommandHandler(String command, int value) {        
  switch (command.charAt(0)) {
      case 'F':
        digitalWrite(leftMotorDirectOut, 1);
        analogWrite(leftMotorSpeedOut, value); // в качестве value подается int 0..255
        digitalWrite(rightMotorDirectOut, 1);
        analogWrite(rightMotorSpeedOut, value);
        break;
      case 'B':
        digitalWrite(leftMotorDirectOut, 0);
        analogWrite(leftMotorSpeedOut, value);
        digitalWrite(rightMotorDirectOut, 0);
        analogWrite(rightMotorSpeedOut, value); 
        break;
      case 'L':
        digitalWrite(leftMotorDirectOut, 0);
        analogWrite(leftMotorSpeedOut, value);
        digitalWrite(rightMotorDirectOut, 1);
        analogWrite(rightMotorSpeedOut, value);
        break;
      case 'R':
        digitalWrite(leftMotorDirectOut, 1);
        analogWrite(leftMotorSpeedOut, value);
        digitalWrite(rightMotorDirectOut, 0);
        analogWrite(rightMotorSpeedOut, value);
        break;
      default: break;
  }
}

Сейчас схему набросаю.. Хотя стоит ли? Подключаю, как в этой статье. Скетч в конце статьи отрабатывает также как у автора на видео.

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

А с чего вы взяли что какой то из выводов это "направление" а какой то "скорость" ? Автор статьи подсказал? Чему же тогда удивляетесь? У него и спрашивайте.

ШИМ должен подаваться на ENABLE A и ENABLE B, в то время как INPUT 1, 2, 3 ,4 отвечают только за "напрвление", а точнее за состояние ноги OUTPUT одного из мостов.

https://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf

Так что ничего странного в работе этого драйвера при таком подключении нет.

alexkov87
Offline
Зарегистрирован: 04.10.2013

upd. Вижу, добавили ссылку. Спасибо. Сейчас попробую. Отпишусь.

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

Нет никакой ошибки. При таком подключении все правильно работает.

alexkov87
Offline
Зарегистрирован: 04.10.2013

Получается, мне для управления нужно будет 6 выходов? или по-прежнему 4-х хватит?

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

Конечно 6. Вам нужно IN 1,2,3,4 использовать как цифровые выводы, а на EN A,B подавать шим.

Причем управлять в вашем случае IN 1,2 нужно так что бы когда на IN 1 высокий уровень, то на IN 2 низкий и наоборот. Аналогично с IN 3,4. На многих шилдах это организовано с помощь инверторов для экономии выводов МК.

Пример:

// в одном направлении:
digitalWrite(IN1, 1);
digitalWrite(IN2, 0);
analogWrite(ENA, value);

// в другом направлении:
digitalWrite(IN1, 0);
digitalWrite(IN2, 1);
analogWrite(ENA, value);

аналогично со вторым мостом:

// в одном направлении:
digitalWrite(IN3, 1);
digitalWrite(IN4, 0);
analogWrite(ENB, value);

// в другом направлении:
digitalWrite(IN3, 0);
digitalWrite(IN4, 1);
analogWrite(ENB, value);

вот при таком подключении у вас ШИМ будет работать так как вы хотите.

alexkov87
Offline
Зарегистрирован: 04.10.2013

Спасибо Вам огромное. Теперь всё встало на свои места. Я полдня уже положил на это дело:(

Да уж уроки называется...

P.S. Я уже начал было думать, как переделывать программу и ужаснулся от всех этих инверсий%) Да ещё и неизвестно удалось ли бы мне это реализовать.. Ещё раз спасибо!

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

Поэтому берете и делаете так:

#define IN1 2 
#define IN2 4
#define ENA 3 
#define IN3 5 
#define IN4 7
#define ENB 6 

void setup() 
{
  Serial.begin(115200);
  Serial.write("Ready");

  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
}

// пропущу часть, всё в очень черновом варианте

void motorCommandHandler(String command, int value) 
{        
  switch (command.charAt(0)) 
  {
  case 'F':
    leftMotorDirect(1);
    rightMotorDirect(1);
    break;
  case 'B':
    leftMotorDirect(0);
    rightMotorDirect(0);
    break;
  case 'L':
    leftMotorDirect(0); 
    rightMotorDirect(1);
    break;
  case 'R':
    leftMotorDirect(1);
    rightMotorDirect(0);
    break;
  }
  leftMotorSpeed(value); 
  rightMotorSpeed(value);
}

void leftMotorDirect(bool dir)
{
  digitalWrite(IN1, dir);
  digitalWrite(IN2, !dir);
}

void rightMotorDirect(bool dir)
{
  digitalWrite(IN3, dir);
  digitalWrite(IN4, !dir);
}

void leftMotorSpeed(byte speed)
{
  analogWrite(ENA, speed);
}

void rightMotorSpeed(byte speed)
{
  analogWrite(ENB, speed);
}

 

alexkov87
Offline
Зарегистрирован: 04.10.2013

Спасибо за помощь и участие. Пока реализовал так:

#define lMotorDirOutF 2 // Left motor direction 1
#define lMotorDirOutB 4 // Left motor direction 2
#define lMotorSpeedOut 3 // PWM
#define rMotorDirOutF 7 // Right motor direction1
#define rMotorDirOutB 8 // Right motor direction2
#define rMotorSpeedOut 6 // PWM

void setup() {
  
  Serial.begin(115200);
  Serial.write("Ready");

pinMode(lMotorDirOutF, OUTPUT);
pinMode(lMotorDirOutB, OUTPUT);
pinMode(rMotorDirOutF, OUTPUT);
pinMode(rMotorDirOutB, OUTPUT);
}

void loop() {
  String inData = "";
  char inChar;

  while(Serial.available() > 0) {
      inChar = Serial.read();
      inData += inChar;
      delay(10);
  }
  Serial.flush();
  int inDataLength = inData.length();
  if (inData.length() == 5) {  
  inputDataHandler(inData); 
}
}
void inputDataHandler(String inData) {
  String val = "";
  String command = "";
  int value;
  char com = inData[1];
  command += com;
  
  char val1 = inData[2];
  char val2 = inData[3];
  char val3 = inData[4];

  val += val1;
  val += val2;
  val += val3;
  value = val.toInt();

  switch (inData.charAt(0)) {
      case 'M':
        motorCommandHandler(command, value);
        break;
//      case 'C':
//        cameraCommandHandler(command, value);
//        break;
        default: break;
  }
}
void motorCommandHandler(String command, int value) {
  bool go = true;
  Serial.println(command); 
  Serial.println(value);
  if (value > 255) 
    value = 255; 
  else if (value > 0 && value < 100)
    value = 100;
  switch (command.charAt(0)) {
      case 'F':
        digitalWrite(lMotorDirOutF, go);
        digitalWrite(lMotorDirOutB, !go);
        digitalWrite(rMotorDirOutF, go);
        digitalWrite(rMotorDirOutB, !go);
        break;
      case 'B':
        digitalWrite(lMotorDirOutF, !go);
        digitalWrite(lMotorDirOutB, go);
        digitalWrite(rMotorDirOutF, !go);
        digitalWrite(rMotorDirOutB, go);
        break;
      case 'L':
        digitalWrite(lMotorDirOutF, !go);
        digitalWrite(lMotorDirOutB, go);
        digitalWrite(rMotorDirOutF, go);
        digitalWrite(rMotorDirOutB, !go);
        break;
      case 'R':
        digitalWrite(lMotorDirOutF, go);
        digitalWrite(lMotorDirOutB, !go);
        digitalWrite(rMotorDirOutF, !go);
        digitalWrite(rMotorDirOutB, go);
        break;
      default: break;
  }
  analogWrite(lMotorSpeedOut, value);
  analogWrite(rMotorSpeedOut, value);
  if (value == 0) {
    digitalWrite(lMotorDirOutF, !go);
    digitalWrite(lMotorDirOutB, !go);
    digitalWrite(rMotorDirOutF, !go);
    digitalWrite(rMotorDirOutB, !go);
  }
  command = "";
  value = 0;
}

Вроде бы всё работает как надо. Хотя, конечно, очень коряво сделано :)

Команду я планирую передавать вида "MF000..MF255; MR000..MR255" ну и так далее.

Но, для аппаратного раздела это всё уже офтопик.

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

P.S. Стал пользоваться форумами (в качестве участника) только когда начал пробовать себя в программировании. Пользуюсь второй раз, но как это всё-таки здорово работает:) Начинаешь чувствовать мощную поддержку — и это придаёт уверенности. Ещё раз спасибо.

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

Данные строки бессмыслены:

 if (value == 0) {
    digitalWrite(lMotorDirOutF, !go);
    digitalWrite(lMotorDirOutB, !go);
    digitalWrite(rMotorDirOutF, !go);
    digitalWrite(rMotorDirOutB, !go);
  }

так как когда на ENA и ENB логический 0 двигатели и так не будут крутиться.

alexkov87
Offline
Зарегистрирован: 04.10.2013

Я тоже так думал, но без этого у меня продолжал крутиться правый мотор, почему-то. Пришлось добавить. Может я где-то натупил, сейчас проверю ещё раз.

alexkov87
Offline
Зарегистрирован: 04.10.2013

Ха! Это был маленький подарок от китайцев:

 

 

 

 

 

 

 

 

 

Перемкнуло контакты ENB (там где была перемычка). Подчистил, теперь всё ОК.  Часть кода, действительно лишняя)

И снова спасибо.

Lictor
Offline
Зарегистрирован: 01.10.2015

Что бы не плодить темы спрошу здесь. Подключил к этому же драйверу мотор Nema17. Можно ли подключить оба вывода ENB и ENA к одному ШИМ выводу ардуино?

uragan
Offline
Зарегистрирован: 23.02.2015

Мне можно тоже спросить: если подключить один двигатель на два выхода( для тока 4 a), то и управляющие входа можно запараллелить?