Проблемы с драйвером двигателя L298N
(отредактировано)
Так жаль, что я виноват. Чтобы было ясно:
Судя по картинке, которую я опубликовал, мне нужно нажать PBA (as Button1), чтобы оба двигателя могли работать вперед (CW-по часовой стрелке) и назад (CCW-против часовой стрелки) и остановиться.
В то время как с другой стороны, PBB (как button2) предназначен для другого условия, оба двигателя могут работать влево, вправо и останавливаться.
Проблемы:
Когда я запускаю свой код, он появляется на ЖК-дисплее.
Я смог добиться этого для стороны PBB, но для стороны PBA оба двигателя вообще не двигаются.
Я использовал потенциометр, чтобы регулировать скорость. Потенциометр работает нормально.
Я использую debounce для обеих моих кнопок, и я не уверен, влияет ли debounce на мой
void setmode(int Mode, int MotorMode1){}
////////////////////////////////////////////////////////////////////////////////[![введите описание изображения здесь][1]][1]
boolean lastButton=LOW;
boolean currentButton = LOW;
boolean last1Button = LOW;
boolean current1Button = LOW;
boolean debounce(boolean last){
boolean current = digitalRead(PBA);
if (last != current) {
delay(5);
current = digitalRead(PBA);
return current;
}
}
boolean debounce1(boolean last1) {
boolean current1 = digitalRead(PBB);
if (last1 != current1) {
delay(5);
current1 = digitalRead(PBB);
return current1;
}
}
int Mode = 0;
int motorMode1 = 0;
void loop() {
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SPEED:");
lcd.setCursor(0, 1);
// потенциометр LCD
float inputValue = analogRead (pot);
inputValue = map(inputValue, 0, 1023, 0, 100);
lcd.setCursor(7, 0);
lcd.print (inputValue);
lcd.setCursor(12, 0);
lcd.print ("%");
//считывание значений с потенциометра
MotorSpeed = analogRead(SpeedControl);
MotorSpeed = map(MotorSpeed, 0 , 1023 , 0 , 255);
// отрегулируйте для предотвращения на низкой скорости
if (MotorSpeed < 8)MotorSpeed = 0;
//установка частоты вращения двигателя
//analogWrite (enA, MotorSpeed);
//analogWrite (enB, MotorSpeed);
// MotorLCD
lcd.setCursor(0, 1);
lcd.print("MOVE:");
currentButton = debounce(lastButton);
if (currentButton == HIGH && lastButton == LOW) {
Mode++;
}
lastButton = currentButton;
if (Mode == 3){
Mode = 0;
}
current1Button = debounce1(last1Button);
if (last1Button == HIGH && current1Button == LOW) {
motorMode1++;
}
last1Button = current1Button;
if (motorMode1 == 3){
motorMode1 = 0;
}
setMode( Mode, motorMode1);
}
void setMode(int Mode, int motorMode1) {
analogWrite (enA, MotorSpeed);
analogWrite (enB, MotorSpeed);
if (Mode == 1 ) {
lcd.setCursor(5, 8);
lcd.print("Forward");
//MOTOR_A МАКСИМАЛЬНАЯ СКОРОСТЬ ПО ЧАСОВОЙ СТРЕЛКЕ
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
//MOTOR_B МАКСИМАЛЬНАЯ СКОРОСТЬ ПО ЧАСОВОЙ СТРЕЛКЕ
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
}
if (Mode == 2) {
lcd.setCursor(5, 8);
lcd.print("Reverse");
//MOTOR_A МАКСИМАЛЬНАЯ СКОРОСТЬ ПРОТИВ ЧАСОВОЙ СТРЕЛКИ
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
//MOTOR_B МАКСИМАЛЬНАЯ СКОРОСТЬ ПРОТИВ ЧАСОВОЙ СТРЕЛКИ
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
}
if (motorMode1 == 1) {
lcd.setCursor(5, 8);
lcd.print("Right");
//MOTOR_A МАКСИМАЛЬНАЯ СКОРОСТЬ ПО ЧАСОВОЙ СТРЕЛКЕ
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
//MOTOR_B МАКСИМАЛЬНАЯ СКОРОСТЬ ПРОТИВ ЧАСОВОЙ СТРЕЛКИ
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
}
if (motorMode1 == 2) {
lcd.setCursor(5, 8);
lcd.print("Left");
//MOTOR_A МАКСИМАЛЬНАЯ СКОРОСТЬ ПРОТИВ ЧАСОВОЙ СТРЕЛКИ
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
//MOTOR_B МАКСИМАЛЬНАЯ СКОРОСТЬ ПО ЧАСОВОЙ СТРЕЛКЕ
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
}
if (Mode == 0 || motorMode1 == 0) {
lcd.setCursor(5, 8);
lcd.print("Stop");
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);
}
}
@Chow Wye En, 👍1
Обсуждение1 ответ
Лучший ответ:
Надеюсь, я вас правильно понял. Лучший способ - рассказать вам, как вы можете использовать состояния для решения проблемы. Но это отняло бы у меня слишком много времени.
Я решил отредактировать вашу программу. У меня нет оборудования, чтобы попробовать это. Так что это просто пример, чтобы показать вам эту идею. Возможно, это работает так, как есть.
Пожалуйста, проверьте комментарии. Если вы действительно заинтересованы в понимании проблемы и решения, а вещи неясны, вы (или другие) можете спросить с комментариями ниже. И конечно, если вы найдете ошибку, я буду рад узнать об этом и исправить ее. ;-)
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// Это разные состояния движения
#define STATE_STOP 0
#define STATE_LEFT 1
#define STATE_RIGHT 2
#define STATE_FORWARD 3
#define STATE_BACKWARD 4
// всегда используйте выразительные имена
// Назначение выводов
//////////////////////////////////////////////
// Analog
int pinPotiSpeed = A0;
// Двигатель A
int pinEnA = 9;
int pinInA1 = 8;
int pinInA2 = 7;
// Двигатель B
int pinEnB = 3;
int pinInB1 = 5;
int pinInB2 = 4;
// Кнопки
const int pinBtnDir = 10;
const int pinBtnTurn = 11 ;
int stateMotors = STATE_STOP;
boolean flagBtnDirPressed = LOW;
boolean flagBtnTurnPressed = LOW;
int stateMotorsSpeed = 0;
int speedPercent = map( stateMotorsSpeed, 0, 255, 0, 100 );
LiquidCrystal_I2C lcd(0x27, 16, 2);
// У меня нет времени много думать об этом разоблачении, но
// У меня плохое предчувствие. Если Arduino не реагирует на нажатия кнопок
// или смена режима на быстрый, пожалуйста, дайте мне знать. Я посмотрю на это, если
// необходимо. ;-)
boolean readButtonAndDebounce(int btnPin, boolean lastState)
{
boolean actualState = digitalRead(btnPin);
if (lastState != actualState)
{
delay(15);
actualState = digitalRead(btnPin);
return actualState;
}
// этот возврат отсутствовал в исходной программе
return actualState;
}
void setup()
{
Serial.begin(9600);
pinMode(pinEnA, OUTPUT);
pinMode(pinInA1, OUTPUT);
pinMode(pinInA2, OUTPUT);
pinMode(pinEnB, OUTPUT);
pinMode(pinInB1, OUTPUT);
pinMode(pinInB2, OUTPUT);
pinMode(pinBtnDir, INPUT);
pinMode(pinBtnTurn, INPUT);
digitalWrite(pinInA1,LOW);
digitalWrite(pinInA2,LOW);
digitalWrite(pinInB1,LOW);
digitalWrite(pinInB2,LOW);
lcd.init();
lcd.backlight();
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("SPEED:");
lcd.setCursor(0, 1);
lcd.setCursor(7, 0);
// преобразовать 0-255 в 0%-100%
lcd.print ("0 %");
lcd.setCursor(0, 1);
lcd.print("MOVE: Stop");
}
void loop()
{
stateMotorsSpeed = map( analogRead( pinPotiSpeed ), 0, 1023, 0, 255 );
if ( stateMotorsSpeed < 8 ) stateMotorsSpeed = 0;
speedPercent = map( stateMotorsSpeed, 0, 255, 0, 100 );
boolean flagBtnDirPressedOld = flagBtnDirPressed;
flagBtnDirPressed = readButtonAndDebounce( pinBtnDir, flagBtnDirPressed );
boolean flagBtnTurnPressedOld = flagBtnTurnPressed;
flagBtnTurnPressed = readButtonAndDebounce( pinBtnTurn, flagBtnTurnPressed );
// this is a bit tricky, because I don't know if i understood the problem correctly.
// Моя проблема в том, что произойдет, если обе кнопки будут нажаты, я решил дать
// кнопка направления приоритет
if ( flagBtnDirPressed && ! flagBtnDirPressedOld )
{
switch( stateMotors )
{
case STATE_STOP:
stateMotors = STATE_FORWARD;
break;
case STATE_FORWARD:
stateMotors = STATE_BACKWARD;
break;
case STATE_BACKWARD:
stateMotors = STATE_STOP;
break;
default:
// это происходит, если состояние из другой кнопки активно
// В таблице нет правила, что делать в этом случае.
// Возможно, вы могли бы посчитать нажатие кнопки по модулю 3 для каждой кнопки
// и тогда вы можете переключиться в правильное состояние
stateMotors = STATE_STOP;
}
}
else if ( flagBtnTurnPressed && ! flagBtnTurnPressedOld )
{
// вводится только в том случае, если состояние нажатия кнопки направления не изменилось
switch( stateMotors )
{
case STATE_STOP:
stateMotors = STATE_RIGHT;
break;
case STATE_RIGHT:
stateMotors = STATE_LEFT;
break;
case STATE_LEFT:
stateMotors = STATE_STOP;
break;
default:
// это происходит, если состояние из другой кнопки активно
stateMotors = STATE_STOP;
}
}
controlMotorAndUpdateLcd();
}
void setMotorSignals( boolean sigA1 , boolean sigA2, boolean sigB1, boolean sigB2 )
{
//MOTOR_A
digitalWrite(pinInA1, sigA1);
digitalWrite(pinInA2, sigA2);
//MOTOR_B
digitalWrite(pinInB1, sigB1);
digitalWrite(pinInB2, sigB2);
}
void controlMotorAndUpdateLcd()
{
lcd.clear();
lcd.setCursor( 0, 0 );
lcd.print( "SPEED:" );
lcd.setCursor( 0, 1 );
// потенциометр LCD
lcd.setCursor( 7, 0 );
lcd.print ( speedPercent );
lcd.setCursor( 12, 0 );
lcd.print ("%");
analogWrite ( pinEnA, stateMotorsSpeed );
analogWrite ( pinEnB, stateMotorsSpeed );
// MotorLCD
lcd.setCursor(0, 1);
lcd.print("MOVE:");
lcd.setCursor(5, 8);
switch( stateMotors )
{
case STATE_STOP:
lcd.print("Stop");
setMotorSignals( LOW, LOW, LOW, LOW);
break;
case STATE_FORWARD:
lcd.print("Forward");
setMotorSignals( HIGH, LOW, HIGH, LOW);
break;
case STATE_BACKWARD:
lcd.print("Reverse");
setMotorSignals( LOW, HIGH, LOW, HIGH);
break;
case STATE_LEFT:
lcd.print("Left");
setMotorSignals( HIGH, LOW, LOW, HIGH);
break;
case STATE_RIGHT:
lcd.print("Right");
setMotorSignals( LOW, HIGH, HIGH, LOW);
break;
}
}
Спасибо за помощь.. На Жидкокристаллическом дисплее все еще есть некоторые сбои. Ты хоть представляешь, почему? Когда я запускаю void setup в части "добро пожаловать", она все еще работает нормально, пока не достигнет конечного состояния части, где "Скорость" и "Движение". Формулировка неясна, и у некоторых есть некоторые сбои., @Chow Wye En
1. Извините, я не понимаю, что вы подразумеваете под "глюками". Вы имеете в виду, например, что значение скорости быстро меняется? Я могу помочь только в том случае, если точно знаю причину ошибки. 2. Я не могу вам помочь с формулировкой, но вы можете использовать тексты, которые вам больше подходят., @Peter Paul Kiefer
Все в порядке, Питер. Я постараюсь решить ее сам. Большое спасибо, Питер. , @Chow Wye En
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Если вы хотите, чтобы кто-то помог вам, правильно отформатируйте код и сократите его только для того, чтобы сосредоточиться на той области, которая, по вашему мнению, потенциально вызвала проблему., @hcheung
Для этого в IDE есть пункт меню
Инструменты / автоформат
., @timemageКстати: В чем вопрос? И что вы подразумеваете под асинхронностью и синхронностью? И почему вы используете два имени для вывода A0 (pot, SpeedControl)? Почему вы называете выходные контакты "inX"? Почему вы сначала устанавливаете inX в функции mode в зависимости от переменной Mode, а затем перезаписываете ее в зависимости от переменной motorMode1? Но самый важный вопрос: чего вы хотите достичь? Попробуйте объяснить это, и, возможно, вы сами увидите, что происходит не так. Мы могли бы помочь, если бы знали, каковы ваши цели. Только глядя на код, я не могу сказать, что вы пытаетесь сделать. ;-), @Peter Paul Kiefer
Привет, Питер, я уже загрузил фотографию, чтобы вы могли правильно понять. 1. почему вы используете два имени для вывода A0 (pot, SpeedControl)? Я объявил дважды с другой функцией, и это вызвало путаницу, и я удалил ее. 2. Почему вы называете выходные контакты "inX"? Почему вы сначала устанавливаете inX в функции mode в зависимости от переменной Mode, а затем перезаписываете ее в зависимости от переменной motorMode1? inX - для выхода двигателя Ln298 имеется 4 выхода inX. и 2 выхода enX под ШИМ. Спасибо за комментарии. :D, @Chow Wye En