Mehrere multiple button states

Liebes Forum,

ich bin noch recht neu in der Arduinowelt, weshalb ich um etwas Nachsicht bitte.

Basierend auf diesem Tutorial (Creating multiple button states with Arduino - Arduino Platform) wollte ich weitere 3 LEDs mit einem weiteren Button steuern. Einfach 3 LEDs mit einem Button bekomme ich. Nach dem selben Strickmuster wollte ich eben noch 3 weitere LEDs mit einem weiteren Button steuern.

Die Schaltung habe ich schon hinbekommen (einfach die 3 LEDs an weitere PINs angeschlossen) und den Code angepasst - dachte ich. Wenn ich den Button für die ersten 3 LEDs drücke reagieren praktisch für beide LED-Reihen die LEDs simulatan; soll heißen: drücke ich den Button leuchten beide grüne LEDs, beim zweiten drücken beide gelbe und beim drücken beide rote. Ich möchte jedoch den ersten Satz LED mit Button 1 und den zweiten Satz LED mit Button 2 steuern.

Ich werde hier noch wahnsinnig. Wo liegt der Fehler? Kann das jemand erklären oder mir erläutern, wo der Fehler liegt?

Anbei noch der Code:

//  Sketch: Multiple states of the button
// Define the pins being used


int pinLEDBtn01[ ] = {13,12,11};
int pinLEDBtn02[] = {10,9,8};
int ButtonPins[] = {2,3};
int ButtonStates[] = {0,0,0};
//int Button01 = 2;
//int Button02 = 3;
int i;
int j;


// variables to hold the new and old switch states
boolean oldSwitchState = LOW;
boolean newSwitchState = LOW;
byte state = 0;


void setup()
{
  Serial.begin(9600);
  
    for (int i = 0; i < sizeof(pinLEDBtn01); i++){
      pinMode(pinLEDBtn01[i],OUTPUT); digitalWrite( pinLEDBtn01[i], LOW); 
      
    for (int j = 0; j < sizeof(ButtonPins); j++){
      pinMode(ButtonPins[i],INPUT);
  
  
  
//  for(int i = 0; i < 3; i++){
//    pinMode( pinLEDBtn01[i],OUTPUT); digitalWrite( pinLEDBtn01[i], LOW); 
//    pinMode( pinLEDBtn02[i],OUTPUT); digitalWrite( pinLEDBtn02[i], LOW);
  
//    pinMode(Button01, INPUT);
//    pinMode(Button02, INPUT);
  }
  }
}


void loop()
{
  newSwitchState = digitalRead(ButtonPins[i]);
  if ( newSwitchState != oldSwitchState )
  {
    // has the button switch been closed?
    if ( newSwitchState == HIGH )
    {
      // increase the value of state
      state++;
      if (state > 3) {
        state = 0;
      }
      
    for (int i = 0; i < 3; i++){
    if (digitalRead(ButtonPins[i])==HIGH) ButtonStates[i]=1;
    else ButtonStates[i]=0;
    }
      
    for (int i = 0; i < 3; i++){
    if (ButtonStates[i] == 1) digitalWrite(pinLEDBtn01[i],HIGH);
    else digitalWrite(pinLEDBtn01[i],LOW);
  }
      
      
      
      // turn all LEDs off. Doing it this way means we do not need to care about the individual LEDs
      // simply turn them all off and then turn on the correct one.
      digitalWrite(pinLEDBtn01[0], LOW);
      digitalWrite(pinLEDBtn01[1], LOW);
      digitalWrite(pinLEDBtn01[2], LOW);
      
      digitalWrite(pinLEDBtn02[0], LOW);
      digitalWrite(pinLEDBtn02[1], LOW);
      digitalWrite(pinLEDBtn02[2], LOW);

      // Turn on the next LED
      // Because the value of state does not change while we are testing it we don't need to use else if
      if (state == 1) {
        digitalWrite(pinLEDBtn01[0], HIGH);
      }
      if (state == 2) {
        digitalWrite(pinLEDBtn01[1], HIGH);
      }
      if (state == 3) {
        digitalWrite(pinLEDBtn01[2], HIGH);
      }
      if (state == 1) {
        digitalWrite(pinLEDBtn02[0], HIGH);
      }
      if (state == 2) {
        digitalWrite(pinLEDBtn02[1], HIGH);
      }
      if (state == 3) {
        digitalWrite(pinLEDBtn02[2], HIGH);
      }
    }
    oldSwitchState = newSwitchState;
  }
}

Danke!

[EDIT] Sketch in Code Tags verfrachtet. Uwe[EDIT]

Hallo,

Dein Sketch ist so schlecht lesbar,

ich hab jetzt nur mal kurz reingesehen. Das Original beruht ja darauf das mit jedem Tastendruck ein Zähler hoch gezählt wird. Kommt er bei 4 an wir er wieder auf 0 gesetzt. Je nach Zählerstand werden dann 0,1,2,3 Leds eingeschaltete.
Wenn Du das zweimal haben willst benötigst Du zwei Zähler. In Deinem Sketch finde ich aber zumindest bei der Abfrage für die LED´s nur eine Variable "State"
Bau Dir ein paar Serial.print ein damit Du den Ablauf und Zustand verfolgen kannst. Mach die eine Funktion für den ersten Button und die ersten 3 LEDs´dann kannst Du das erst mal leicht in eine zweite Funktion für den 2 Button mit den 3 weiteren LES´s kopieren. So wird das dann alles übersichtlicher

Heinz

Schließe Dein Programm bitte in code-Tags ein, damit das Programm richtig dargestellt wird.

Verwenden Sie die </> Taste oder mit drei "backslash-single-quotes".

```
Dein Programm
```

UNGETESTET!
Er kompiliert - Ich bin gleich zum Aussteigen gezwungen. Mehr ging in der Kürze der Zeit nicht.

Wenn Du multiple Button willst, dann musst Du auch multiple states merken.
Ich hab das mal nach meinem Gusto versucht runterzukürzen.
Nachher hab ich Hardware, dann lass ich den mal laufen.

// basiert auf: https://forum.arduino.cc/t/mehrere-multiple-button-states/862875
// Dieser Sketch ist ohne Test - er kompiliert fehlerfrei und ohne Warnungen.

// Sketch: Multiple states of the button
// Define the pins being used
const uint8_t pinButton[2] = {2, 3};
const uint8_t pinLED[sizeof(pinButton)][3] = {{13, 12, 11}, {10, 9, 8}} ;

uint8_t ButtonStates[sizeof(pinButton)][3] = {{0, 0, 0}, {0, 0, 0}};

// variables to hold the new and old switch states
boolean oldSwitchState[sizeof(pinButton)] = {LOW, LOW};
boolean newSwitchState[sizeof(pinButton)] = {LOW, LOW};
uint8_t state[sizeof(pinButton)] = {0, 0};

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < 3; j++)
    {
      pinMode(pinLED[i][j], OUTPUT); digitalWrite(pinLED[i][j], LOW);
    }
  }
  for (uint8_t  i = 0; i < sizeof(pinButton); i++)
  {
    pinMode(pinButton[i], INPUT);
  }
}


void loop()
{
  // Taster Abfrage
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    newSwitchState[i] = digitalRead(pinButton[i]);
    if (newSwitchState[i] != oldSwitchState[i])
    {
      // has the button switch been closed?
      if (newSwitchState[i] == HIGH)
      {
        // increase the value of state
        state[i]++;
        if (state[i] > 3) {
          state[i] = 0;
        }
      }
      oldSwitchState[i] = newSwitchState[i];
    }
  }
  
  // LED Ausgabe
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < sizeof(pinLED[i]); j++)
    {
      digitalWrite(pinLED[i][j], LOW);
      if (state[i]==j) digitalWrite(pinLED[i][j], HIGH);
    }
  }
}

jetzt getestet mit dem SerMon, und noch ein wenig verändert.

// basiert auf: https://forum.arduino.cc/t/mehrere-multiple-button-states/862875
// Dieser Sketch macht was - getestet mit den seriellen Ausgaben.

// Noch verändert: 
// - Ich reagiere auf LOW am Button. (INPUT-PULLUP)
// - Verzicht auf die Variable newSwitchState

const bool ein=HIGH;
const bool aus=LOW;
const uint8_t pinButton[2] = {2, 3};
const uint8_t pinLED[sizeof(pinButton)][3] = {{13, 12, 11}, {10, 9, 8}} ;

uint8_t ButtonStates[sizeof(pinButton)][3] = {{aus, aus, aus}, {aus, aus, aus}};

// variables to hold the new and old switch states
boolean oldSwitchState[sizeof(pinButton)] = {ein, ein};
uint8_t state[sizeof(pinButton)] = {aus, aus};

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < 3; j++)
    {
      pinMode(pinLED[i][j], OUTPUT);
      digitalWrite(pinLED[i][j], aus);
      Serial.print(F("LED-Pin initialisiert: "));
      Serial.print(i);
      Serial.print("\t");
      Serial.print(j);
      Serial.print("\t");
      Serial.println(pinLED[i][j]);
    }
  }
  Serial.println();
  for (uint8_t  i = 0; i < sizeof(pinButton); i++)
  {
    pinMode(pinButton[i], INPUT_PULLUP);
    Serial.print(F("Taster-Pin initialisiert: "));
    Serial.print(i);
    Serial.print("\t");
    Serial.println(pinButton[i]);
  }
  delay(2000); // Pause zum lesen...
}


void loop()
{
  // Taster Abfrage
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    if (digitalRead(pinButton[i]) != oldSwitchState[i])
    {
      Serial.print(F("Taster Pin: "));
      Serial.print(i);
      Serial.print(F(" hat neuen Status: "));
      Serial.println(!oldSwitchState[i]);
      if (oldSwitchState[i] == ein)
      {
        state[i]++;
        if (state[i] > 3) {
          state[i] = 0;
        }
        Serial.print(F("LED-Kreis: "));
        Serial.print(i);
        Serial.print(F(" hat neuen Status: "));
        Serial.println(state[i]);
        oldSwitchState[i]=aus;
      }
      else
      {
      oldSwitchState[i]=ein;
      }
      delay(20);
    }
  }

  // LED Ausgabe
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < sizeof(pinLED[i]); j++)
    {
      digitalWrite(pinLED[i][j], aus);
      if (state[i] == j) digitalWrite(pinLED[i][j], ein);
    }
  }
}

Guten Morgen zusammen,

@agmue & @Koepel : hatte unter "How to use this forum" im Vorfeld gekuckt, wie man den Code einbindet. Allerdings führt der der Link von nickgammon ins Leere. Aber jetzt weiß ich es ja :slight_smile: und an dieser Stelle Danke auch an Uwe!

@Rentner & @my_xy_projekt : vielen Dank für die Hinweise und den neuen Code. Werde ich gleich heute einmal ausprobieren. Mit const, uint8_t sowie sizeof ist der Code nun doch ganz anders.....soweit bin ich mit meinem Wissen noch gar nicht :smiley: aber ich werde mich da schon reinfuchsen. Vielen Dank noch einmal!!!

Das ist nicht schwer.
uint8_t -> unsigned int
const ist nur die Festlegung, das der Wert nicht mehr verändert werden kann
sizeof ->
https://www.arduino.cc/reference/de/language/variables/utilities/sizeof/
https://en.cppreference.com/w/cpp/language/sizeof

Das nutze ich, um die Größe des arrays rauszubekommen.
Wenn Du oben noch einen weiteren Taster anbaust, dann müsstest Du alles komplett neu schreiben; das vermeide ich damit.

Bitte beachte, das ich den Taster anders abfrage. musst evtl. noch ändern,

Na dann..

Okay, also doch noch einmal ich. Ich habe schnell die Schaltung in Tinkercad nachgebastelt, weil ich kucken wollte, ob es funktioniert. Bei Button Nr. 2 an Pin 3 passiert nichts, auch nicht im SerMon. Die erste LED der 2. Reihe leuchtet dauern und die erste Reihe beginnt mit LED Nr. 2 :-/

Ich stöpsle das heute Abend zu Hause noch einmal nach, vllt liegt es an Tinkercad

Ja.
Ich schrieb doch: Ich habe die anders angeschlossen.
Bei mir geht der Schalter vom PIN nach GND, weil ich den internen PULLUP nutze und nichts aussen anbaue.

Okidoki, dein neuer Post wurde mir vorhin gar nicht angezeigt. Okay, dann probiere ich noch einmal.

Stark! Läuft ja wie ein Länderspiel jetzt :slight_smile: Danke.

Aber wie bekomme ich es hin, dass zu Beginn alle LEDs aus sind und nicht jeweils das erste an?

Nicht ganz:

  • u: unsigned
  • int: Integer, also eine ganze Zahl, nicht float
  • 8: 8 Bit breit; unsigned int hat auf einem UNO 16 Bit
  • _t: ein Typ, zumindest lese ich das so

Das ist nach der Umstellung auf eine neue Foren-Software noch nicht korrigiert. @uwefed: Könntest Du das bitte mal machen oder initiieren?!

Dann könntest Du auch das Einbinden nützlicher Bibliotheken lernen, denn man muß das Rad ja nicht neu erfinden:

#define MAX8BUTTONS     // maximal 8 Taster, Standard sind 16
#include <MobaTools.h>  // Über die IDE zu installieren

const bool ein = HIGH;
const bool aus = LOW;
const uint8_t anzahlTaster = 2;
const uint8_t pinButton[anzahlTaster] = {2, 3};
const uint8_t anzahlLED = 3;
const uint8_t pinLED[anzahlTaster][anzahlLED] = {{13, 12, 11}, {10, 9, 8}} ;

uint8_t ButtonStates[anzahlTaster][anzahlLED] = {{aus, aus, aus}, {aus, aus, aus}};

button_t getHW( void ) {  // User-Callback-Funktion: Einlesen der Tasterstates
  button_t tasterTemp = 0;
  for (byte i = 0; i < anzahlTaster; i++) {
    bitWrite( tasterTemp, i, !digitalRead(pinButton[i]) );   // Fragt den Taster ab und merkt sich den Status
  }
  return tasterTemp;
}

MoToButtons Taster( getHW, 20, 500 );  // 20ms Entprellzeit, 500ms für den Unterschied kurz/lang gedrückt.

void setup()
{
  Serial.begin(9600);
  delay(500);
  Serial.println(F("Start..."));
  for (uint8_t i = 0; i < anzahlTaster; i++)
  {
    pinMode(pinButton[i], INPUT_PULLUP);  // Taster-Pins als Input definieren (gedrückt = LOW)
    for (uint8_t j = 0; j < anzahlLED; j++)
    {
      pinMode(pinLED[i][j], OUTPUT);
      digitalWrite(pinLED[i][j], ein);
      Serial.print(F("LED-Pin initialisiert: "));
      Serial.print(i);
      Serial.print("\t");
      Serial.print(j);
      Serial.print("\t");
      Serial.println(pinLED[i][j]);
      delay(500);
      digitalWrite(pinLED[i][j], aus);
    }
  }
  Serial.println();
}


void loop()
{
  Taster.processButtons();  // Taster entprellt einlesen und Startzeit merken
  static uint8_t schritt[anzahlTaster];

  // Taster Abfrage
  for (uint8_t taster = 0; taster < anzahlTaster; taster++)
  {
    if ( Taster.shortPress(taster) ) {
      {
        Serial.print(F("Taster Pin: "));
        Serial.print(pinButton[taster]);
        Serial.println(F(" hat neuen Status "));
        if (schritt[taster] < anzahlLED) {
          schritt[taster]++;
        } else {
          schritt[taster] = 0;
        }
      }
    }

    // LED Ausgabe
    for (uint8_t i = 0; i < anzahlTaster; i++)
    {
      for (uint8_t j = 0; j < sizeof(pinLED[i]); j++)
      {
        digitalWrite(pinLED[i][j], aus);
        if (schritt[i] == j) digitalWrite(pinLED[i][j], ein);
      }
    }
  }
}

indem Du bei state nicht mit 0 anfängst sondern mit 3.
Ich hab das mal komplettiert und das was nicht gebraucht wird rausgehauen.

// basiert auf: https://forum.arduino.cc/t/mehrere-multiple-button-states/862875
// Dieser Sketch macht was - getestet mit den seriellen Ausgaben.

// Noch verändert: 
// - Ich reagiere auf LOW am Button. (INPUT-PULLUP)
// - Verzicht auf die Variable newSwitchState

const bool ein=HIGH;
const bool aus=LOW;
const uint8_t pinButton[2] = {2, 3};
const uint8_t pinLED[sizeof(pinButton)][3] = {{13, 12, 11}, {10, 9, 8}} ;

// variables to hold the new and old switch states
boolean oldSwitchState[sizeof(pinButton)] = {ein, ein};
uint8_t state[sizeof(pinButton)] = {3, 3};

void setup()
{
  Serial.begin(115200);
  Serial.println(F("Start..."));
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < sizeof(pinLED[sizeof(pinButton)]); j++)
    {
      pinMode(pinLED[i][j], OUTPUT);
      digitalWrite(pinLED[i][j], aus);
      Serial.print(F("LED-Pin initialisiert: "));
      Serial.print(i);
      Serial.print("\t");
      Serial.print(j);
      Serial.print("\t");
      Serial.println(pinLED[i][j]);
    }
  }
  Serial.println();
  for (uint8_t  i = 0; i < sizeof(pinButton); i++)
  {
    pinMode(pinButton[i], INPUT_PULLUP);
    Serial.print(F("Taster-Pin initialisiert: "));
    Serial.print(i);
    Serial.print("\t");
    Serial.println(pinButton[i]);
  }
}


void loop()
{
  // Taster Abfrage
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    if (digitalRead(pinButton[i]) != oldSwitchState[i])
    {
      Serial.print(F("Taster Pin: "));
      Serial.print(i);
      Serial.print(F(" hat Status: "));
      Serial.println(!oldSwitchState[i]);
      if (oldSwitchState[i] == aus)
      {
        state[i]++;
        if (state[i] > 3) {
          state[i] = 0;
        }
        Serial.print(F("LED-Kreis: "));
        Serial.print(i);
        Serial.print(F(" hat neuen Status: "));
        Serial.println(state[i]);
        oldSwitchState[i]=ein;
      }
      else
      {
      oldSwitchState[i]=aus;
      }
      delay(20);
    }
  }

  // LED Ausgabe
  for (uint8_t i = 0; i < sizeof(pinButton); i++)
  {
    for (uint8_t j = 0; j < sizeof(pinLED[i]); j++)
    {
      digitalWrite(pinLED[i][j], aus);
      if (state[i] == j) digitalWrite(pinLED[i][j], ein);
    }
  }
}

Wenn Du nach einem Umlauf - also LED 13 - 12 - 11 nicht willst, das wieder alle ausgehen, dann einfach die Zeile:

    if (state[i] > 3) {

ändern in
if (state[i] >= 3) {

@agmue Vielen Dank für die Infos noch einmal. Bibliotheken? Ohje, da habe ich aktuell noch zu großen Respekt davor. Ich weiß, wenn man etwas größeres vor hat, sind Bibliotheken mehr als praktisch. Und im Grunde nach, weiß ich auch, wofür diese gut sind. Aber bei meinem Wissensstand muss ich noch grundlegende Grundlagen erlernen, bevor ich mich mit Bibliotheken beschäftige. MoBaTools merke ich mir aber - 16 Taster? Perfekt für mein Projekt.

@my_xy_projekt Besten Dank!!!!

Davon möchte ich Dich keinesfalls abbringen!

Das Beispiel habe ich nicht nur für Dich, sondern zum Test der MobaTools geschrieben und nach einem kurzen Austausch mit dem Autor @MicroBahner wird er seine Doku im Detail überarbeiten. So hast Du indirekt ein wenig zur Verbesserung dieser Bibliothek beigetragen. Klasse, oder?

Ein wenig für die Gemeinschaft, viel für Dich, so läuft ein öffentliches Forum :slightly_smiling_face:

@agmue Natürlich ist das Klasse :slight_smile:

Ich werde mich auch damit auseinander setzen - nur nicht in diesem Augenblick...In Tinkercad kann ich keine Bibliotheken einbinden. Und auf Arbeit kann ich nur Tinkercad nutzen :wink:

Ich trage gerne auch zur Verbesserung bei oder teile - irgendwann, wenn ich schlau genug bin - auch gerne meine Wissen :slight_smile: