Вопрос по управлению двигателей с помощью L298N ШИМом.
- Войдите на сайт для отправки комментариев
Пт, 04/10/2013 - 23:20
Добрый вечер! Я тут новенький во всём этом.
Делаю "робомашинку". Подключил Китайский модуль L298N. Вот такой: 
Он работает, но на мой взгляд как-то странно. А именно:
если подаю 0 (на направление), то скорость работает нормально (0..255)
если подаю 1 (на направление), то скорость работает наоборот (255..0)
то есть подаю 1 (направление) и 255 (скорость ШИМ) - стоит
подаю 1 (направление) и 0 (скорость ШИМ) - крутит на всю.
Подскажите, это нормально или нет, если нет - то буду приводить скетчи и т.д.
Спасибо.
cхема подключения и скетч
#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; } }Сейчас схему набросаю.. Хотя стоит ли? Подключаю, как в этой статье. Скетч в конце статьи отрабатывает также как у автора на видео.
А с чего вы взяли что какой то из выводов это "направление" а какой то "скорость" ? Автор статьи подсказал? Чему же тогда удивляетесь? У него и спрашивайте.
ШИМ должен подаваться на ENABLE A и ENABLE B, в то время как INPUT 1, 2, 3 ,4 отвечают только за "напрвление", а точнее за состояние ноги OUTPUT одного из мостов.
https://www.sparkfun.com/datasheets/Robotics/L298_H_Bridge.pdf
Так что ничего странного в работе этого драйвера при таком подключении нет.
upd. Вижу, добавили ссылку. Спасибо. Сейчас попробую. Отпишусь.
Нет никакой ошибки. При таком подключении все правильно работает.
Получается, мне для управления нужно будет 6 выходов? или по-прежнему 4-х хватит?
Конечно 6. Вам нужно IN 1,2,3,4 использовать как цифровые выводы, а на EN A,B подавать шим.
Причем управлять в вашем случае IN 1,2 нужно так что бы когда на IN 1 высокий уровень, то на IN 2 низкий и наоборот. Аналогично с IN 3,4. На многих шилдах это организовано с помощь инверторов для экономии выводов МК.
Пример:
вот при таком подключении у вас ШИМ будет работать так как вы хотите.
Спасибо Вам огромное. Теперь всё встало на свои места. Я полдня уже положил на это дело:(
Да уж уроки называется...
P.S. Я уже начал было думать, как переделывать программу и ужаснулся от всех этих инверсий%) Да ещё и неизвестно удалось ли бы мне это реализовать.. Ещё раз спасибо!
Поэтому берете и делаете так:
#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); }Спасибо за помощь и участие. Пока реализовал так:
#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. Стал пользоваться форумами (в качестве участника) только когда начал пробовать себя в программировании. Пользуюсь второй раз, но как это всё-таки здорово работает:) Начинаешь чувствовать мощную поддержку — и это придаёт уверенности. Ещё раз спасибо.
Данные строки бессмыслены:
if (value == 0) { digitalWrite(lMotorDirOutF, !go); digitalWrite(lMotorDirOutB, !go); digitalWrite(rMotorDirOutF, !go); digitalWrite(rMotorDirOutB, !go); }так как когда на ENA и ENB логический 0 двигатели и так не будут крутиться.
Я тоже так думал, но без этого у меня продолжал крутиться правый мотор, почему-то. Пришлось добавить. Может я где-то натупил, сейчас проверю ещё раз.
Ха! Это был маленький подарок от китайцев:
Перемкнуло контакты ENB (там где была перемычка). Подчистил, теперь всё ОК. Часть кода, действительно лишняя)
И снова спасибо.
Что бы не плодить темы спрошу здесь. Подключил к этому же драйверу мотор Nema17. Можно ли подключить оба вывода ENB и ENA к одному ШИМ выводу ардуино?
Мне можно тоже спросить: если подключить один двигатель на два выхода( для тока 4 a), то и управляющие входа можно запараллелить?