Как управлять двумя шаговыми двигателями и использовать ультразвуковой датчик вместе?

Я работаю над автономным роботом с двумя 4-контактными шаговыми двигателями, ультразвуковым датчиком HC-SR04, двумя драйверами двигателей L298N (по одному на каждый двигатель) и Arduino Uno. Моя проблема в том, что когда я использую шаговые двигатели с библиотекой Stepper, одновременно работает только один двигатель. Мое решение заключалось в том, чтобы контролировать шаг за шагом в течение короткого периода времени, что сработало, однако это создает новую проблему. Ультразвуковой датчик требует задержки для работы, но это делает движение робота довольно медленным и дерганым, поскольку он работает только по одному шагу за раз. Когда я убираю задержку с ультразвукового датчика, он начинает возвращать правильное значение, но также возвращает 0 сразу после каждого правильного значения. Мое решение состояло в том, чтобы игнорировать возвращенный 0, но это не идеально.

Как я могу одновременно использовать два шаговых двигателя и использовать ультразвуковой датчик?

Вот мой код:

#include <Stepper.h>
#include <Ultrasonic.h>

/*
* Передать в качестве параметра вывод триггера и эха соответственно,
* или только сигнальный контакт (для датчиков 3 контакта), например:
* Ультразвуковой ультразвуковой(13);
*/
 Ultrasonic ultrasonic(13, 12);
 int distance;

 int driveSpeed = 100;
 int stepsPerRevolution = 200;
 int leftMotorStep = 0;
 int rightMotorStep = 0;

 // Интервал времени между шагами для обоих моторов
 const int stepInterval = 10;  // При необходимости отрегулируйте

 // Время последнего шага для каждого двигателя
 unsigned long leftMotorLastStepTime = 0;
 unsigned long rightMotorLastStepTime = 0;

 Stepper rightMotor(stepsPerRevolution, 8, 9, 10, 11);
 Stepper leftMotor(stepsPerRevolution, 4, 5, 6, 7);

 void setup() {
   Serial.begin(9600);
   rightMotor.setSpeed(driveSpeed);
   leftMotor.setSpeed(driveSpeed);
 }
 void loop() {
   distance = ultrasonic.read();

   Serial.print("Distance in CM: ");
   Serial.println(distance);
   delay(250); //Эта задержка заставляет моторы вести себя странно

   if (distance < 15) {
     Serial.println("AVOIDING OBSTACLE!");
     // Выполнение действий по избеганию препятствий
     avoidObstacle();
   } else if (distance < 30) {
     Serial.println("APPROACHING OBSTACLE!");
     // Выполняем медленное приближение
     slowApproach();
   } else {
     Serial.println("DRIVING!");
     // Делаем обычное поведение вождения
     drive();
   }
 }

 void avoidObstacle() {
   // Остановить робота
   halt();

   // Поворачиваем робота, чтобы избежать препятствия
   leftM();

   // Задержка для завершения вращения
   delay(1000);
 }

 void slowApproach() {
   // Замедлить моторы
   int slowSpeed = 50;
   rightMotor.setSpeed(slowSpeed);
   leftMotor.setSpeed(slowSpeed);

   // Медленно двигаем робота вперед
   forwardM();

   // Задержка для медленного подхода
   delay(1000);
 }

 void drive() {
   // Возвращаем моторы к нормальной скорости
   rightMotor.setSpeed(driveSpeed);
   leftMotor.setSpeed(driveSpeed);

   // Двигаем робота вперед
   forwardM();
 }

 void forwardM() {
   rightMotor.step(1);
   leftMotor.step(1);
 }
 void leftM() {
   rightMotor.step(1);
   leftMotor.step(-1);
 }
 void rightM() {
   rightMotor.step(-1);
   leftMotor.step(1);
 }
 void reverseM() {
   rightMotor.step(-1);
   leftMotor.step(-1);
 }
 void halt() {
   rightMotor.step(0);
   leftMotor.step(0);
 }

, 👍1

Обсуждение

во-первых, прекратите использовать delay(), @jsotola

Когда я не использую delay(), ультразвуковой датчик возвращает 0 после каждого значения (как упоминалось в посте)., @Renier Jr.

прекратите использовать функцию delay() для введения задержки... см. скетч примера blinkWithoutDelay в Arduino IDE, @jsotola

Спасибо, это определенно помогает!, @Renier Jr.

может быть интересно... https://wokwi.com/projects/327381547863769683, @jsotola


1 ответ


Лучший ответ:

2

Попробуйте этот код.

Вот симуляция. https://wokwi.com/projects/366108641014000641

Нажмите на датчик, чтобы установить расстояние в моделировании

ПРИМЕЧАНИЕ: сантиметры — это cm, а не CM.

Не тестировалось на оборудовании.



// https://arduino.stackexchange.com/questions/93302/how-to-drive-two-stepper-motors-and-use-an-ultrasonic-sensor-together

#include <Stepper.h>
#include <Ultrasonic.h>

/*
* Передать в качестве параметра вывод триггера и эха соответственно,
* или только сигнальный контакт (для датчиков 3 контакта), например:
* Ультразвуковой ультразвуковой(13);
*/
 
 Ultrasonic ultrasonic(13, 12);
 
 int distance;

 int slowSpeed          =  100;
 int driveSpeed         = 1000;
 int stepsPerRevolution =  100;
 int leftMotorStep      =    0;                         // текущая скорость и направление шага
 int rightMotorStep     =    0;

 int stepSpeed          =   10;                         // это скорость двигателя

 const int stepInterval =    1;                         // Интервал времени между шагами для обоих моторов

 unsigned long leftMotorLastStepTime  = 0;              // Время последнего шага для каждого двигателя
 unsigned long rightMotorLastStepTime = 0;

 Stepper rightMotor(stepsPerRevolution, 8, 9, 10, 11);
 Stepper leftMotor (stepsPerRevolution, 4, 5,  6,  7);


 void setup() {
   Serial.begin(9600);
   rightMotor.setSpeed(1);
   leftMotor. setSpeed(1);
 }


 void loop() {

  distance = ultrasonic.read();

  Serial.print("Distance in cm: ");
  Serial.print(distance);  Serial.print("\t");

  switch (distance) {                              // используется switch/case для более чистого кода
    case 0 ... 14:
      Serial.println("avoid");
      avoidObstacle();                             // Выполнение действий по избеганию препятствий
      break;

    case 15 ... 29:
      Serial.println("approach");
      slowApproach();                              // Выполняем медленное приближение
      break;

    default:
      Serial.println("drive");
      drive();                                     // Делаем обычное поведение вождения
      break;
  }

  rightMotor.step(rightMotorStep);                 // это на самом деле приводит в движение моторы
  leftMotor .step(leftMotorStep);
}

 void avoidObstacle() {
   halt();                                          // Остановить робота
   leftM();                                         // Поворачиваем робота, чтобы избежать препятствия
 }

 void slowApproach() {
   rightMotor.setSpeed(slowSpeed);                  // Замедлить моторы
   leftMotor. setSpeed(slowSpeed);
   forwardM();                                      // Медленно двигаем робота вперед
 }

 void drive() {
   rightMotor.setSpeed(driveSpeed);                 // Возвращаем моторы к нормальной скорости
   leftMotor. setSpeed(driveSpeed);
   forwardM();                                      // Двигаем робота вперед
 }

 void forwardM() {
   rightMotorStep =  stepSpeed;                     // выбираем только направление шага
   leftMotorStep  =  stepSpeed;                     // не двигать двигатель
 }                                                  // фактическое пошаговое выполнение выполняется в конце цикла()
 void leftM() {
   rightMotorStep =  stepSpeed;
   leftMotorStep  = -stepSpeed;
 }
 void rightM() {
   rightMotorStep = -stepSpeed;
   leftMotorStep  =  stepSpeed;
 }
 void reverseM() {
   rightMotorStep = -stepSpeed;
   leftMotorStep  = -stepSpeed;
 }
 void halt() {
   rightMotorStep =  0;
   leftMotorStep  =  0;
 }

,

Спасибо, это действительно полезно!, @Renier Jr.