Может ли кто-нибудь помочь мне решить вопрос цикла и пару других для моей программы?

В настоящее время я работаю над комплектом смарт-машины elegoo uno r3, в котором используется Arduino. Я написал некоторый код, и он работает по большей части, но мне не помешала бы помощь. Я пытаюсь понять, что мне нужно сделать, чтобы моя квадратная программа зациклилась и продолжалась до тех пор, пока не будет нажата кнопка остановки. Может ли кто-нибудь помочь мне, пожалуйста? Кроме того, у меня есть 2 программы в нем. Один из них предназначен для обхода препятствий, которым управляет кнопка 2, и квадратной программы, которая управляется кнопкой 3. Кнопка остановки будет использоваться для остановки любой программы. Я поставлю код ниже.

#include <Servo.h>

//#включить <ArduinoJson.h>


// Таблица истинности левого мотора
// Вот несколько удобных таблиц, показывающих различные режимы работы.
// ENB IN1 IN2 Описание
// НИЗКИЙ Неприменимо Неприменимо Двигатель выключен
// HIGH LOW LOW Двигатель остановлен (тормоза)
// ВЫСОКИЙ ВЫСОКИЙ НИЗКИЙ Двигатель включен и вращается вперед
// ВЫСОКИЙ НИЗКИЙ ВЫСОКИЙ Двигатель включен и вращается назад
// HIGH HIGH HIGH Двигатель остановлен (тормоза)
#include <IRremote.h>

//#включить <Servo.h>
Servo myservo;      // создаем сервообъект для управления сервоприводом
// Сервопривод; // Создаем объект привода постоянного тока
//#включить <stdio.h>

//#включаем "HardwareSerial.h"

int Echo = A4;  
int Trig = A5;

//значения кнопок дистанционного управления/ таблица данных===========================
#define f 16736925    // ВПЕРЕД
#define b 16754775    // НАЗАД
#define l 16720605    // СЛЕВА
#define r 16761405    // ПРАВО
#define s 16712445    // СТОП
#define KEY2 16750695 //режим обхода препятствий
#define KEY3 16756815 // квадратный режим

#define KEY_STAR 16728765
#define KEY_HASH 16732845


// определить контакт ввода-вывода
#define ENB 5
#define IN1 7
#define IN2 8
#define IN3 9
#define IN4 11
#define ENA 6
#define RECV_PIN 12
#define ECHO_PIN A4
#define TRIG_PIN A5
#define LED_Pin 13
#define carSpeed 250
int rightDistance = 0, leftDistance = 0, middleDistance = 0;

IRrecv irrecv(RECV_PIN);

decode_results results;



void forward(){

  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Forward");
}

void stop_r() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
   /* digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);*/
  Serial.println("Stop!");
}

void back() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, LOW);
  Serial.println("Back");
}

void left() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, LOW);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);
  Serial.println("Left");
}

void right() {
  analogWrite(ENA, carSpeed);
  analogWrite(ENB, carSpeed);
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);
  Serial.println("Right");
}

void stop_() {
  digitalWrite(ENA, LOW);
  digitalWrite(ENB, LOW);
   /* digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);*/
  Serial.println("Stop!");
}

//Подфункция ультразвукового измерения расстояния
int getDistance() {
    digitalWrite(Trig, LOW);
    delayMicroseconds(2);
    digitalWrite(Trig, HIGH);
    delayMicroseconds(10);
    digitalWrite(Trig, LOW);
    return (int)pulseIn(Echo, HIGH) / 58;
}


//--------------------ЗИГ ЗАГ--------------------------- --------------------------



//запускаем машину
void setup() {


  //pinMode(IN1, OUTPUT); //установить режим вывода IO OUTPUT
  //pinMode(IN2, OUTPUT);
 // pinMode(ENB, OUTPUT);
 // digitalWrite(ENB, HIGH); // Включить левый мотор

  myservo.attach(3);  // прикрепляем сервопривод к контакту 3 к сервообъекту
  Serial.begin(9600);
  pinMode(Echo, INPUT);
  pinMode(Trig, OUTPUT);

  pinMode(IN1, OUTPUT);     //установить режим вывода IO OUTPUT
  pinMode(IN2, OUTPUT);
  pinMode(ENB, OUTPUT);
  digitalWrite(ENB, HIGH);  // Включить левый мотор

  pinMode(ENB, OUTPUT);
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  digitalWrite(ENA, HIGH);//вперед
  digitalWrite(ENB, HIGH);


  pinMode(IN3, OUTPUT);     //установить режим вывода IO OUTPUT
  pinMode(IN4, OUTPUT);
  pinMode(ENA, OUTPUT);
  digitalWrite(ENA, HIGH);  // Включить правый мотор

  //attachInterrupt(0,CHECK_IR,CHANGE);

  irrecv.enableIRIn(); // Запускаем приемник

  stop_r();


  //pinMode(IN3, OUTPUT); //установить режим вывода IO OUTPUT
  //pinMode(IN4, OUTPUT);
  //pinMode(ENA, OUTPUT);
  // цифровая запись (ENA, HIGH); // Включить правый мотор
}

//основной цикл============================================ ================================================== =============================
void loop() {

  if(irrecv.decode(&results)){
    Serial.println(results.value);
    irrecv.resume();
  }
  delay(100);

  //квадрат();

 if (results.value == KEY2){
     digitalWrite(ENA, HIGH);
     digitalWrite(ENB, HIGH);
    obstacleavoidance();    
    //irrecv.resume();
  } else if (results.value == s){
    stop_r();
    results.value = 12;
    //irrecv.resume();
  }

  if(results.value == KEY3){
    digitalWrite(ENA, HIGH);
     digitalWrite(ENB, HIGH);
    square();
    //irrecv.resume();
  }else if (results.value == s){
    stop_r();
    results.value = 12;
    //irrecv.resume();
  }

 /* if(results.value == KEY3){
    square();
  } else if (results.value == s){
    stop_r();
  }*/

 /*if (key_pressed == KEY2){
    obstacleavoidance();
  }
  while (key_pressed == s){
    stop_r();
  }*/

}

void get_keys(){

}

void CHECK_IR(){
  if(irrecv.decode(&results)){
    Serial.println(results.value);
    //key_pressed = results.value;
    irrecv.resume();
  }
  delay(100);
}


void square (){
  Serial.println("square");
  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);        
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, HIGH);   //иди вперед
  delay(1000);

  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);   //останавливаться
  delay(1000);

  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, LOW);  
  delay(660);              //правое колесо поворачивается вперед


  digitalWrite(IN1, LOW);
  digitalWrite(IN2, LOW);
  digitalWrite(IN3, LOW);
  digitalWrite(IN4, LOW);   //останавливаться
  delay(1000);
}

void obstacleavoidance(){

  myservo.write(90);  //установить положение сервопривода в соответствии с масштабированным значением
    delay(500);
    middleDistance = getDistance();
    // задержка (100);
    if(middleDistance <= 20) {
      stop_r();
      delay(500);
      myservo.write(10);
      delay(1000);
      rightDistance = getDistance();

      delay(500);
      myservo.write(90);
      delay(1000);
      myservo.write(180);
      delay(1000);
      leftDistance = getDistance();

      delay(500);
      myservo.write(90);
      delay(1000);
      if(rightDistance > leftDistance) {
        right();
        delay(360);
      }
      else if(rightDistance < leftDistance) {
        left();
        delay(360);
      }
      else if((rightDistance <= 20) || (leftDistance <= 20)) {
        back();
        delay(180);
      }
      else {
        forward();
      }
    }
    else {
        forward();
    }
}

, 👍1

Обсуждение

вам нужно очистить свой код, прежде чем делать что-либо еще... нет причин повторять команды в setup().... вы определяете функции для left(), right(), forward() и т. д., но вы не используйте функции в Square(), @jsotola

Ваша проблема в том, что вы используете код блокировки для square() и obstacleavoidance(). Ничто другое не может произойти во время вызова delay(), даже проверка кнопки (если только вы не используете прерывания). Вы должны переписать свой код без каких-либо вызовов delay(), чтобы Arduino могла делать это, например, изменять выходы, когда придет время, и проверять кнопки между ними. Для этого посмотрите на пример BlinkWithoutDelay, который поставляется с Arduino IDE. Он объясняет, как использовать millis() в качестве источника времени., @chrisl

Также вы должны изучить конечные автоматы (FSM). Это довольно простая техника программирования, которая поможет вам упорядочить код и придать ему хорошую структуру для работы. Для обоих упомянутых стилей кодирования в Интернете есть учебные пособия., @chrisl

@sempaiscuba Не могли бы вы помочь мне переписать код так, как вы объясняете? Я совершенно новичок в программировании Arduino., @Hannah

Начните с изучения того, как использовать millis(). В сети есть куча обучающих программ для этого. После того, как вы это поняли, вы можете искать реализацию FSM. Должно быть достаточно материала, который можно погуглить. Помнится, я уже писал ответы про автоматы на этом сайте., @chrisl


1 ответ


1

Ханна, люди, которые пишут программное обеспечение, по своей природе ленивы, поэтому, поскольку ваш код делает одно и то же снова и снова, это совершенно чуждо большинству людей здесь :) Как правило, если вы копируете и вставляете его более одного раза, он должен быть функцией.

В верхней части кода у вас есть функции для перемещения машины, но вы, похоже, ими не пользуетесь. Их использование сделает код короче, но при этом более читабельным.

В вашей функции setup() вы постоянно устанавливаете pinMode для выводов. Сгруппируйте все вызовы pinMode(), а затем используйте контакты. Опять же, это упростит чтение кода и снизит вероятность поломки при его изменении.

Возвращаясь к вашему вопросу, как заставить бота бегать по квадратам, пока вы не нажмете кнопку? Ну, это будет примерно так:

void square ()
{
  while (condition)
  {
    for (int side = 0; side < 4 && condition; ++side)
    {
      forward ();
      delay (1000);
      stop ();
      right ();
      delay (660);
      stop();
    }
  }
}

Вам нужно найти способ связать условие с помощью кнопки остановки, я не хочу делать все за вас.

Надеюсь, это поможет, если не кричать.

,

Как указывает Крисл в своем ответе, если вы используете задержку, вы не сможете обнаруживать нажатия кнопок (или ** что-то еще **) во время задержки. Код OP действительно нуждается в рефакторинге с использованием millis()., @Duncan C