Tastenaggregat / Radio Buttons wie am besten programmieren ?

Hallo,

für ein Projekt benötige ich so eine Art klassisches Tastenaggregat. Also ca. 10 Taster die an diversen digitalen Eingängen eines z.B. UNO hängen und 10 Leuchtdioden (z.B. an Schieberegister 4094)

Die Tasten sollen gegeneinander verriegelt sein. Also wenn man Taste 1 drückt leuchtet LED1, wenn man nun z.B. Taste 3 drückt geht LED1 aus und entsprechend LED3 an, so wie bei klassischen Tastenaggregaten wo immer nur eine Taste gedrückt ist und die vorherige "rausspringt".

Ich habe jetzt überlegt eine State Machine zu programmieren, wird aber für so eine einfache Aufgabe erstaunlich umfangreich weil man von jeder der 10 Positionen auf jede andere springen kann...
Macht man das wirklich so oder gibt es dafür einen einfacheren Trick?

Danke,
Christian

Wieso Trick....Statemachine ist für dein Projekt schon das richtige.

Hi

Du kannst doch, wenn ein Taster erkannt wird, die Eingabe löschen, die jetzigen Taster übernehmen, prüfen, ob's nur Einer ist und 1:1 zum Ausgang 'durchschieben'.
Oder per PC_INT wird der erste Eingang, Der von diesem PC_INT erfasst wird, wird als der einzige Taster festgelegt.
Wenn Dieser gerade betätigt wurde (der PC_INT schlägt auch beim Lösen, auch beim Prellen an) werden alle Ausgänge abgeschaltet und nur der Eine AN.

Oder anders gefragt: Was hast Du vor?
Vll. hast Du ja ein ganz anderes Problem, als Das, was Du nun zu Lösen versuchst.
(X-Y-Problem)

MfG

Ich habe jetzt überlegt eine State Machine zu programmieren, wird aber für so eine einfache Aufgabe erstaunlich umfangreich weil man von jeder der 10 Positionen auf jede andere springen kann...
Macht man das wirklich so oder gibt es dafür einen einfacheren Trick?

Die 10 handelt man in einer Schleife ab.
Oder in einem 16 Bit Wort.
Da baut man keinen Automaten für 11 Zustände!

Der Automat muss also für 10 LED nicht fetter sein, als der Automat für 2 LED.

Ich würde es so machen:

du beginnst mit dem Beispiel 02.Digital | Debounce -> Taster verstehen lernen
dann erweiterst mal einen zweiten Taster und zweite LED die sich gegenseitig auslösen. -> Feasibilty
bevor du den dritten bis zehnten Button und LED anschließt verwendest für die Pins Arrays. -> Umsetzen was Combie schreibt

noiasca:
du beginnst mit dem Beispiel 02.Digital | Debounce -> Taster verstehen lernen

Auch wenn ich Dir grundsätzlich zustimme, ist in diesem Thema das Entprellen kein Thema, da die Tasten ja rasten sollen.

Hier ein überzogener Vorschlag......

Ist ein Fragment aus meiner Wühlkiste.
Benennungen usw. leicht für diese Zwecke angepasst.
Raus schieben hinzugefügt

template<typename T>
class Tastenaggregat
{
  private:
   T aggregat;

  public:
    Tastenaggregat():aggregat(0){}

    T operator ()(uint16_t index)
    {
      aggregat = 1ULL<<index;
      return aggregat;
    }
        
    operator T()
    {
      return aggregat;
    }
};

template<typename ArrayType, size_t count> constexpr size_t arrayCount(const ArrayType (&)[count]){return count;}


const byte radioButtons[] {A0,A1,A2,A3,2,3,4,5,6,7};
Tastenaggregat<uint16_t>  tastenaggregat;

void handleRadioButtons()
{
  uint16_t merker = tastenaggregat;
  for(byte i = 0; i < arrayCount(radioButtons); i++)
  {
    if(not digitalRead(radioButtons[i]))
    {
      tastenaggregat(i);
      break; // erste gefundene gerdueckte Taste gewinnt das Rennen
    }
  }
  
  if(merker != tastenaggregat) // Veraenderung erkennen
  {
      // z.B. hier die daten raus schieben
      //shiftOut(dataPin, clockPin, MSBFIRST, tastenaggregat >> 8);  
      //shiftOut(dataPin, clockPin, MSBFIRST, tastenaggregat);
      Serial.println(tastenaggregat,BIN); // kontrollausgabe
  }
}

void setup() 
{
 Serial.begin(9600);
 Serial.println("Start");
 for(byte button:radioButtons) pinMode(button,INPUT_PULLUP); 
}

void loop() 
{
  handleRadioButtons();
}

Den Off Button habe ich entfernt, da nicht zur Anforderung gehörend.
Evtl. nötige Schutzvorkehrungen ignoriert.

jo, kann man ohne Entprellen auch machen.
Ich habs jetzt mal mit:

/*
  Debounce

  https://forum.arduino.cc/index.php?topic=627418.msg4248707#new

*/

// constants won't change. They're used here to set pin numbers:
const int buttonPin[] = {2, 3, 4};  // the number of the pushbutton pin
const int ledPin[] = {13, 12, 11};    // the number of the LED pin

const byte pins = 3;

// Variables will change:
int ledState[pins];                // the current state of the output pin
int buttonState[pins];             // the current reading from the input pin
int lastButtonState[pins];         // the previous reading from the input pin

// the following variables are unsigned longs because the time, measured in
// milliseconds, will quickly become a bigger number than can be stored in an int.
unsigned long lastDebounceTime[pins];  // the last time the output pin was toggled
const unsigned long debounceDelay = 50;    // the debounce time; increase if the output flickers

void setup() {
  Serial.begin(115200);
  Serial.println(F("Klaviertasten"));
  for (byte i=0; i < pins; i++)
  {
    pinMode(buttonPin[i], INPUT_PULLUP);
    pinMode(ledPin[i], OUTPUT);
    digitalWrite(ledPin[i], ledState[i]);   // set initial LED state
  }
}

void loop() {

  for (byte i = 0; i < pins; i++)
  {
    byte reading = !digitalRead(buttonPin[i]);  //invers, weil ich den Button mit Pullups betreibe
    if (reading != lastButtonState[i]) {
      lastDebounceTime[i] = millis();
    }

    if ((millis() - lastDebounceTime[i]) > debounceDelay) {
      // whatever the reading is at, it's been there for longer than the debounce
      // delay, so take it as the actual current state:

      // if the button state has changed:
      if (reading != buttonState[i]) {
        buttonState[i] = reading;
        Serial.print(i); Serial.println(F(" pressed"));
        // hier bauen wir statt dem toggeln das einschalten und abschalten der anderen Pins
        for (byte j = 0; j < pins; j++)
        {
          if (i == j)
          {
            ledState[j] = HIGH;
          }
          else
          {
            ledState[j] = LOW;
          }
          // set the LED:
          digitalWrite(ledPin[j], ledState[j]);
          Serial.print(j); Serial.println(F("-->"));Serial.println(ledState[j]);
        }
      }
    }
    // save the reading. Next time through the loop, it'll be the lastButtonState:
    lastButtonState [i] = reading;
  }

}

Wenn alle so fleißig ihre Vorschläge machen, mache ich auch noch einen:

byte pos;
uint16_t aus;

struct Tastenaggregat {
  const byte tasterPin, ledPin;
  bool aktZustand, altZustand;
  Tastenaggregat(const byte tasterPin, const byte ledPin) : tasterPin(tasterPin), ledPin(ledPin), aktZustand(0), altZustand(0) {}

  void init() {
    pinMode(tasterPin, INPUT_PULLUP);
    pinMode(ledPin, OUTPUT);
  }

  void aktualisieren() {
    altZustand = aktZustand;
    aktZustand = !digitalRead(tasterPin); // invers, wg. pullup
    if (!altZustand && aktZustand) {
      aus = 1 << pos;
    }
    pos++;
  }

  void ausgabe() {
    bool b = aus & (1 << pos);
    digitalWrite(ledPin, b);
    pos++;
  }
};

Tastenaggregat taster[] = {
  // Taster-Pin, LED-Pin
  {2, 5},
  {3, 6},
  {4, 7}
};

void setup() {
  for (Tastenaggregat &t : taster) t.init();
}

void loop()
{
  pos = 0;
  for (Tastenaggregat &t : taster) t.aktualisieren();
  pos = 0;
  for (Tastenaggregat &t : taster) t.ausgabe();
}

dann probiere ich noch eine anfängertaugliche Variante auf Basis des 02. Digital | Button

// constants won't change. They're used here to set pin numbers:
const int buttonPin[] = {2, 3, 4};  // the number of the pushbutton pin
const int ledPin[] = {13, 12, 11};    // the number of the LED pin
const byte pins = 3;

void setup() {
  Serial.begin(115200);
  Serial.println(F("Piano-push-buttons"));
  for (byte i = 0; i < pins; i++)
  {
    pinMode(buttonPin[i], INPUT_PULLUP);
    pinMode(ledPin[i], OUTPUT);
  }
  //digitalWrite(ledPin[0], HIGH);   // if one LED should be ON after boot
}

void loop() {
  for (byte i = 0; i < pins; i++)
  {
    if (!digitalRead(buttonPin[i]))  //invers, weil ich den Button mit Pullups betreibe
    {
       Serial.print(i); Serial.println(F(" pressed"));
      // hier bauen wir statt dem toggeln das einschalten und abschalten der anderen Pins
      for (byte j = 0; j < pins; j++)
      {
        Serial.print(j);
        if (i == j)
        {
          digitalWrite(ledPin[j], HIGH);
          Serial.println(F("--> HIGH"));
        }
        else
        {
          digitalWrite(ledPin[j], LOW);
          Serial.println(F("--> LOW"));
        }
      }
    }
  }
  // do whatever you need to do ...
  
}