Schleife mittels Tastendruck verlassen?

/**
   Author: Omar Draidrya
   Date: 2024/07/03
   This code controls the forward and backward movement of a motor using an H-bridge.
*/

#include <AFMotor.h>
#include <Arduino.h>
#include <Servo.h>
byte triggerPin = A4;
byte echoPin = A5;
long duration, distance;
int number = 0;
byte star = 1;
Servo myservo;
unsigned long lastServoAction;
long cm, cml, cmr;
int pos = 30;
bool richtung = true; 
int val;
constexpr uint8_t minPoint{ 45 };
constexpr uint8_t maxPoint{ 135 };
constexpr uint8_t servo{ 10 };
AF_DCMotor motor1(1);  // Create motor #1 using M1 connector
AF_DCMotor motor2(2);  // Create motor #2 using M2 connector
AF_DCMotor motor3(3);  // Create motor #3 using M3 connector
AF_DCMotor motor4(4);  // Create motor #4 using M4 connector

char BT_input;

void setup() {
  Serial.begin(9600);    // Start serial communication at 9600 baud rate
  motor1.setSpeed(150);  // Set initial motor speeds
  motor2.setSpeed(150);
  motor3.setSpeed(150);
  motor4.setSpeed(150);
  pinMode(triggerPin, OUTPUT);
  pinMode(echoPin, INPUT);
  myservo.attach(servo);
  myservo.write(minPoint);
}

void loop() {
  connection();
  uint32_t myMillis = millis();

  if (myMillis - lastServoAction > 15)                          // Pause für Echounterdrückung
  {
    if (lastServoAction != 0)
    {
      Serial.print(F("timing: "));
      Serial.println(myMillis - lastServoAction);
    }

    lastServoAction = myMillis;
    constexpr uint8_t fieldTicks{ (maxPoint - minPoint) / 3 };  // (40) gleichmässig Bereiche über den gesamten Arbeitsbereich verteilen
    static uint32_t tempData = 0;
    uint16_t d = ultra();
    tempData += d;
    /*
      Serial.print(F("Dura: "));
      Serial.print(d);
      Serial.print(F("  Summe: "));
      Serial.println(tempData);
    */

    switch (pos)
    {
      case minPoint:    // (30) ganz links
        if (!richtung)  // kommt von rechts
        {
          cml = tempData / (fieldTicks - 1);
        }

        Serial.println(F("Servo links"));
        richtung = HIGH;  // Richtungsumkehr
        tempData = 0;
        break;

      case minPoint + fieldTicks:  // (30+40 = 70)Ende linke Ausleuchtung - Anfang Mitte
        if (richtung)              // Auf dem Weg nach rechts
        {
          cml = tempData / (fieldTicks - 1);
        }
        else      // auf dem Weg nach links
        {
          cm = tempData / (fieldTicks - 1);
        }

        Serial.println(F("tick 70"));
        tempData = 0;
        break;

      case maxPoint - fieldTicks:  // (150-40 = 110) Ende Mitte - Anfang rechte Ausleuchtung
        if (!richtung)             // Auf dem Weg nach links
        {
          cmr = tempData / (fieldTicks - 1);
        }
        else      // Auf dem Weg nach rechts
        {
          cm = tempData / (fieldTicks - 1);
        }

        Serial.println(F("110 tick"));
        tempData = 0;
        break;

      case maxPoint:  // (150) ganz rechts
        if (richtung)
        {
          cmr = tempData / (fieldTicks - 1);
        }

        Serial.println(F("Servo rechts"));
        richtung = LOW;
        tempData = 0;
        break;
    }

    if (richtung)
    {
      pos+=8;
    }
    else
    {
      pos-=8;
    }

    // Fehlerbehandlung
    if (pos > maxPoint)
    {
      pos = maxPoint;
      Serial.println(F("maxPosFail"));
    }

    if (pos < minPoint)
    {
      pos = minPoint;
      Serial.println(F("minPosFail"));
    }

    myservo.write(pos);  // Servo setzen
  }

    digitalWrite(triggerPin, LOW);
  delayMicroseconds(4);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  return duration / 60;
  
}

void connection() {
  if (Serial.available() > 0) {
    BT_input = Serial.read();
    Serial.println(BT_input);  // Read the incoming BT_input
    switch (BT_input) {
      case 'F':
        forward();

        break;
      case 'B':
        backward();

        break;
      case 'L':
        turnLeft();

        break;
      case 'R':
        turnRight();

        break;
      case 'S':
        stop();

        break;
      case 'X':
         static unsigned long lastAction = 0;
  static uint8_t State = 0;

  switch (State) {
    case 0:  //Foreward
      if ((cm < 30) || ((cm < 20) && (cmr < 20) && (cm < 20))) {
        Serial.println(F("zu eng...Stop"));
        stop();
        drive();  // erstmal anhalten
        State = 1;
        lastAction = millis();
      } else {
       forward();
      }
      break;
    case 1:  //Stop abwarten
      if (millis() - lastAction > 20) {
        lastAction = millis();
        Serial.println(F("Zurück"));
        backward();  // Rückwärts raus
        State = 2;
      }
      break;
    case 2:  //Zurück abwarten
      if (millis() - lastAction > 1000) {
        lastAction = millis();
        Serial.println(F("Stop"));
        stop();  // anhalten
        State = 3;
      }
      break;
    case 3:  //wohin?
      if (millis() - lastAction > 20) {
        lastAction = millis();
        if (cml < cmr) {  // Richtungsbewegung
          Serial.println(F("turnRight"));
          turnRight();
        } else {
          Serial.println(F("turnLeft"));
          turnLeft();
        }
        State = 4;
      }
      break;
    case 4:  //Stop abwarten
      if (millis() - lastAction > 20) {
        lastAction = millis();
        State = 0;
      }
      break;
  }

        break;
    }
  }
}


void drive() {
  number = random(3);
  if (number == 1) {
    turnLeft();
    delay(1500);
  } else {
    turnRight();
    delay(1500);
  }
}


void forward() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void backward() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}

void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}

void stop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
/*void automatic() {
  static unsigned long lastAction = 0;
  static uint8_t State = 0;

  switch (State) {
    case 0:  //Foreward
      if ((cm < 30) || ((cm < 20) && (cmr < 20) && (cm < 20))) {
        Serial.println(F("zu eng...Stop"));
        stop();
        drive();  // erstmal anhalten
        State = 1;
        lastAction = millis();
      } else {
       forward();
      }
      break;
    case 1:  //Stop abwarten
      if (millis() - lastAction > 20) {
        lastAction = millis();
        Serial.println(F("Zurück"));
        backward();  // Rückwärts raus
        State = 2;
      }
      break;
    case 2:  //Zurück abwarten
      if (millis() - lastAction > 1000) {
        lastAction = millis();
        Serial.println(F("Stop"));
        stop();  // anhalten
        State = 3;
      }
      break;
    case 3:  //wohin?
      if (millis() - lastAction > 20) {
        lastAction = millis();
        if (cml < cmr) {  // Richtungsbewegung
          Serial.println(F("turnRight"));
          turnRight();
        } else {
          Serial.println(F("turnLeft"));
          turnLeft();
        }
        State = 4;
      }
      break;
    case 4:  //Stop abwarten
      if (millis() - lastAction > 20) {
        lastAction = millis();
        State = 0;
      }
      break;
  }
}*/

void setServoGetDist() {

  uint32_t myMillis = millis();

  if (myMillis - lastServoAction > 15)                          // Pause für Echounterdrückung
  {
    if (lastServoAction != 0)
    {
      Serial.print(F("timing: "));
      Serial.println(myMillis - lastServoAction);
    }

    lastServoAction = myMillis;
    constexpr uint8_t fieldTicks{ (maxPoint - minPoint) / 3 };  // (40) gleichmässig Bereiche über den gesamten Arbeitsbereich verteilen
    static uint32_t tempData = 0;
    uint16_t d = ultra();
    tempData += d;
    /*
      Serial.print(F("Dura: "));
      Serial.print(d);
      Serial.print(F("  Summe: "));
      Serial.println(tempData);
    */

    switch (pos)
    {
      case minPoint:    // (30) ganz links
        if (!richtung)  // kommt von rechts
        {
          cml = tempData / (fieldTicks - 1);
        }

        Serial.println(F("Servo links"));
        richtung = HIGH;  // Richtungsumkehr
        tempData = 0;
        break;

      case minPoint + fieldTicks:  // (30+40 = 70)Ende linke Ausleuchtung - Anfang Mitte
        if (richtung)              // Auf dem Weg nach rechts
        {
          cml = tempData / (fieldTicks - 1);
        }
        else      // auf dem Weg nach links
        {
          cm = tempData / (fieldTicks - 1);
        }

        Serial.println(F("tick 70"));
        tempData = 0;
        break;

      case maxPoint - fieldTicks:  // (150-40 = 110) Ende Mitte - Anfang rechte Ausleuchtung
        if (!richtung)             // Auf dem Weg nach links
        {
          cmr = tempData / (fieldTicks - 1);
        }
        else      // Auf dem Weg nach rechts
        {
          cm = tempData / (fieldTicks - 1);
        }

        Serial.println(F("110 tick"));
        tempData = 0;
        break;

      case maxPoint:  // (150) ganz rechts
        if (richtung)
        {
          cmr = tempData / (fieldTicks - 1);
        }

        Serial.println(F("Servo rechts"));
        richtung = LOW;
        tempData = 0;
        break;
    }

    if (richtung)
    {
      pos+=8;
    }
    else
    {
      pos-=8;
    }

    // Fehlerbehandlung
    if (pos > maxPoint)
    {
      pos = maxPoint;
      Serial.println(F("maxPosFail"));
    }

    if (pos < minPoint)
    {
      pos = minPoint;
      Serial.println(F("minPosFail"));
    }

    myservo.write(pos);  // Servo setzen
  }
}
long ultra() {
  digitalWrite(triggerPin, LOW);
  delayMicroseconds(4);
  digitalWrite(triggerPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(triggerPin, LOW);
  duration = pulseIn(echoPin, HIGH);
  return duration / 60;
}

mit +=8 und -=8 bin ich schon nah dran, wahrscheinlich eher 10. Jetzt will er den ersten Befehl ausführen und bleibt dann dadrin hängen. <--- per Tastendruck kommt man aber raus

Fehler gefunden -.-

So ein Durcheinander. Was soll die Funktion setServoGetDist(), wenn sie eh nicht verwendet und alles in der loop() verwurstet wird?

Warum diese Rechnerei mit den fieldTicks? Die ist doch auch "statisch". Da kannst Du auch gleich die Servopositionen in einem Array vorgeben....

Beispiel (nur Servosteuerung mit Entfernungsmessung):

#include "Servo.h"
#include "HCSR04.h"

using MillisType = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;

namespace gc {
constexpr uint8_t EchoPin {A5};
constexpr uint8_t TrigPin {A4};
constexpr uint8_t ServoPin {10};
constexpr MillisType SensorInterval {2000};
}   // namespace gc

class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const MillisType duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  MillisType timeStamp {0};
};

constexpr uint8_t ServoPositions[] {30, 70, 110, 150, 110, 70};
//constexpr uint8_t ServoPositions[] {30, 70, 110, 150};

Servo SonarServo;
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

template <size_t N> unsigned int checkDistance(const uint8_t (&SPos)[N], uint8_t& Idx, Servo& Sv, USDSensor& DSensor) {
  if (Idx >= N) { Idx = N-1; }
  Sv.write(SPos[Idx]);
  Idx = (Idx + 1) % N;
  return DSensor.measureDistanceCm();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start Program and wait a little...");
  SonarServo.attach(gc::ServoPin);
  delay(5000);
  Serial.println("Go...");
}

void loop() {
  static uint8_t Index {0};

  if (SensorTimer(gc::SensorInterval)) {
    unsigned Distance = checkDistance(ServoPositions, Index, SonarServo, DistanceSensor);
    Serial.println(Distance);
    SensorTimer.start();
  }
}

Oder etwas objektorientierter was bei den Definitionen mehr Arbeit macht, aber das Handling im folgenden Programm etwas vereinfacht:

#include "Servo.h"
#include "HCSR04.h"

using MillisType = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;

namespace gc {
constexpr uint8_t EchoPin {A5};
constexpr uint8_t TrigPin {A4};
constexpr uint8_t ServoPin {10};
constexpr MillisType SensorInterval {2000};
}   // namespace gc

class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const MillisType duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  MillisType timeStamp {0};
};

class ServoInterface : public Servo {
public:
  virtual void operator()() = 0;
  virtual void operator()(uint8_t) = 0;
  virtual uint8_t getIndex() const = 0;
};

template <uint8_t Pin> class ServoCtrl : public ServoInterface {
public:
  template <size_t N> ServoCtrl(const uint8_t (&PosTable)[N]) : PosTable {PosTable}, TableElements {N} {}
  void begin() { this->attach(Pin); }

  virtual void operator()() override {
    this->write(PosTable[Index]);
    Index = (Index + 1) % TableElements;
  }

  virtual void operator()(uint8_t idx) override {
    if (idx < TableElements) {
      Index = idx;
      this->write(PosTable[Index]);
    }
  }

  virtual uint8_t getIndex() const override { return Index; }

private:
  const uint8_t* PosTable;
  const uint8_t TableElements;
  uint8_t Index {0};
};

// constexpr uint8_t ServoPositions[] {30, 70, 110, 150, 110, 70};
constexpr uint8_t ServoPositions[] {30, 70, 110, 150};

ServoCtrl<gc::ServoPin> SonarServo(ServoPositions);
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

unsigned int checkDistance(ServoInterface& SCtrl, USDSensor& DSensor) {
  SCtrl();
  return DSensor.measureDistanceCm();
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start Program and wait a little...");
  SonarServo.begin();
  delay(5000);
  Serial.println("Go...");
}

void loop() {
  if (SensorTimer(gc::SensorInterval)) {
     unsigned Distance = checkDistance(SonarServo, DistanceSensor);
    Serial.println(Distance);
    SensorTimer.start();
  }
}

Zum Ausprobieren:

Das ist lieb gemeint, aber das hat nix mehr mit Minimal-Prinzip zu tun und ich stehe jetzt vor dem Code wie der Ochs vor dem Scheunentor und mein Kopf sagt "TschuuuTschuuu"...

Habs versucht irgendwie umzusetzen, aber ich kriege nur rote Fehlermeldungen und es ist mit sicherheit falsch


/*
https://forum.arduino.cc/t/schleife-mittels-tastendruck-verlassen/1406825/
*/

#include <AFMotor.h>
#include <Arduino.h>
#include <Servo.h>
#include "HCSR04.h"
using MillisType = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;

namespace gc {
constexpr uint8_t EchoPin {A5};
constexpr uint8_t TrigPin {A4};
constexpr uint8_t ServoPin {10};
constexpr MillisType SensorInterval {2000};
}   // namespace gc

class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const MillisType duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  MillisType timeStamp {0};
};

constexpr uint8_t ServoPositions[] {30, 70, 110, 150, 110, 70};
//constexpr uint8_t ServoPositions[] {30, 70, 110, 150};

Servo SonarServo;
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

template <size_t N> unsigned int checkDistance(const uint8_t (&SPos)[N], uint8_t& Idx, Servo& Sv, USDSensor& DSensor) {
  if (Idx >= N) { Idx = N-1; }
  Sv.write(SPos[Idx]);
  Idx = (Idx + 1) % N;
  return DSensor.measureDistanceCm();
}
int s_links = A3;
int s_rechts = A2;
long duration, distance;
int number = 0;
Servo myservo;
unsigned long lastServoAction;
long cm, cml, cmr;
int pos = 0;
bool richtung = true;
int val;
constexpr uint8_t minPoint{ 45 };
constexpr uint8_t maxPoint{ 135 };
constexpr uint8_t servo{ 9 };
AF_DCMotor motor1(1);  // Create motor #1 using M1 connector
AF_DCMotor motor2(2);  // Create motor #2 using M2 connector
AF_DCMotor motor3(3);  // Create motor #3 using M3 connector
AF_DCMotor motor4(4);  // Create motor #4 using M4 connector

const char befehle[] = { 'F', 'B', 'L', 'R', 'S', 'X', 'Y' };

char command;

void setup() {
  Serial.begin(9600);    // Start serial communication at 9600 baud rate
  motor1.setSpeed(150);  // Set initial motor speeds
  motor2.setSpeed(150);
  motor3.setSpeed(150);
  motor4.setSpeed(150);
  SonarServo.attach(gc::ServoPin);
  delay(5000);
  pinMode(s_links, INPUT);
  pinMode(s_rechts, INPUT);
}

void loop() {
  connection();
  action();
  static uint8_t Index {0};

  if (SensorTimer(gc::SensorInterval)) {
    unsigned Distance = checkDistance(ServoPositions, Index, SonarServo, DistanceSensor);
    Serial.println(Distance);
    SensorTimer.start();
  }
}
void linefollow() {
  byte value_l = digitalRead(s_links);
  byte value_r = digitalRead(s_rechts);

  if (value_l == LOW && value_r == LOW) {
    forward();
    Serial.println("LOW und LOw");
  }
  if (value_l == HIGH && s_rechts == LOW) {
    turnLeft();
    Serial.println("HIGH und LOw");
  }
  if (value_l == LOW && value_r == HIGH) {
    turnRight();
    Serial.println("LOW und HIGH");
  }
  if (value_l == HIGH && value_r == HIGH) {
    stop();
    Serial.println("HIGH und HIGH");
  }
}

void connection() {
  if (Serial.available() > 0) {
    char newCommand = Serial.read();
    Serial.println(command);  // Read the incoming command

    if (newCommand != command && isPrintable(newCommand))  // Neues Zeichen und ist anzeigbar
    {
      Serial.print(F("Neues Commando: "));  // ausgeben
      Serial.println(newCommand);

      for (byte b = 0; b < sizeof(befehle) / sizeof(befehle[0]); b++)  // zähle durch alle vorandenen Werte
      {
        if (befehle[b] == newCommand)  // wenn vorhanden, dann übernehmen
        { command = newCommand; }
      }
    }
  }
}

void action() {
  switch (command) {
    case 'F':
      forward();
      break;

    case 'B':
      backward();
      break;

    case 'L':
      turnLeft();
      break;

    case 'R':
      turnRight();
      break;

    case 'S':
      stop();
      break;

    case 'X':
      taschenlampe();
      break;
    case 'Y':
    linefollow();
    break;
  }
}

void taschenlampe() {


  switch (distance) {
    case 1 ... 15:
      backward();
      Serial.println("rueckwaerts");
      drive();
      //Serial.println(number);
      break;

    case 16 ... 30:
      motor1.setSpeed(90);
      motor2.setSpeed(90);
      motor3.setSpeed(90);
      motor4.setSpeed(90);
      forward();
      Serial.println("langsam vor");
      break;

    case 31 ... 300:
      forward();
      Serial.println("Vorwaerts");
      break;

    default:
      backward();
      Serial.println("default");
      break;
  }
}

void drive() {
  number = random(3);

  if (number == 1) {
    turnLeft();
    delay(1500);
  } else {
    turnRight();
    delay(1500);
  }
}
void forward() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void backward() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void stop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
Sketch wird kompiliert ...
"C:\\Users\\Natalie\\AppData\\Local\\Arduino15\\packages\\arduino\\tools\\avr-gcc\\7.3.0-atmel3.6.1-arduino7/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10607 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR "-IC:\\Users\\Natalie\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\cores\\arduino" "-IC:\\Users\\Natalie\\AppData\\Local\\Arduino15\\packages\\arduino\\hardware\\avr\\1.8.6\\variants\\standard" "-Ic:\\Users\\Natalie\\Documents\\Arduino\\libraries\\Adafruit_Motor_Shield_library" "-IC:\\Users\\Natalie\\AppData\\Local\\Arduino15\\libraries\\Servo\\src" "-Ic:\\Users\\Natalie\\Documents\\Arduino\\libraries\\HC-SR04\\src" "C:\\Users\\Natalie\\AppData\\Local\\arduino\\sketches\\78E3B54D84CA1ABAC3FC88F91C174208\\sketch\\20092025_robot.ino.cpp" -o "C:\\Users\\Natalie\\AppData\\Local\\arduino\\sketches\\78E3B54D84CA1ABAC3FC88F91C174208\\sketch\\20092025_robot.ino.cpp.o"
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:11:19: error: 'UltraSonicDistanceSensor' does not name a type
 using USDSensor = UltraSonicDistanceSensor;
                   ^~~~~~~~~~~~~~~~~~~~~~~~
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:33:1: error: 'USDSensor' does not name a type; did you mean 'HCSR04Sensor'?
 USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
 ^~~~~~~~~
 HCSR04Sensor
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:36:99: error: 'USDSensor' has not been declared
 template <size_t N> unsigned int checkDistance(const uint8_t (&SPos)[N], uint8_t& Idx, Servo& Sv, USDSensor& DSensor) {
                                                                                                   ^~~~~~~~~
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino: In function 'unsigned int checkDistance(const uint8_t (&)[N], uint8_t&, Servo&, int&)':
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:40:18: error: request for member 'measureDistanceCm' in 'DSensor', which is of non-class type 'int'
   return DSensor.measureDistanceCm();
                  ^~~~~~~~~~~~~~~~~
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino: In function 'void loop()':
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:82:74: error: 'DistanceSensor' was not declared in this scope
     unsigned Distance = checkDistance(ServoPositions, Index, SonarServo, DistanceSensor);
                                                                          ^~~~~~~~~~~~~~
C:\Users\Natalie\Documents\Arduino\20092025_robot\20092025_robot.ino:82:74: note: suggested alternative: 'Distance'
     unsigned Distance = checkDistance(ServoPositions, Index, SonarServo, DistanceSensor);
                                                                          ^~~~~~~~~~~~~~
                                                                          Distance
Bibliothek Adafruit Motor Shield library in Version 1.0.1 im Ordner: C:\Users\Natalie\Documents\Arduino\libraries\Adafruit_Motor_Shield_library  wird verwendet
Bibliothek Servo in Version 1.2.2 im Ordner: C:\Users\Natalie\AppData\Local\Arduino15\libraries\Servo  wird verwendet
Bibliothek HC-SR04 in Version 1.1.3 im Ordner: C:\Users\Natalie\Documents\Arduino\libraries\HC-SR04  wird verwendet
exit status 1

Compilation error: 'UltraSonicDistanceSensor' does not name a type

Ist meine Lieblingsfarbe :rofl:

Vermutlich hast Du eine andere Bibliothek, versuche mal diese: GitHub - Martinsos/arduino-lib-hc-sr04: Arduino library for HC-SR04 ultrasonic distance sensor.

jo das hat geholfen, aber die Werte können auch nicht stimmen

14:04:16.448 -> 65535
14:04:18.451 -> 65535
14:04:20.507 -> 65535
14:04:22.498 -> 65535
14:04:24.524 -> 65535
14:04:26.547 -> 65535
14:04:28.579 -> 65535
14:04:30.598 -> 65535
14:04:32.657 -> 65535
14:04:34.656 -> 65535

und der Servo bewegt sich nicht :wink:

Hab den Code mal ohne meinen probiert und der Servo bewegt sich, aber die Werte bleiben gleich

Index: 1 Distance: 65535
14:09:53.368 -> Index: 2 Distance: 65535
14:09:55.404 -> Index: 3 Distance: 65535
14:09:57.407 -> Index: 0 Distance: 65535
14:09:59.424 -> Index: 1 Distance: 65535
14:10:01.491 -> Index: 2 Distance: 65535
14:10:03.496 -> Index: 3 Distance: 65535
14:10:05.518 -> Index: 0 Distance: 65535
14:10:07.554 -> Index: 1 Distance: 65535
14:10:09.557 -> Index: 2 Distance: 65535
14:10:11.593 -> Index: 3 Distance: 65535
14:10:13.613 -> Index: 0 Distance: 65535
14:10:15.632 -> Index: 1 Distance: 65535
14:10:17.669 -> Index: 2 Distance: 65535

Mach doch probe mit Beispiel aus der Bibliothek

#include <HCSR04.h>

UltraSonicDistanceSensor distanceSensor(A4, A5);   

void setup () {
    Serial.begin(9600);  // We initialize serial connection so that we could print values from sensor.
}

void loop () {
    // Every 500 miliseconds, do a measurement using the sensor and print the distance in centimeters.
    Serial.println(distanceSensor.measureDistanceCm());
    delay(500);
}

Jo also der hat funktioniert. Hab auch zur Sicherheit nochmal einen 2. HC-SR04 probiert, aber das selbe.


/*
https://forum.arduino.cc/t/schleife-mittels-tastendruck-verlassen/1406825/
*/

#include <AFMotor.h>
#include <Arduino.h>
#include <Servo.h>
#include "HCSR04.h"
using MillisType = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;

namespace gc {
constexpr uint8_t EchoPin {A5};
constexpr uint8_t TrigPin {A4};
constexpr uint8_t ServoPin {9};
constexpr MillisType SensorInterval {2000};
}   // namespace gc

class Timer {
public:
  void start() { timeStamp = millis(); }
  bool operator()(const MillisType duration) const { return (millis() - timeStamp >= duration) ? true : false; }

private:
  MillisType timeStamp {0};
};

constexpr uint8_t ServoPositions[] {30, 70, 110, 150, 110, 70};
//constexpr uint8_t ServoPositions[] {30, 70, 110, 150};

Servo SonarServo;
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

template <size_t N> unsigned int checkDistance(const uint8_t (&SPos)[N], uint8_t& Idx, Servo& Sv, USDSensor& DSensor) {
  if (Idx >= N) { Idx = N-1; }
  Sv.write(SPos[Idx]);
  Idx = (Idx + 1) % N;
  return DSensor.measureDistanceCm();
}
int s_links = A3;
int s_rechts = A2;
long duration, distance,Distance;
int number = 0;
Servo myservo;
unsigned long lastServoAction;
long cm, cml, cmr;
int pos = 0;
bool richtung = true;
int val;
constexpr uint8_t minPoint{ 45 };
constexpr uint8_t maxPoint{ 135 };
//constexpr uint8_t servo{ 9 };
AF_DCMotor motor1(1);  // Create motor #1 using M1 connector
AF_DCMotor motor2(2);  // Create motor #2 using M2 connector
AF_DCMotor motor3(3);  // Create motor #3 using M3 connector
AF_DCMotor motor4(4);  // Create motor #4 using M4 connector

const char befehle[] = { 'F', 'B', 'L', 'R', 'S', 'X', 'Y' };

char command;

void setup() {
  Serial.begin(9600);    // Start serial communication at 9600 baud rate
  motor1.setSpeed(150);  // Set initial motor speeds
  motor2.setSpeed(150);
  motor3.setSpeed(150);
  motor4.setSpeed(150);
  SonarServo.attach(gc::ServoPin);
  delay(5000);
  pinMode(s_links, INPUT);
  pinMode(s_rechts, INPUT);
}

void loop() {
  connection();
  action();
  static uint8_t Index {0};

  if (SensorTimer(gc::SensorInterval)) {
    unsigned Distance = checkDistance(ServoPositions, Index, SonarServo, DistanceSensor);
    Serial.println(Distance);
    SensorTimer.start();
  }
}
void linefollow() {
  byte value_l = digitalRead(s_links);
  byte value_r = digitalRead(s_rechts);

  if (value_l == LOW && value_r == LOW) {
    forward();
    Serial.println("LOW und LOw");
  }
  if (value_l == HIGH && s_rechts == LOW) {
    turnLeft();
    Serial.println("HIGH und LOw");
  }
  if (value_l == LOW && value_r == HIGH) {
    turnRight();
    Serial.println("LOW und HIGH");
  }
  if (value_l == HIGH && value_r == HIGH) {
    stop();
    Serial.println("HIGH und HIGH");
  }
}

void connection() {
  if (Serial.available() > 0) {
    char newCommand = Serial.read();
    Serial.println(command);  // Read the incoming command

    if (newCommand != command && isPrintable(newCommand))  // Neues Zeichen und ist anzeigbar
    {
      Serial.print(F("Neues Commando: "));  // ausgeben
      Serial.println(newCommand);

      for (byte b = 0; b < sizeof(befehle) / sizeof(befehle[0]); b++)  // zähle durch alle vorandenen Werte
      {
        if (befehle[b] == newCommand)  // wenn vorhanden, dann übernehmen
        { command = newCommand; }
      }
    }
  }
}

void action() {
  switch (command) {
    case 'F':
      forward();
      break;

    case 'B':
      backward();
      break;

    case 'L':
      turnLeft();
      break;

    case 'R':
      turnRight();
      break;

    case 'S':
      stop();
      break;

    case 'X':
      taschenlampe();
      break;
    case 'Y':
    linefollow();
    break;
  }
}

void taschenlampe() {


  switch (Distance) {
    case 1 ... 15:
      backward();
      Serial.println("rueckwaerts");
      drive();
      //Serial.println(number);
      break;

    case 16 ... 30:
      motor1.setSpeed(90);
      motor2.setSpeed(90);
      motor3.setSpeed(90);
      motor4.setSpeed(90);
      forward();
      Serial.println("langsam vor");
      break;

    case 31 ... 300:
      forward();
      Serial.println("Vorwaerts");
      break;

    default:
      backward();
      Serial.println("default");
      break;
  }
}

void drive() {
  number = random(3);

  if (number == 1) {
    turnLeft();
    delay(1500);
  } else {
    turnRight();
    delay(1500);
  }
}
void forward() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void backward() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void stop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}

Ich habe den Code auch in "Echt" probiert. Funktioniert einwandfrei.

Dann stimmt etwas mit Deiner Elektronik nicht. Distanzsensor falsch angeschlossen. Zu wenig Power für den Servo/Controller oder was auch immer...

Ziel des Beispielcodes war es eigentlich nur zu zeigen, dass man mit vorgefertigten Tabellen (in diesem Fall einem einfachen Array) viel Programmierarbeit und Rechnerei sparen kann.

Das Drumherum war halt zur Ansteuerung eines Servos und der Einbindung eines Distanzsensors notwendig um ein lauffähiges Beispiel zeigen zu können.
Das habe ich halt auf "meine" Art gemacht. Ja, das hat nicht viel mit Deinem Programm gemein.

Aber das Verständnis von Arrays passt zu Deiner "void" Frage im anderen Thread. Die Kenntnis von Datentypen ist sehr wichtig. Man kann es nicht oft genug sagen.

Und wenn Du dir das Verständnis angeeignet hast, weißt Du auch, wie Du das in Dein Programm einbauen kannst.

Ich hatte deine erste Variante ausprobiert, die hat nicht geklappt. Die 2. Variante hat funktioniert.

Die „erste“ Variante funktioniert aber auch :wink:

Gut..... er gibt mir jetzt die 3 Werte aus. Wie deklariere ich die nun, sodass ich Sie nutzen kann. Sodass die dann in cm, cmr und cml gespeichert werden

Die sind schon deklariert und definiert.

Vielleicht meinst du "zuweisen"...?
Dafür gibts den Zuweisungsoperator.

16:54:36.200 -> 57
16:54:38.220 -> 45
16:54:40.220 -> 27
16:54:42.204 -> 53
16:54:44.240 -> 81
16:54:46.242 -> 51
16:54:48.247 -> 27
16:54:50.255 -> 53
16:54:52.286 -> 81
16:54:54.308 -> 60

Die Werte möchte ich gern cmr, cm und cml nennen. Damit man diese vergleichen kann
Als Beispiel: Ist cml und cmr > cm fahre vorwärts

Du könntest Dir z.B. einen Datentypen bauen, der zu jeder Position des Servos auch die gemessene Entfernung speichert. Im folgenden Beispiel wurde das einfache Array mit den Positionsdaten durch einen eigenen Datentypen "ServoData" ersetzt. Dieser Datentyp ist eine Struktur, die die Positionsdaten und die gemessene Entfernung speichern kann.

Aus diesem Datentyp wurde ein Array für vier Positionen gebaut. So hast Du im Programm jederzeit Zugriff auf alle gemessenen Positionsdaten und kannst sie auswerten.

Die checkDistance() Funktion wurde in der Parameterliste auf den neuen Datentyp geändert. Außerdem wurde noch die Variable Step mitgegeben um eine Richtungsänderung des Servos bewirken zu können.

Der Typ der Funktion ist jetzt void, weil sie keinen Wert mehr zurück gibt. Die Datenstruktur wird als Referenz übergeben, behält also die Werte, die Ihr in der Funktion zugewiesen wurden.

#include "Servo.h"
#include "HCSR04.h"

using millis_t = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;

namespace gc {
constexpr uint8_t EchoPin {A5};
constexpr uint8_t TrigPin {A4};
constexpr uint8_t ServoPin {10};
constexpr millis_t SensorInterval {2000};
}   // namespace gc

class Timer {
public:
  void start() { TimeSpamp = millis(); }
  bool operator()(const millis_t duration) const { return (millis() - TimeSpamp >= duration) ? true : false; }

private:
  millis_t TimeSpamp {0};
};

struct ServoData {
  const uint8_t ServoPos;
  unsigned int Distance;
};

ServoData ServoPosData[] {
    {30,  0},
    {70,  0},
    {110, 0},
    {150, 0}
};

Servo SonarServo;
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

template <size_t N>
void checkDistance(ServoData (&SPData)[N], uint8_t& Idx, int8_t& Step, Servo& Sv, USDSensor& DSensor) {
  if (Idx >= N) { Idx = N - 2; }
  Sv.write(SPData[Idx].ServoPos);
  SPData[Idx].Distance = DSensor.measureDistanceCm();
  Idx += Step;
  if (Idx == 0 || Idx >= N) {
    if (Idx >= N) {
      Step = -1;
      Idx = N - 2;
    } else {
      Step = 1;
    }
  }
}

void setup() {
  Serial.begin(115200);
  Serial.println("Start Program and wait a little...");
  SonarServo.attach(gc::ServoPin);
  delay(5000);
  Serial.println("Go...");
}

void loop() {
  static uint8_t Index {0};
  static int8_t Step {1};

  if (SensorTimer(gc::SensorInterval)) {
    Serial.print("Index: ");
    Serial.println(Index);
    checkDistance(ServoPosData, Index, Step, SonarServo, DistanceSensor);
    for (auto const& Data : ServoPosData) {
      Serial.print(" Servoposition: ");
      Serial.print(Data.ServoPos);
      Serial.print(" Distance: ");
      Serial.println(Data.Distance);
    }
    SensorTimer.start();
  }
}

Danke erstmal für die Hilfe. Soweit läuft alles :slight_smile:
Ich möchte eine Linefollower Funtkion einbauen. Nun habe ich das Problem, dass der Servo oder der Ultrasensor den Tracker Sensor (lt. Beschreibung auf dem Sensor) beeinflusst. Immer wenn er auf 90 und 150 scannt, wird der rechte Tracker aktiviert/deaktiviert. Kann mir jemand sagen woran das liegt und wie ich das korrigiere?

#include <AFMotor.h>
#include <Arduino.h>
#include <Servo.h>
#include "HCSR04.h"
#include <SoftwareSerial.h>

int ll, rr;
#define right A2
#define left A3
SoftwareSerial mySerial(A0, A1);
const char befehle[] = { 'F', 'B', 'L', 'R', 'S', 'X', 'Y' };
byte number;
char command;
using millis_t = decltype(millis());
using USDSensor = UltraSonicDistanceSensor;
int links, rechts, mitte;
namespace gc {
constexpr uint8_t EchoPin{ A5 };
constexpr uint8_t TrigPin{ A4 };
constexpr uint8_t ServoPin{ 10 };
constexpr millis_t SensorInterval{ 2000 };
}  // namespace gc

class Timer {
public:
  void start() {
    TimeSpamp = millis();
  }
  bool operator()(const millis_t duration) const {
    return (millis() - TimeSpamp >= duration) ? true : false;
  }

private:
  millis_t TimeSpamp{ 0 };
};

struct ServoData {
  const uint8_t ServoPos;
  unsigned int Distance;
};

ServoData ServoPosData[]{
  { 30, 0 },
  { 90, 0 },
  { 150, 0 }
};

Servo SonarServo;
USDSensor DistanceSensor(gc::TrigPin, gc::EchoPin);
Timer SensorTimer;

template<size_t N>
void checkDistance(ServoData (&SPData)[N], uint8_t& Idx, int8_t& Step, Servo& Sv, USDSensor& DSensor) {
  if (Idx >= N) { Idx = N - 2; }
  Sv.write(SPData[Idx].ServoPos);
  SPData[Idx].Distance = DSensor.measureDistanceCm();
  Idx += Step;
  if (Idx == 0 || Idx >= N) {
    if (Idx >= N) {
      Step = -1;
      Idx = N - 2;
    } else {
      Step = 1;
    }
  }
}
AF_DCMotor motor1(1);  // Create motor #1 using M1 connector
AF_DCMotor motor2(2);  // Create motor #2 using M2 connector
AF_DCMotor motor3(3);  // Create motor #3 using M3 connector
AF_DCMotor motor4(4);  // Create motor #4 using M4 connector
void setup() {
  Serial.begin(115200);
  Serial.println("Start Program and wait a little...");
  SonarServo.attach(gc::ServoPin);
  delay(5000);
  Serial.println("Go...");
  motor1.setSpeed(150);  // Set initial motor speeds
  motor2.setSpeed(150);
  motor3.setSpeed(150);
  motor4.setSpeed(150);
  mySerial.begin(9600);
}

void loop() {
  static uint8_t Index{ 0 };
  static int8_t Step{ 1 };
  if (mySerial.available() > 0) {
    char newCommand = mySerial.read();
    Serial.println(command);  // Read the incoming command

    if (newCommand != command && isPrintable(newCommand))  // Neues Zeichen und ist anzeigbar
    {
      Serial.print(F("Neues Commando: "));  // ausgeben
      Serial.println(newCommand);

      for (byte b = 0; b < sizeof(befehle) / sizeof(befehle[0]); b++)  // zähle durch alle vorandenen Werte
      {
        if (befehle[b] == newCommand)  // wenn vorhanden, dann übernehmen
        { command = newCommand; }
      }
    }
  }
  action();

  if (SensorTimer(gc::SensorInterval)) {
    //Serial.print("Index: ");
    //Serial.println(Index);
    checkDistance(ServoPosData, Index, Step, SonarServo, DistanceSensor);
    for (auto const& Data : ServoPosData) {
      //Serial.print(" Servoposition: ");
      //Serial.print(Data.ServoPos);
      //Serial.print(" Distance: ");
      //Serial.println(Data.Distance);
      if (Data.ServoPos == 30) {
        links = Data.Distance;
        //Serial.println(links);
      }
      if (Data.ServoPos == 90) {
        mitte = Data.Distance;
        //Serial.println(mitte);
      }

      if (Data.ServoPos == 150) {
        rechts = Data.Distance;
        //Serial.println(rechts);
      }
    }
    SensorTimer.start();
  }
}
/*void getData() {
  while (mySerial.available()) {
    //char myChar = Serial.read();
    char myChar = mySerial.read();

    if (isAlpha(myChar)) {
      myChar = ucase(myChar);
      switch (myChar) {
        case 'X':  //automatic
        case 'Y':  //linefollow
        case 'B':  //backward
        case 'F':  //forward
        case 'L':  //left
        case 'R':  //right
        case 'S':  //stop
          Serial.print(F("Input Char: "));
          Serial.println(myChar);
          BT_input = myChar;
          break;  //gültiges Zeichen
        default:
          if (myChar >= ' ') {
            Serial.print(F("FailChar: "));
            Serial.println(myChar, HEX);
            BT_input = 'S';
          }
      }
    }
  }
  if (oldInput != BT_input) {
    drive(stop);
    delay(20);  // kurze Pause schont die Antriebe!
    oldInput = BT_input;
  }
}
char ucase(const char c) {
  if (c >= 'a' && c <= 'z') {
    return (c + ('A' - 'a'));
  }
  return c;
}
*/
void action() {
  switch (command) {
    case 'F':
      forward();
      break;

    case 'B':
      backward();
      break;

    case 'L':
      turnLeft();
      break;

    case 'R':
      turnRight();
      break;

    case 'S':
      stop();
      break;

    case 'X':
      if (links < 15) {
        turnRight();
        delay(20);
      }
      if (rechts < 15) {
        turnLeft();
        delay(20);
      }
      if (rechts < 15 && links < 15) {
        backward();
        delay(20);
        drive();
        delay(20);
      }
      if (mitte < 15) {
        backward();
        delay(20);
      }
      if (mitte > 15 && rechts > 15 && links > 15) {
        forward();
        delay(20);
      }
      break;
    case 'Y':   ll = analogRead(left)*10;
   rr = analogRead(right)*10;
Serial.println (ll);
Serial.println (rr);

  if (ll <= 400 && rr <= 400) {
    stop();
    delay(20);
    Serial.println ("Stop");
  } else if (ll >= 400 && rr <= 400) {
    turnLeft();
    delay(300);
    Serial.println ("turnLeft");
  } else if (ll >= 400 && rr >= 400) {
    turnRight();
    delay(300);
    Serial.println ("turnRight");
  } else if (ll >= 400 && rr >= 400) {
    forward();
    delay(20);
    Serial.println ("Forward");
  } break;
  }
}

void drive() {
  number = random(3);

  if (number == 1) {
    turnLeft();
    delay(1500);
  } else {
    turnRight();
    delay(1500);
  }
}
void forward() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void backward() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void turnLeft() {
  motor1.run(BACKWARD);
  motor2.run(BACKWARD);
  motor3.run(FORWARD);
  motor4.run(FORWARD);
}
void turnRight() {
  motor1.run(FORWARD);
  motor2.run(FORWARD);
  motor3.run(BACKWARD);
  motor4.run(BACKWARD);
}
void stop() {
  motor1.run(RELEASE);
  motor2.run(RELEASE);
  motor3.run(RELEASE);
  motor4.run(RELEASE);
}
void linefollower() {
  ll = analogRead(left);
   rr = analogRead(right);
Serial.println (ll);
Serial.println (rr);

  if (ll <= 400 && rr <= 400) {
    stop();
    delay(20);
    Serial.println ("Stop");
  } else if (ll <= 400 && rr >= 400) {
    turnLeft();
    delay(300);
    Serial.println ("turnLeft");
  } else if (ll >= 400 && rr <= 400) {
    turnRight();
    delay(300);
    Serial.println ("turnRight");
  } else if (ll >= 400 && rr >= 400) {
    forward();
    delay(20);
    Serial.println ("Forward");
  }
}

A0 ist das Problem oder?

Wie kommst du darauf?

Blicke leider nicht durch, ist mir nicht modular genug.
Zu viele if, delay usw.

Das ist übrigens zu kompliziert!

 bool operator()(const millis_t duration) const {
    return millis() - TimeSpamp >= duration;
  }

Reicht aus, da der Ausdruck selber schon einen bool liefert.

War nur mal eine Idee, woran ich vermute das es liegt und ich hab mal umgepinnt und den A0er auf dem freien digitalen Port 2 gesteckt und jetzt habe ich es nicht mehr, dass der Tracker beim 90 und 150 tick ausgelöst wird.

Verstehe ich nicht!
Sehe ich nicht.
Sehe nur dass du A0 für Software Serial verwendest.