3Phasen Schrittmotor mit Hall

Hallo,

und zwar muss ich einen 3 Phasen Schrittmotor mit Hall Sensoren ansteuern. Dies funktioniert soweit. Nur habe ich das Problem das der Motor manchmal unrund läuft und ich weiß nicht woran dies liegen könnte.

Wollte das Programm hochladen geht aber nicht da ich ein neuer Benutzer bin.

Daten: Arduino Mega 2560, 2x L298N, 12V netzteil,
Motor: DB41S024030-A

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.

Wenn wir hellsehen könnten könnten wir Dir Antworten.

Ohne Schaltplan und Sketch können wir nur sagen daß es ein Fehler im Sketch oder Schaltplan sein wird.
Grüße Uwe

Die Pins 50 bis 54 sind für SPI gedacht, da würde ich für Hall andere Pins nutzen, es gibt ja noch ein paar freie. Das gilt auch für 18 und 19. Nur eine Empfehlung :slightly_smiling_face:

Am rechten Treiber fehlen laut Schaltbild die 5V Versorgung.
OUT3 müßte vechts vorne sein nicht rechts hinten.

Wieso benutzt Du 2 L298?

Grüße Uwe

Am linken L298 habe ich nur 5V abgezweigt damit ich den arduino ohne pc nur über das Netzteil laufen lassen kann.

Dieser eine OUT ist nur falsch gezeichnet ist aber an OUT 3 angeschlossen😅

Du meinst ich soll lieber PIN 22 - 27 benutzen?

Das ist falsch.
Der L298 hat 4 Halbbrücken. Du brauchst für den 3-Phasenmotor 3 Halbbrücken. Jede Halbbrücke hat einen eigenen Eingang. Enable ist immer für 2 Halbbrücken.
Grüße Uwe

Da man die 3 Phasen getrennt schalten muss und mit einem L298N könnte man auf der Seite wo die 2 Phasen angeschlossen sind immer nur beide zusammen ein und ausschalten.

Es stimmt daß man immer nur 2 Ausgänge abschalten kann (Enable).
Braucht man das aber? Wie ist dei Sequenz mit der man die Ausgänge schaltet?

Grüße Uwe

Ja, dann bleiben die mit spezieller Hardware verbundenen Pins frei, so Du diese mal brauchen solltest.

Achso nein ich brauche dies nur für dieses Projekt.
Mehr Anschlüsse brauche ich erstmal nicht.

Ok wel man die Ausgänge Hochohmig schalten muß braucht es 2 L298.
Grüße Uwe

Setze Deinen Sketch bitte in Codetags. Wie das geht, steht hier.
Außerdem formatiere den Code bitte ordentlich. Strg+T in der IDE hilft Dir dabei.
Das kannst Du auch noch nachträglich ändern.

Gruß Tommy

#define MIT_PID 1
//ohne Regelung - >  die Zeile die beiden // entfernen
//#undef MI_TPID
 

#include "LiquidCrystal_I2C.h"
#include "TEST__.h"
#include "PID.h"
 
// PID Klasse initialisieren
PID pid = PID();
 
// Rotary Encoder Anschlüsse
//   pin CLK muss ein interruptfähiger Pin sein
//   pin SW muss ein interruptfähiger Pin sein
#define DT_Pot 19
#define CLK_Pot 18
#define SW_Pot 2
 
// Rotary - Voreinstellungen default Werte
volatile uint8_t lastvalueCLK;
 
// Motor  Pin's ENA ENB ENA
#define P1A 10
#define P2A 5
#define P3A 6
 
int p1a = P1A;
int p2a = P2A;
int p3a = P3A;
 
// L298N Motorsteuerung    - IN1  IN3  IN1
#define P11 7
#define P21 9
#define P31 3
 
int p11 = P11;
int p21 = P21;
int p31 = P31;
 
// Hallsensoren  Blau, Weiß und Grün
#define MHB 50
#define MHW 51
#define MHG 52
 
int mhb = MHB;
int mhw = MHW;
int mhg = MHG;
 
#define K_SPEED 55
volatile int istSpeed = K_SPEED;
volatile int sollSpeed = K_SPEED;
bool motorStoped = false;  // läuft der Motor ?
int lastSpeed = K_SPEED - 3;
int lastSollSpeed = K_SPEED - 3;
bool motorVor = true;  // Drehrichtung true - vor   false - zurück
 
bool takt1 = false, takt2 = false;  // Berechnung der Umdrehungen
unsigned int takt = 0;
unsigned long t1Drehzahl = 0;
unsigned long umdrehung = 0;
int sollUmin = 0;
int istUmin = 0;
int lastistUmin = -1;
volatile bool sollSpeedChanged = false;
 

LiquidCrystal_I2C lcd(0x27, 16, 2);  // lcd initialisieren -  Adressezuweisen
 
/*
   setup für das LCD Display
*/
void setupDisplay() {
  lcd.init();  // initialize the lcd
  lcd.clear();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print(" IST-U/min: ");
  lcd.setCursor(0, 1);
  lcd.print("SOLL-U/min: ");
}
/*
   auf dem LCD Display die Drehzahl ausdrucken
*/
void showDrehzahl() {
  char s1[8];
  if (lastSpeed != istSpeed || lastistUmin != istUmin) {
    if (motorStoped == true)
      sprintf(s1, "%5d", 0);
    else {
      lastSpeed = istSpeed;
      lastistUmin = istUmin;
      sprintf(s1, "%5d", istUmin);
    }
    lcd.setCursor(11, 0);
    lcd.print(s1);
  }
  if (sollSpeedChanged) {
    sollSpeedChanged = false;
    lcd.setCursor(11, 1);
    sprintf(s1, "%5d", sollUmin);
    lcd.print(s1);
  }
}
/*
   Setup der 2 L298N Motorsteuerungsbausteine
*/
void setupBridges() {
  pinMode(mhb, INPUT_PULLUP);
  pinMode(mhw, INPUT_PULLUP);
  pinMode(mhg, INPUT_PULLUP);
 
  Serial.begin(115200);
  pinMode(p11, OUTPUT);
  pinMode(p21, OUTPUT);
  pinMode(p31, OUTPUT);
 
  pinMode(p1a, OUTPUT);
  pinMode(p2a, OUTPUT);
  pinMode(p3a, OUTPUT);
  digitalWrite(p1a, HIGH);
  digitalWrite(p2a, LOW);
  digitalWrite(p3a, LOW);
 
  digitalWrite(p11, LOW);
  digitalWrite(p21, LOW);
  digitalWrite(p31, LOW);
 

  TCCR1A = 0b10100010;  // Configure TCCR1A for PWM on Pin 9
  TCCR1B = 0b00011001;  // Configure TCCR1B for PWM on Pin 9
  OCR1A = 32768;          // Set the compare value for Channel A
  OCR1B = 32768;          // Set the compare value for Channel A
  OCR1C = 32768;          // Set the compare value for Channel A
 
  // Drehrichtung des Motors
  motorVor = true;
}
 
/* Setup für den Rotary Encoder
     Pinmode
     Interrupt Funktion zuweisen
*/
void setupRotary() {
  pinMode(CLK_Pot, INPUT);
  pinMode(DT_Pot, INPUT);
  pinMode(SW_Pot, INPUT_PULLUP);
 
  attachInterrupt(digitalPinToInterrupt(CLK_Pot), interruptDT, CHANGE);
  attachInterrupt(digitalPinToInterrupt(SW_Pot), interruptSW, CHANGE);
  lastvalueCLK = digitalRead(CLK_Pot);
}
 
/*
   Motor ausschalten
*/
void motorAus() {
  motorStoped = true;
  lastSpeed = 0;
  t1Drehzahl = 0;
 
  digitalWrite(p1a, LOW);
  digitalWrite(p2a, LOW);
  digitalWrite(p3a, LOW);
  digitalWrite(p11, LOW);
  digitalWrite(p21, LOW);
  digitalWrite(p31, LOW);
}
/*
   Motor einschalten
*/
void motorEin() {
  // Motor starten
  motorStoped = false;
 
  takt1 = false;
  takt2 = false;
  t1Drehzahl = 0;
  umdrehung = 0;
#ifdef MIT_PID
  pid.resetN();
#endif
}
/* Interrupt Funktion, die bei einem Interrupt ausgeführt wird
       auslösen des Interrupt -> drehen am KY-040 Rotary Encoder - Änderung des Wertes am Pin DT_Pot
       -> dient zur Steuerung
*/
void interruptDT() {
  noInterrupts();
  uint8_t valueCLK = digitalRead(CLK_Pot);
  if (valueCLK != lastvalueCLK) {
    long sp = abs(sollSpeed);
 
    if (!motorVor)
      sp = -sp;
 
    if (digitalRead(DT_Pot) != valueCLK)
      sp--;
    else
      sp++;
 
    istSpeed = constrain(abs(sp), 0, 255);
 
    if (motorStoped && istSpeed >= 50) {
      motorStoped = false;
      istSpeed = K_SPEED;
    }
    else if (istSpeed < 50 && istSpeed > 35)
    {
      if (!motorStoped) {
        motorAus();
        istSpeed = 35;
        sollUmin = 0;
      }
    }
    else if (istSpeed < 20)
    {
      motorVor = !motorVor;
      motorEin();
      istSpeed = K_SPEED;
      sollUmin = 0;
    }
    sollSpeed = istSpeed;
  }
  lastvalueCLK = valueCLK;
  interrupts();
}
/* Interupt Funktion, die bei einem Interrupt ausgeführt wird
      auslösen des Interrupt -> Clicken am KY-040 Rotary Encoder - Änderung des Wertes am Pin SW_Pot
 
   schaltet den Motor aus oder ein
*/
void interruptSW() {
  int valueSW = digitalRead(SW_Pot);
 
  if (valueSW) {
    if (motorStoped == true) {
      // Motor starten
      motorEin();
    } else {
      // Motor stopen
      motorAus();
    }
  }
}
/*
   setup routinedes Arduinos
     hier werden die verschiedenen Baustein initialisiert
*/
void setup() {
  Serial.begin(115200);
  setupRotary();
  setupBridges();
  setupDisplay();
#ifdef MIT_PID
  pid.setDefaultK(1.0, 0.4, 0.5);
#endif
}
/*
   wartet bis der nächste HAll Schritt erreicht ist
*/
void waitNextStep(int h1, int h2, int h3) {
  while (h1 == digitalRead(mhb) && h2 == digitalRead(mhw) && h3 == digitalRead(mhg))
    ;
}
 
#ifdef __TEST
/*
   ist nur zu testzwecken aktiv
       - kann in der Datei  Test__.h aktiviert/deaktiviert werden
*/
void printSchritt(int step, int h1, int h2, int h3) {
  int ta = 8;
  // Hallsensoren lesen
  if (h1 == 1)  // H1
    ta += 4;
  if (h2 == 1)  // H2
    ta += 2;
  if (h3 == 1)  // H3
    ta += 1;
 
  Serial.print("Schritt ");
  Serial.print(step);
  Serial.print("  takt =  ");
  Serial.print(ta);
  Serial.print("   Hall 1 2 3: ");
  Serial.print(h1);
  Serial.print(h2);
  Serial.println(h3);
}
#endif
/*
   ermittelt die aktuelle Drehzahl
*/
void countDrehzahl() {
  unsigned long t2;
  if (t1Drehzahl == 0)
  {
    t1Drehzahl = millis();
    t2 = t1Drehzahl + 1000;
    umdrehung = 0;
  }
 
  // takt: 2, 3, 1, 5, 4, 6       - Vorwärts
  // takt: 12, 13, 9, 11, 10, 14  - Rückwärts
 
  switch (takt) {
    case 1:
    case 9:
      takt1 = true;
      break;
 
    case 2:
    case 12:
      takt2 = true;
      break;
 
    default: return;
  }
 
  if (takt1 == false || takt2 == false)
    return;
 
  takt1 = false;
  takt2 = false;
  umdrehung++;
 
#define UMDREH 100
 
  if (umdrehung == UMDREH || millis() > t2) {
    float t;
 
    // 1 Umdrehung hat 5 * 6 Phasen
    umdrehung /= 5;
 
    t = ((millis() - t1Drehzahl) / 1000.0);
    t = round((float(umdrehung) / t) * 6) * 10.0;
    istUmin = int(t);
    takt1 = false;
    takt2 = false;
    t1Drehzahl = 0;
    umdrehung = 0;
 
    if (lastSollSpeed != sollSpeed) {
#ifdef MIT_PID
      pid.resetN();
#endif
      if (istUmin < 350)
        return;
 
      sollSpeedChanged = true;
      lastSollSpeed = sollSpeed;
      sollUmin = istUmin;
    }
 
#ifdef MIT_PID
    istSpeed = pid.getNewSpeed(istSpeed, sollUmin, istUmin);
#endif
  }
}



/*
   die Hauptfunktion des Programmes
     hier wird das Drehen des Motors gesteuert
*/
void motorDreht(void) {
  // Ermittlung des Taktes der ausgeführt wird
  //   Anfangswert - takt = 0 -> im Uhrzeigersinn rechts Lauf
  //                 takt = 8 -> im Uhrzeigersinn links Lauf
  if (motorVor)
    takt = 0;
  else
    takt = 8;
 
  // Hallsensoren lesen
  int h1 = digitalRead(mhb);
  int h2 = digitalRead(mhw);
  int h3 = digitalRead(mhg);
 
  // Werte in die Variable takt schreiben
  if (h1 == 1)  // H1
    takt += 4;
  if (h2 == 1)  // H2
    takt += 2;
  if (h3 == 1)  // H3
    takt += 1;
 
  // takt: < 8    - Vorwärts
  // takt: > 8    - Rückwärts
 
  switch (takt) {
    case 5:  // Schritt 4    Sensor (CBA) 010    vor
    case 12: // Schritt 1    Sensor (CBA) 101    zurück
 
#ifdef __TEST
      if (takt == 5)
        printSchritt(4, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(1, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
 
      analogWrite(p21, istSpeed);
      digitalWrite(p11, LOW);
      digitalWrite(p31, LOW);
 
      digitalWrite(p1a, HIGH);
      digitalWrite(p2a, HIGH);
      digitalWrite(p3a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p21, LOW);
      digitalWrite(p1a, LOW);
      digitalWrite(p2a, LOW);
      break;
 
    case 1:  // Schritt 3    Sensor (CBA) 110    vor
    case 13: // Schritt 6    Sensor (CBA) 001    zurück
 
#ifdef __TEST
      if (takt == 1)
        printSchritt(3, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(6, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
      analogWrite(p31, istSpeed);
      digitalWrite(p11, LOW);
      digitalWrite(p21, LOW);
 
      digitalWrite(p3a, HIGH);
      digitalWrite(p1a, HIGH);
      digitalWrite(p2a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p31, LOW);
      digitalWrite(p3a, LOW);
      digitalWrite(p1a, LOW);
      break;
 
    case 3: // Schritt 2    Sensor (CBA) 100    vor
    case 9: // Schritt 5    Sensor (CBA) 011    zurück
 
#ifdef __TEST
      if (takt == 3)
        printSchritt(2, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(5, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
 
      analogWrite(p31, istSpeed);
      digitalWrite(p11, LOW);
      digitalWrite(p21, LOW);
 
      digitalWrite(p3a, HIGH);
      digitalWrite(p2a, HIGH);
      digitalWrite(p1a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p31, LOW);
      digitalWrite(p3a, LOW);
      digitalWrite(p2a, LOW);
      break;
 
    case 2:  // Schritt 1    Sensor (CBA) 101    vor
    case 11: // Schritt 4    Sensor (CBA) 010    zurück
 
#ifdef __TEST
      if (takt == 2)
        printSchritt(1, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(4, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
 
      analogWrite(p11, istSpeed);
      digitalWrite(p21, LOW);
      digitalWrite(p31, LOW);
 
      digitalWrite(p1a, HIGH);
      digitalWrite(p2a, HIGH);
      digitalWrite(p3a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p11, LOW);
      digitalWrite(p1a, LOW);
      digitalWrite(p2a, LOW);
      break;
 
    case 6:  // Schritt 6    Sensor (CBA) 001    vor
    case 10: // Schritt 3    Sensor (CBA) 110    zurück
 
#ifdef __TEST
      if (takt == 6)
        printSchritt(6, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(3, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
 
      analogWrite(p11, istSpeed);
      digitalWrite(p21, LOW);
      digitalWrite(p31, LOW);
 
      digitalWrite(p1a, HIGH);
      digitalWrite(p3a, HIGH);
      digitalWrite(p2a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p11, LOW);
      digitalWrite(p1a, LOW);
      digitalWrite(p3a, LOW);
      break;
 
    case 4:  // Schritt 5    Sensor (CBA) 011    vor
    case 14: // Schritt 2    Sensor (CBA) 100    zurück
 
#ifdef __TEST
      if (takt == 4)
        printSchritt(5, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
      else
        printSchritt(2, digitalRead(mhb), digitalRead(mhw), digitalRead(mhg));
#endif
 
      analogWrite(p21, istSpeed);
      digitalWrite(p11, LOW);
      digitalWrite(p31, LOW);
 
      digitalWrite(p2a, HIGH);
      digitalWrite(p3a, HIGH);
      digitalWrite(p1a, LOW);
 
      waitNextStep(h1, h2, h3);
      digitalWrite(p21, LOW);
      digitalWrite(p2a, LOW);
      digitalWrite(p3a, LOW);
      break;
  }
}
 
/*
   Hauptloop - hier wird die Arbeit gemacht
     - Drehzahl anzeigen
     - Moto steuern
     - Drehzahl ermitteln
*/
void loop() {
  //    Serial.print(" sollSpeed = ");
  //    Serial.print(sollSpeed);
  //    Serial.print(" motorStoped = ");
  //    Serial.print(motorStoped);
  //    Serial.print("  motorVor = ");
  //    Serial.println(motorVor);
 
  showDrehzahl();
  if (!motorStoped) {
    motorDreht();
    countDrehzahl();
  }
}

Man kanns auch unnötig kompliziert machen.

Benutze 8 bit Variablen wo es keine größeren braucht. Dadurch wird der Sketch schneller und braucht weniger Speicher.

Grüße Uwe

Okay danke.

Mach ich es richtig das PIN 7,9 und 3 mit 31khz Fast PWM angesteuert werden?

Mit freundlichen Grüßen

Hallo,

du musst jetzt ganz stark sein.

Du fragtest u.a. nach dem Timer. Ist mein Liebling deswegen gleich angeschaut. Das man die Register erstmal löschen muss, weil sonst eine falsche Konfiguration "enstehen" kann, kannst du nicht wissen. Also immer alle wichtigen Timerregister erstmal löschen wenn das Arduino Framework verwendet wird. Sonst kann es lustige bzw. unlustige Effekte geben. Denn die sind voreingestellt.
Ich empfehle zuerst TCCRnB zu löschen, damit steht der Timer erstmal zwangsweise.
Daanch TCCRnA löschen. Dann sollte man pauschal noch TIMSKn löschen.
Dann ist man erstmal auf der sicheren Seite bevor man den Timer selbst konfiguriert.
Desweiteren empfehle ich die Prescaler Bits erst zum Schluss einzuschalten. Sonst taktet womöglich der Timer mit einer noch unvollständigen Konfiguration los.

Jetzt zu deiner Konfig. Habe ich einmal übersetzt.

// Fast PWM Mode 14  
TCCR1B = 0;
OCR1A = 32768;          // Set the compare value 
OCR1B = 32768;          // 
OCR1C = 32768;          // 
ICR1 = ???
TCCR1A = _BV(COM1A1) | _BV(COM1B1) | _BV(WGM11);  // Configure TCCR1A for PWM on Pin 9 
TCCR1B = _BV(WGM13)  | _BV(WGM12)  | _BV(CS10);   // Configure TCCR1B for PWM on Pin 9

Ich sehe in deinem Programm nicht das du die Timer 1 Hardwarepins 11, 12 und 13 (OC1A, OC1B und OC1C) verwendest. Der Kommentar Pin 9 kann so nicht stimmen. Zudem für Pin 13 die COM Bit Konfiguration fehlt. Zusammen mit der Eingangserklärung wird der Timer irgendwas machen. Leider nicht das Gewünschte. Die TOP Wert Konfiguration für ICR1 fehlt auch. Muss größer gleich den Compare Werten entsprechen. Genauer gesagt muss man das umgekehrt betrachten. Die Compare Werte nicht größer werden wie TOP, weil TOP muss man festlegen. Die Frequenz wird mit der Formel im Manual berechnet Kapitel 17.9.3. Ist für jeden Modus anders!

Wenn der Timer den Motor steuern soll, muss man die Frequenz steuern. Von 0 auf 100 kann kein Motor. Soll der Timer den Motor steuern? Was soll der Timer machen?
Eine pauschale Timer 1 Anleitung. Arduin Timer0/Timer1 - #5 by Doc_Arduino
Was machen die Hallsensoren? Ist das überhaupt ein Schrittmotor? Oder ein Servomotor? Laut deiner Typangabe findet man einen BLDC-Motor. Sollst du eine Steuerung entwickeln?

Was mir auch aufgefallen ist das Haufenweise Copy Paste an jeder Ecke. Das führt zu Kaos und alles ist kaum lesbar. Bsp. Serial.begin ist doppelt vorhanden.

Mit dem Taster am Interrupt Pin ist auch ungünstig. Du liest im Interrupt (interruptSW ISR) dennoch per digitalRead den Pin aus. Dann benötigt man auch keinen Interrupt.

Ähnliches für den Encoder. Kann man mit Interrupt machen, muss man eher nicht. Was aber nicht gut ist, die gesamte Abarbeitung in die ISR zu werfen. Und manuell Interrupt aus/einschalten macht man in der ISR auch nicht.

Ehrlich gesagt ist das nur alles wild zusammengeschustert. Am besten du fängst nochmal komplett von vorn an. Doppelt vorhandene Datensätze wie zum Bsp. für die beiden H-Brücken würde ich gleich mit einer Struktur erschlagen. Thema 'struct' lesen. Dann fällt die gesamte Dopplung und Benennung weg. Die ganzen Defines gefallen mir auch nicht. switch case ohne break? Muss das so sein? Muss mindestens kommentiert werden.

Du solltest dich neben struct auch unbedingt mit Array befassen. Sonst endet das wie man sieht im Kaos. Ich helfe dir mal auf die Sprünge. Eine Demo wie man das machen könnte.

Das wäre schon eine Klasse mit struct, mit Konstruktor, weil unterschiedliche Parameter übergeben werden müssen.

struct Bridge
{
  // Elemente
  const uint8_t pinIN1;
  const uint8_t pinIN2;
    
  // Konstruktor 
  Bridge (uint8_t p1, uint8_t p2) :
  // Initialisierungsliste
    pinIN1 {p1},
    pinIN2 {p2}
  {}

  // Elementfunktionen
  void init(void)
  {
    pinMode(pinIN1, OUTPUT);
    pinMode(pinIN2, OUTPUT);
  }

  void setIN1 (const bool state) { digitalWrite(pinIN1, state); }
  void setIN2 (const bool state) { digitalWrite(pinIN2, state); }
};

Angewendet zum Objekte erstellen kann man das so

/*               Pin IN1      
                 |   Pin IN2  
                 |   |    */
Bridge bruecke1 (2, 3);
Bridge bruecke2 (4, 5);

Oder als Array so

Bridge bruecke [] = {
/* Pin IN1      
   |   Pin IN2  
   |   |    */
  {2, 3},
  {4, 5}
};

Die Elementfunktionen entweder einzeln mit Objektnamen angewandt

bruecke1.init();
bruecke2.init();
bruecke1.setIN1(LOW);
bruecke2.setIN1(LOW);
bruecke1.setIN2(LOW);
bruecke2.setIN2(LOW);

Oder mittels Array einfach über alle iterieren

for (auto &b : bruecke) {
    b.init();
    b.setIN1(LOW);
    b.setIN2(LOW);
}
Demo Klasse
struct Bridge
{
  // Elemente
  const uint8_t pinIN1;
  const uint8_t pinIN2;
    
  // Konstruktor 
  Bridge (uint8_t p1, uint8_t p2) :
  // Initialisierungsliste
    pinIN1 {p1},
    pinIN2 {p2}
  {}

  // Elementfunktionen
  void init(void)
  {
    pinMode(pinIN1, OUTPUT);
    pinMode(pinIN2, OUTPUT);
  }

  void setIN1 (const bool state)
  {
    digitalWrite(pinIN1, state);
  }

  void setIN2 (const bool state)
  {
    digitalWrite(pinIN2, state);
  }
};

// Entweder
/*               Pin IN1      
                 |   Pin IN2  
                 |   |    */
Bridge bruecke1 (2, 3);
Bridge bruecke2 (4, 5);

// ODER
Bridge bruecke [] =
{
/* Pin IN1      
   |   Pin IN2  
   |   |    */
  {2, 3},
  {4, 5}
};

void setup (void)
{
  Serial.begin(9600);
  Serial.println("\nuC Reset ###");

  // Entweder
  bruecke1.init();
  bruecke2.init();
  bruecke1.setIN1(LOW);
  bruecke2.setIN1(LOW);
  bruecke1.setIN2(LOW);
  bruecke2.setIN2(LOW);

  // ODER
  for (auto &b : bruecke)
  {
    b.init();
    b.setIN1(LOW);
    b.setIN2(LOW);
  }
}

void loop (void)
{ }

Du siehst hoffentlich den Vorteil vom Array wenn man gleiche Objekte damit erschlagen lassen kann. LOW, HIGH kann man für das laufende Programm mit Variablen ersetzen die man passend ändert und dann in einem Rutsch an alle Brücken ausgibt, sozusagen ein Update macht. Aber egal ob du das verwendest oder nicht. Deinen Sketch aufräumen musst du so oder so.

1 Like

Schön erklärt, grüße bitte den Bergsteiger :slightly_smiling_face:

Ich wollte dir Pins 7,9 und 3 mit 31khz ansteuern lassen damit der Motor flüssiger läuft. Der Motor wird über die Spannung geregelt. Je mehr Spannung desto schneller läuft er.

Wenn die Pins mit 31khz angesteuert werden bekomme ich ein sauberes signal.
Die Pins sollen dauerhaft mit 31khz laufen.