Arduino UNO - Roboclaw 2X30A - 2 Bürstenlose DC Antriebe Probleme bei Programmierung Sketch

Hallo zusammen,

ich befasse mich seit kurzer Zeit mit dem Arduino UNO und dem Roboclaw 2X 30A.

Informationen:
Arduino UNO Version 1.8.19
Basicmicro Roboclaw 2X30A Version 1.0.0.71
2X 12V BLDC Motoren für ein Panorama Display.

Problemstellung:

Die gesamte Einstellung der Motoren wie PID sowie die abfrage bzw. die Positionierung über die Encoder (Hallgeber) funktionieren einwandfrei.

Ein entsprechende Sketch habe ich erstellt und hier mit eingefügt.

Ich habe 4 Positionen (accl/speed/deccl/Position) die im Automatikbetrieb (Taster) über den Sketch abgearbeitet werden. Funktioniert einwandfrei.

Jetzt habe ich 4 weitere Taster sowie Anzeige LED´s angeschlossen und möchte eine "Schrittkette" programmieren.
Drücke Taster 1 - fahre auf Pos1
Drücke Taster 2 - fahre von Pos 1 auf 2 usw.

Ich habe schon if while Schleifen sowie mit Merkern versucht es zu realisieren, leider bisher ohne Erfolg.

Vielleicht könnt ihr mir helfen, dafür wäre ich sehr dankbar.

Hier ist der aktuelle Sketch:

//Buffered Drive M1 with signed Speed, Accel, Deccel and Position

//Includes required to use Roboclaw library
#include <SoftwareSerial.h>
#include "RoboClaw.h"

//See limitations of Arduino SoftwareSerial
SoftwareSerial serial(10, 11);
RoboClaw roboclaw(&serial, 10000);

#define address 0x80


#define ledPOS1 8                  
#define tasterPOS1 2
#define ledPOS2 13                    
#define tasterPOS2 4         
#define ledPOS3 12
#define tasterPOS3 7
#define ledPOS4 5                  
#define tasterPOS4 3
#define ledPOS5 6                    
#define tasterPOS5 9 

int merker0 = HIGH;
int merker1 = LOW;
int merker2 = LOW;
int merker3 = LOW;
int merker4 = LOW;

boolean enabledled1, enabledled2, enabledled3, enabledled4, enabledled5 = false;            // True, wenn die LED leuchtet, sonst false.
boolean buttonPOS1, buttonPOS2, buttonPOS3, buttonPOS4, buttonPOS5 = false;                 // True, wenn der Taster gedrückt wird, sonst false.



//Display Encoder and Speed for Motor 1
void displayspeed(void)
{
  uint8_t status1, status2;
  bool valid1, valid2;
  int32_t enc1 = roboclaw.ReadEncM1(address, &status1, &valid1);
  int32_t speed1 = roboclaw.ReadSpeedM1(address, &status2, &valid2);


  if (valid1) {
    Serial.print("Encoder1:");
    Serial.print(enc1, DEC);
    Serial.print(" ");
    Serial.print(status1, HEX);
    Serial.print(" ");
  }
  if (valid2) {
    Serial.print("Speed1:");
    Serial.print(speed1, DEC);
    Serial.print(" ");
  }

  Serial.println();
}


void setup() {
  //Open Serial and roboclaw at 38400bps
  Serial.begin(57600);
  roboclaw.begin(38400);

  Serial.println("Starting...");

  pinMode( tasterPOS1, INPUT_PULLUP);  // wir definieren den tasterPin als Eingang mit Pull Up
  pinMode( ledPOS1, OUTPUT);           // wir definieren den ledPin als Ausgang
  pinMode( tasterPOS2, INPUT_PULLUP);
  pinMode( ledPOS2, OUTPUT);
  pinMode( tasterPOS3, INPUT_PULLUP);
  pinMode( ledPOS3, OUTPUT);
  pinMode( tasterPOS4, INPUT_PULLUP);
  pinMode( ledPOS4, OUTPUT);
  pinMode( tasterPOS5, INPUT_PULLUP);
  pinMode( ledPOS5, OUTPUT);

}

void loop() {

  //Taster POS1 entprellen LED 1 

  if (digitalRead(tasterPOS1) == LOW) {                            
    buttonPOS1 = true;
    delay(10);                                                     
  }
  if (digitalRead(tasterPOS1) == HIGH && buttonPOS1 == true) {     
    buttonPOS1 = false;

    if (ledPOS1 == true) {                                          
      digitalWrite(ledPOS1, LOW);                                   
      enabledled1 = false;                                          
    } else {                                                        
      digitalWrite(ledPOS1, HIGH);                                  
      enabledled1 = true;                                          
    }
  }

  //Taster POS2 entprellen LED 2 

  if (digitalRead(tasterPOS2) == LOW) {                           
    buttonPOS2 = true;
    delay(10);                                                    
  }
  if (digitalRead(tasterPOS2) == HIGH && buttonPOS2 == true) {     
    buttonPOS2 = false;

    if (enabledled2 == true) {                                      
      digitalWrite(ledPOS2, LOW);                                   
      enabledled2 = false;                                          
    } else {
      digitalWrite(ledPOS2, HIGH);                                  
      enabledled2 = true;                                           
    }
  }

  //Taster Pos3 entprellen LED 3 

  if (digitalRead(tasterPOS3) == LOW) {                             
    buttonPOS3 = true;
    delay(10);                                                     
  }
  if (digitalRead(tasterPOS3) == HIGH && buttonPOS3 == true) {     
    buttonPOS3 = false;

    if (enabledled3 == true) {                                      
      digitalWrite(ledPOS3, LOW);                                   
      enabledled3 = false;                                          
    } else {
      digitalWrite(ledPOS3, HIGH);                                  
      enabledled3 = true;                                           
    }
  }

  //Taster Pos4 entprellen LED 4 

  if (digitalRead(tasterPOS4) == LOW) {                              
    buttonPOS4 = true;
    delay(10);                                                     
  }
  if (digitalRead(tasterPOS4) == HIGH && buttonPOS4 == true) {     
    buttonPOS4 = false;

    if (enabledled4 == true) {                                      
      digitalWrite(ledPOS4, LOW);                                  
      enabledled4 = false;                                          
    } else {
      digitalWrite(ledPOS4, HIGH);                                  
      enabledled4 = true;                                           
    }
  }

  //Taster Pos5 entprellen LED 5 

  if (digitalRead(tasterPOS5) == LOW) {                              
    buttonPOS5 = true;
    delay(10);                                                     
  }
  if (digitalRead(tasterPOS5) == HIGH && buttonPOS5 == true) {     
    buttonPOS5 = false;

    if (enabledled5 == true) {                                      
      digitalWrite(ledPOS5, LOW);                                   
      enabledled5 = false;                                          
    } else {
      digitalWrite(ledPOS5, HIGH);                                  
      enabledled5 = true;                                           
    }
  }
  // Ablaufsteuerung-------------------------------------------------------------------------------

  // 1. Wert Beschleunigung
  // 2. Wert Geschwindigkeit max = 1685 Qpps
  // 3. Wert Entschleunigung
  // 4, Wert Position
  // 5. Wert Buffer Der Puffer kann auf 1 oder 0 gesetzt werden. Bei einem Wert von 0 wird der Befehl gepuffert
  //    und in der gesendeten Reihenfolge ausgeführt. Bei einem Wert von 1 wird der aktuell laufende Befehl angehalten,
  //    alle anderen Befehle im Puffer werden gelöscht und der neue Befehl wird ausgeführt.

  if (merker0 == HIGH && buttonPOS1 == HIGH);
  {
    merker1 = HIGH;
    merker0 = LOW;
  }

  do  {

    //Von Startposition 0 auf Schwenkposition 1 - volle Geschwindigkeit
    roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, 11000, 1);

    break;
  }

  while (merker1 == HIGH && buttonPOS2 == HIGH);
  {
    merker2 = HIGH;
    merker1 = LOW;
  }

  do  {

    //Schwenkposition 1 Display schwenken - halbe Geschwindigkeit
    roboclaw.SpeedAccelDeccelPositionM1(address, 200, 842, 200, 15000, 0);

    break;
  }

  while (merker2 == HIGH && buttonPOS3 == HIGH);
  {

    merker3 = HIGH;
    merker2 = LOW;
  }

  do  {

    // Von Schwenkposition 2 auf Kino Position 3 - viertel Geschwindigkeit
    roboclaw.SpeedAccelDeccelPositionM1(address, 200, 421, 200, 20000, 0);
    break;
  }
  while (merker3 == HIGH && buttonPOS4 == HIGH);
  {
    merker4 = HIGH;
    merker3 = LOW;
  }

  do  {

    // Von  Kino Position 3 auf Startposition 0 - volle Geschwindigleit
    roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, 0, 0);

   break;
  }
  while (merker4 == HIGH && buttonPOS5 == HIGH);
  {
    merker0 = HIGH;
    merker4 = LOW;
  }
  exit (0);
}

Im englischen Teil des Forum müssen die Beiträge und Diskussionen in englischer Sprache verfasst werden. Deswegen wurde diese Diskussion in den deutschen Teil des Forums verschoben.

mfg ein Moderator.

Warum schreibst du das so kompliziert? Ersetze
do { x(); break;} while (...); einfach durch
x(); .
Das macht dasselbe.

Servus Michael, danke erstmal für die Rückmeldung.
Ich programmiere erst seit ein paar Tagen, bringe mir das alles selber bei, deshalb wirkt es manchmal kompliziert und umständlich :slight_smile:

Könntest Du mir evtl. das zeigen, wie du es mit x(); meinst ?

Besten Dank

Das break; beendet die do-while Schleife. Die Anweisungen davor werden also einmal ausgeführt, die Bedingung im while() wird nie ausgewertet.

(Ohne das break; wäre es übrigens noch schlimmer: wenn die while-Bedingung einmal erfüllt ist, bleibt sie ewig erfüllt, und das Programm hängt fest)

Grundregel: keine Schleifen innerhalb von loop: loop selbst ist die Schleife, alles andere ist für Menschen zu kompliziert.

Dein Code kann nicht funktionieren.

Du hast Dich verhauen. Bei allen.

Dann mal ne Frage zum Verständnis:
Warum willst Du erst auslösen, wenn Du die Taste loslässt? Es spart viel Code, wenn Du auf das drücken der Taste auslöst.
Die enableLEDs-Merker kannst Du Dir vollständig sparen. Frage einfach den LED-Pin ab.
Das gleiche gilt für buttonPosx.

Mir ist nur noch nicht ganz klar, was da tatsächlich passiert.
Ich meine, das der Ablauf so sein soll:

  • Das Ding steht in Ausgangsstellung
  • Taster 1 wird ausgelöst
    • Das Ding fährt in Stellung 1
  • Wenn das Ding da ankommt, wird Taster 2 ausgelöst
    • Das Ding fährt in Stellung 2
      [..]
      in Stellung 4 angekommen, wird gewartet, das Taster 5 gedrückt wird und das Ding fährt in Ausgangsstellung.

Richtig?

Hallo zusammen, danke für eure Rückmeldungen.

Grundstellung = Position 0 (Inkrement 0)
Drücke Taster 1 - Fahre auf Position 1 (Inkrement 11000)
Drücke Taster 2 - Fahre auf Position 2 (Inkrement 15000)
Drücke Taster 3 - Fahre auf Position 3 (Inkrement 20000)
Drücke Taster 4 - Fahre zurück auf Position 0 (Inkrement 0)

Klar, gibt es noch optimierungsbedarf, vieles ist überflüssig oder zu kompliziert. Wenn Die Grundfunktion erstmal steht, werde ich alles nach und nach optimieren.

Beste Grüße

Danke Michael, und schon lernt man etwas mehr von der Thematik.

Genau das ist das Problem. Der Motor startet ohne den Taster zu betätigen und bleibt an Position 1 stehen.
Wie würdest Du es programmieren?

Gruß

Du bringst dir alles selber bei. Anhand was? Einfach ausprobieren, schauen was passiert, und daraus eine Meinung bilden. Nicht falsch verstehen, mich interessiert einfach wie du vorgegangen bist.

Kennst du dies? https://www.arduinoforum.de/arduino_referenz_down.php

Habe früher viel S5 und S7 programmiert, deshalb bin ich auch auf die Merker gegangen, ein bisschen Grundkenntnisse sind noch da lol.
Bei Basicmicro gibt es eine Bibliothek mit vorgefertigte Sketches, die ich erweitert habe.

Der Rest ist sehr viel lesen, versuchen, verstehen. Teilweise gibt es gute Erklärungen im Internet.

Gruß

Kannst du den Code zeigen, der einwandfrei funktioniert und den du auf 4 Taster erweitern willst?

Das passt nicht. Du hast 5 Taster.

Ich hab mir mal was zusammengereimt:

//Buffered Drive M1 with signed Speed, Accel, Deccel and Position

//Includes required to use Roboclaw library
#include <SoftwareSerial.h>
#include "RoboClaw.h"

//See limitations of Arduino SoftwareSerial
SoftwareSerial serial(10, 11);
RoboClaw roboclaw(&serial, 10000);

#define address 0x80

const byte kreise = 5;
const byte tasterPin[kreise] = {2, 4, 7, 3, 9};
const byte ledPin[kreise] = {8, 13, 12, 5, 6};
byte status = 0;


void setup()
{
  //Open Serial and roboclaw at 38400bps
  Serial.begin(57600);
  roboclaw.begin(38400);
  Serial.println("Starting...");
  for (byte b = 0; b < kreise; b++)
  {
    pinMode( tasterPin[b], INPUT_PULLUP);  // wir definieren den tasterPin als Eingang mit Pull Up
    digitalWrite(ledPin[b], LOW);
    pinMode( ledPin[b], OUTPUT);           // wir definieren den ledPin als Ausgang
  }
}

void loop()
{
  actor();
}
//
void actor()
{
  switch (status)
  {
    case 0:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        //Von Startposition 0 auf Schwenkposition 1 - volle Geschwindigkeit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, 11000, 1);
        status = 1;
      }
      break;
    case 1:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        //Schwenkposition 1 Display schwenken - halbe Geschwindigkeit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 842, 200, 15000, 0);
        status = 2;
      }
      break;
    case 2:
      //Taster Pos3 entprellen LED 3
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        // Von Schwenkposition 2 auf Kino Position 3 - viertel Geschwindigkeit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 421, 200, 20000, 0);
        status = 3;
      }
      break;
    case 3:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        // Von  Kino Position 3 auf Startposition 0 - volle Geschwindigleit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, 0, 0);
        status = 4;
      }
      break;
    case 4:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        status = 0;
      }
      break;
  }
}
//
void setLed(const byte led)
{
  for (byte b = 0; b < kreise; b++)
  { digitalWrite(ledPin[b], LOW); }
  digitalWrite(ledPin[led], HIGH);
}
//
//Display Encoder and Speed for Motor 1
void displayspeed(void)
{
  uint8_t status1, status2;
  bool valid1, valid2;
  int32_t enc1 = roboclaw.ReadEncM1(address, &status1, &valid1);
  int32_t speed1 = roboclaw.ReadSpeedM1(address, &status2, &valid2);
  if (valid1)
  {
    Serial.print("Encoder1:");
    Serial.print(enc1, DEC);
    Serial.print(" ");
    Serial.print(status1, HEX);
    Serial.print(" ");
  }
  if (valid2)
  {
    Serial.print("Speed1:");
    Serial.print(speed1, DEC);
    Serial.print(" ");
  }
  Serial.println();
}

Allerdings habe ich ein Problem mit der lib:

/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp: In member function 'bool RoboClaw::ReadVersion(uint8_t, char*)':
/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp:599:11: warning: comparison is always true due to limited range of data type [-Wtype-limits]
    if(data!=-1){
       ~~~~^~~~
/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp:606:13: warning: comparison is always true due to limited range of data type [-Wtype-limits]
      if(data!=-1){
         ~~~~^~~~
/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp:609:14: warning: comparison is always true due to limited range of data type [-Wtype-limits]
       if(data!=-1){
          ~~~~^~~~
/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp: In member function 'int RoboClaw::read(uint32_t)':
/home/user1/Arduino/libraries/roboclaw_arduino_library-master/RoboClaw.cpp:146:1: warning: control reaches end of non-void function [-Wreturn-type]
 }
 ^

Da hat wer nicht aufgepasst. data ist ein unsigned typ.

1 Like

Vielen lieben Dank :slight_smile:
Taste 5 soll der Wahlschalter Auto/Manuell werden.

Der Sketch funktioniert, du bist der Hammer :+1: :ok_hand:

Muss nochmal den Taster 4 umklemmen, der funktioniert noch nicht, aber so weit war ich auch noch nicht :slight_smile: Besten Dank Leute

Melde mich, wenn alles funktioniert.

Es funktioniert jetzt alles, nochmals vielen vielen Dank.

Ich versuche die Tage noch den Auto/Man Schalter zu integrieren und den Sketch anpassen.

Melde mich bestimmt nochmals :slight_smile:

Euch allen vorab ein schönes Wochenende....

Beste Grüße Ben

Du meinst:
Taster1 gedrückt: Wenn in Position 0, fahre auf Position 1, wenn in einer anderen Position, mache nichts

Servus,
erstmal nochmals vielen Dank für den Sketch, habe ihn mittlerweile verstanden.
Ich hätte noch eine Frage: :slight_smile:

Positionseinstellung Display schwenken.

Wäre es möglich im "Case 1" das Display über diesen Taster (z.B. 5 mal drücken) jeweils um 100 Inkremente (Position + 100) zu schwenken und mit dem nächsten Taster "Case 2" jeweils um -100 Inkremente (Position -100) ?

Ich wünsche Dir vorab ein schönes Wochenende....

Gruß Ben

Welchen der Werte möchtest Du denn jeweils verändern?

        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 842, 200, 15000, 0);

Bedenke, ich hab das Teil nicht... Ich weiss nicht, was da passiert. :wink:

Guten Morgen, danke für Deine Nachricht.

Display fährt in Position 11000 (Case 0)
roboclaw.SpeedAccelDeccelPositionM1(address, 200, 842, 200, "11000", 0);

Durch drücken des Tasters im Case 1 möchte ich (wenn möglich) 5 mal die Position um 100 Inkremente erhöhen.

Taste 1 X gedrückt 11100
Taste 2 X gedrückt 11200 usw.

Im Case 2 Möchte ich dann das Display (mit jedem Tastendruck) um -100 Inkremente zurück
schwenken.

Dann fährt in Case 3 das Display (in dieser Schwenkposition) auf die Kinoposition.

Besten Dank mein lieber....

Na das bekommt man hin...

Versuch mal, ob im case 1 sich die Position so ändert, wie Du willst:

//Buffered Drive M1 with signed Speed, Accel, Deccel and Position

//Includes required to use Roboclaw library
#include <SoftwareSerial.h>
#include "RoboClaw.h"

//See limitations of Arduino SoftwareSerial
SoftwareSerial serial(10, 11);
RoboClaw roboclaw(&serial, 10000);

#define address 0x80

const byte kreise = 5;
const byte tasterPin[kreise] = {2, 4, 7, 3, 9};
const byte ledPin[kreise] = {8, 13, 12, 5, 6};
byte status = 0;


void setup()
{
  //Open Serial and roboclaw at 38400bps
  Serial.begin(57600);
  roboclaw.begin(38400);
  Serial.println("Starting...");
  for (byte b = 0; b < kreise; b++)
  {
    pinMode( tasterPin[b], INPUT_PULLUP);  // wir definieren den tasterPin als Eingang mit Pull Up
    digitalWrite(ledPin[b], LOW);
    pinMode( ledPin[b], OUTPUT);           // wir definieren den ledPin als Ausgang
  }
}

void loop()
{
  actor();
}
//
void actor()
{
  static bool tasteGedrueckt = false;
  static byte zaehler = 0;
  unsigned long lastmillis = 0;
  const unsigned long bounceTime = 40;
  const unsigned long schwenkPosition = 11000;
  const unsigned int addSchwenk = 500;
  switch (status)
  {
    case 0:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        //Von Startposition 0 auf Schwenkposition 1 - volle Geschwindigkeit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, schwenkPosition, 1);
        zaehler = 0;
        tasteGedrueckt = false;
        status = 1;
      }
      break;
    case 1:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        if (tasteGedrueckt == false)
        {
          tasteGedrueckt = true;
          lastmillis = millis();
          zaehler++;
          //Schwenkposition 1 Display schwenken - halbe Geschwindigkeit
          roboclaw.SpeedAccelDeccelPositionM1(address, 200, 842, 200, schwenkPosition + zaehler * addSchwenk, 0);
          if (zaehler == 5)
          {
            zaehler = 0;
            tasteGedrueckt = false;
            status = 2;
          }
        }
      }
      else if (millis() - lastmillis >= bounceTime)
      { tasteGedrueckt = false; }
      break;
    case 2:
      //Taster Pos3 entprellen LED 3
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        // Von Schwenkposition 2 auf Kino Position 3 - viertel Geschwindigkeit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 421, 200, 20000, 0);
        status = 3;
      }
      break;
    case 3:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        // Von  Kino Position 3 auf Startposition 0 - volle Geschwindigleit
        roboclaw.SpeedAccelDeccelPositionM1(address, 200, 1685, 200, 0, 0);
        status = 4;
      }
      break;
    case 4:
      if (digitalRead(tasterPin[status]) == LOW)
      {
        setLed(status);
        status = 0;
      }
      break;
  }
}
//
void setLed(const byte led)
{
  for (byte b = 0; b < kreise; b++)
  { digitalWrite(ledPin[b], LOW); }
  digitalWrite(ledPin[led], HIGH);
}
//
//Display Encoder and Speed for Motor 1
void displayspeed(void)
{
  uint8_t status1, status2;
  bool valid1, valid2;
  int32_t enc1 = roboclaw.ReadEncM1(address, &status1, &valid1);
  int32_t speed1 = roboclaw.ReadSpeedM1(address, &status2, &valid2);
  if (valid1)
  {
    Serial.print("Encoder1:");
    Serial.print(enc1, DEC);
    Serial.print(" ");
    Serial.print(status1, HEX);
    Serial.print(" ");
  }
  if (valid2)
  {
    Serial.print("Speed1:");
    Serial.print(speed1, DEC);
    Serial.print(" ");
  }
  Serial.println();
}

Im case 2: fängst Du mit 20000 an - Du hast derzeit 11000 aus case 0: und 5*500 = 2500 aus case 1 dazu = 13500...
Muss das noch angepasst werden?