Я пытаюсь управлять двумя шаговыми двигателями с помощью последовательного ввода. Мой код работает, однако мне приходится несколько раз нажимать новую команду направления
Я использую два шаговых двигателя 28BYJ-48 с двумя драйверами, которые идут в комплекте. (Я не знаю их названия.)
Вот мой код:
/*
* Код для одновременного управления двумя шаговыми двигателями с использованием вызовов функций библиотеки шаговых двигателей
* Этот код имеет функции, которые делают вызовы для запуска одного шага от каждого из двух двигателей за раз.
* поэтому каждый двигатель по очереди делает шаг, в результате чего они оба работают вместе
* переменная 'lastCall' обеспечивает непрерывный ввод, чтобы поддерживать работу степперов, если нет последовательного ввода
* Написано Габриэлем Адамсом — март 2023 г. —
*/
#include <Stepper.h>
//определения для каждой команды, которая будет получена через последовательный порт
#define COMMAND_LEFT 'a'
#define COMMAND_RIGHT 'd'
#define COMMAND_FORWARD 'w'
#define COMMAND_BACK 's'
#define COMMAND_STOP ' '
//Количество шагов на внутренний оборот двигателя
const float STEPS_PER_REV = 32;
//Величина понижения передачи
const float GEAR_RED = 64;
//Количество шагов на один оборот выходного редуктора
const float STEPS_PER_OUT_REV = STEPS_PER_REV * GEAR_RED;
//введите здесь количество шагов на оборот для ваших двигателей
int stepsInRev = STEPS_PER_OUT_REV ;
// это устанавливает значение для циклов for и, следовательно, устанавливает количество шагов в каждом вызове
int num_of_steps = 1;
// установка выводов для каждого драйвера Motor1 ~ IN1, IN2, IN3, IN4; двигатель2 ~ IN1, IN2, IN3, IN4
Stepper myStepper1(STEPS_PER_OUT_REV, 4, 6, 5, 7);
Stepper myStepper2(STEPS_PER_OUT_REV, 8, 10, 9, 11);
// переменная для хранения последнего обращения к последовательному порту
char lastCall = ' ';
// Я прототипировал здесь все функции, но по какой-то причине Arduino IDE это не понравилось
//поэтому они закодированы, пока я не выясню, почему
//аннулировать forwardStep();
//отменить обратный шаг();
// недействительный левый шаг();
// недействительный правый шаг();
//аннулировать allStop();
//двигать моторы вперед
void forwardStep(int steps){
Serial.println("forward");
// шаг вперед на один шаг
myStepper1.step(1);
myStepper2.step(1);
delay(10);
}
// чтобы переместить моторы назад
void backwardStep(int steps){
Serial.println("backward");
// шаг на один шаг назад
myStepper1.step(-1);
myStepper2.step(-1);
delay(10);
}
// для перемещения двигателей в противоположных направлениях (слева)
void leftStep(int steps){
Serial.println("left");
// шаг на один шаг влево
myStepper1.step(1);
myStepper2.step(-1);
delay(10);
}
// для перемещения двигателей в противоположных направлениях (справа)
void rightStep(int steps){
Serial.println("right");
// шаг на один шаг вправо
myStepper1.step(-1);
myStepper2.step(1);
delay(10);
}
// чтобы отключить драйверы моторов и остановить моторы
void allStop(){
Serial.println("stop");
// шаговики останавливаются
PORTD = B00000000; //устанавливает все контакты с 0 по 7 в состояние LOW, чтобы выключить stepper1
PORTB = B00000000; //устанавливает все контакты с 8 по 13 в состояние LOW, чтобы выключить stepper2
}
void setup() {
Serial.begin(9600);//запускаем последовательный порт bluetooth - отправка и получение на скорости 9600 бод
// устанавливаем скорость 60 об/мин:
myStepper1.setSpeed(700);
myStepper2.setSpeed(700);
}
void loop() {
//проверить, есть ли последовательная связь, и если да, прочитать данные
if(Serial.available()) {
char data = (char)Serial.read();
// переключиться на установку символа через последовательный порт на команду
switch(data) {
case COMMAND_FORWARD:
forwardStep(num_of_steps);
break;
case COMMAND_BACK:
backwardStep(num_of_steps);
break;
case COMMAND_LEFT:
leftStep(num_of_steps);
break;
case COMMAND_RIGHT:
rightStep(num_of_steps);
break;
case COMMAND_STOP:
allStop();
break;
}
// установить переменную 'lastCall' на последний вызов из серийного номера
lastCall = data;
}
char data = lastCall;
Loop(lastCall);
Serial.read();
}
void Loop(char x){
switch(lastCall) {
case COMMAND_FORWARD:
forwardStep(num_of_steps);
break;
case COMMAND_BACK:
backwardStep(num_of_steps);
break;
case COMMAND_LEFT:
leftStep(num_of_steps);
break;
case COMMAND_RIGHT:
rightStep(num_of_steps);
break;
case COMMAND_STOP:
allStop();
break;
}
return lastCall;
(char)Serial.read();
}
@Gabriel Adams, 👍0
Обсуждение1 ответ
Проблема в том, что вы читаете из последовательного буфера без использования данных. В вашем коде есть три места, где вы используете Serial.read();
:
- Вы используете in в блоке с серийным кодом и соответствующим образом устанавливаете
lastCall
. Это нормально. - Затем вы используете его в конце
void loop()
, но ничему не присваиваете значение. - И вы используете его в конце своей собственной функции
Loop()
, снова не присваивая значение чему-либо.
Краткое объяснение того, как работает Последовательный
: Uno имеет аппаратное обеспечение для обработки последовательной связи в фоновом режиме через прерывания. Данные поступают на Uno и автоматически (в фоновом режиме) помещаются во внутренний буфер объекта Serial
. Вызов Serial.read()
удаляет самый старый байт из буфера (чтобы вы получали байты в порядке поступления) и возвращает его. Если нет доступных новых данных, он вернет -1
.
Поэтому, когда вы просто используете Serial.read()
, не присваивая значение чему-либо, вы фактически выбрасываете байты данных из последовательного буфера.
Я думал, что команда Serial.read() обеспечит более быстрое чтение последовательного ввода.
Чтения данных из буфера недостаточно. На самом деле нужно что-то с этим делать. В противном случае вы просто читаете, не реагируя. Поэтому удалите два вызова Serial.read()
, оставив только один в блоке if(Serial.available())
.
почему в данный момент он не изменит сразу направление, когда я даю новую команду, как мне использовать команду Serial.read() для быстрого перехода к новому циклу?
Вы должны удалить все вызовы delay()
. В настоящее время ваш код тратит больше всего времени на эти задержки, ничего не делая. Вместо этого вы можете использовать неблокирующий стиль кодирования из примера BlinkWithoutDelay
, который поставляется с Arduino IDE. Он использует millis()
в качестве хранителя времени, выполняя код (мигание светодиода в примере; выполнение шага в вашем коде) только тогда, когда пришло время это сделать. В Интернете есть много руководств по этому поводу.
Если вы хотите, вы можете пойти еще дальше и переключиться на библиотеку AccelStepper
, которая имеет больше возможностей, чем стандартная библиотека Stepper
. Он позволяет вам установить скорость и ускорение, а затем вы просто запускаете двигатель, достаточно часто выполняя метод run()
. Тогда нет необходимости в собственном времени шагов, потому что библиотека справляется с этим. Хотя это будет более серьезное изменение в вашем коде.
- Управление направлением шагового двигателя с помощью кнопок.
- Шаговый двигатель не работает с платой A4988
- Grbl на Arduino Uno (Elegoo) с неработающим шаговым двигателем DM542 + nema24
- Кнопка сброса не работает + не могу загрузить код, что не так?
- Принципиальная схема для работы биполярного шагового двигателя с использованием LDR
- Непрерывное обнаружение кнопок для шагового управления
- Справка по библиотеке AccelStepper - Одновременное управление двигателем
- Как позволить шаговому двигателю вращаться постоянно?
Почему вы делаете эти два
Serial.read()
, не используя результат за пределами вашего последовательного кода? Если ваши данные поступят прямо перед этим, они будут просто удалены., @chrislЯ все еще нахожусь в процессе изучения объектно-ориентированного кодирования. Я думал, что команда Serial.read() обеспечит более быстрое чтение последовательных входов. Как мне лучше оценить это? Например, вместо того, как в данный момент он не изменит направление немедленно, когда я даю новую команду, как мне использовать команду Serial.read() для быстрого перехода к новому циклу., @Gabriel Adams
Кажется, у вас странное понимание параметров функции, которые не используются функциями. Кстати: прототипирование функций выполняется за вас IDE, но если вы делаете это самостоятельно, делайте это правильно: параметры должны подходить., @DataFiddler