Keypad schalten on/off mit 1 Taster

Hallo,

ich habe mir etwas code umgeschrieben, um mit einem keypad ein 8-fach Relaisboard schalten zu können mit jeweils einem Taster on/off.
Hier erstmal der code:

/*4x4 Matrix Keypad connected to Arduino
This code prints the key pressed on the keypad to the serial port*/

#include <Keypad.h>

const byte numRows= 4; //number of rows on the keypad
const byte numCols= 4; //number of columns on the keypad
const int ledPin = 13;
const int ledPin2 = A0;
const int ledPin3 = A1;

int state1 = HIGH;      // the current state of the output pin
int state2 = HIGH;
int state3 = HIGH;

int stat = 0;
   // the previous reading from the input pin

long time = 0;
long debounce = 200;

//keymap defines the key pressed according to the row and columns just as appears on the keypad
char keymap[numRows][numCols]= 
{
{'1', '2', '3', 'A'}, 
{'4', '5', '6', 'B'}, 
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

//Code that shows the the keypad connections to the arduino terminals
byte rowPins[numRows] = {7,6,5,4}; //Rows 0 to 3
byte colPins[numCols]= {3,2,1,0}; //Columns 0 to 3

//initializes an instance of the Keypad class
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
pinMode(ledPin2, OUTPUT);
pinMode(ledPin3, OUTPUT);


}

//If key is pressed, this key is stored in 'keypressed' variable
//If key is not equal to 'NO_KEY', then this key is printed out
//if count=17, then count is reset back to 0 (this means no key is pressed during the whole keypad scan process
void loop()

{
  char keypressed = myKeypad.getKey();
  if(keypressed)  // Check for a valid key.
  {
    switch (keypressed)
    {
    
    
      case '1':
    if (state1 == LOW)
      state1 = HIGH;
    else
      state1 = LOW;
break;
       case '2':
    if (state2 == LOW)
      state2 = HIGH;
    else
      state2 = LOW;
      break;

      case '4':
    if (state3 == LOW)
      state3 = HIGH;
    else
      state3 = LOW;
      break;

      case '*':
    if (state1 == LOW)
      state1 = HIGH;
    
      if (state2 == HIGH)
      state2 = LOW;
    
      if (state3 == HIGH)
      state3 = LOW;
    
      break;

      case '0':
    if (state1 == HIGH)
      state1 = LOW;
    
      if (state2 == LOW)
      state2 = HIGH;
    
      if (state3 == LOW)
      state3 = HIGH;
    
      break;
   
  }
  

  digitalWrite(ledPin, state1);
  digitalWrite(ledPin2, state2);
  digitalWrite(ledPin3, state3);

  delay (1);
    }  


  }

Dass das keypad derzeit falsch angeschlossen ist (an D0+1) hat praktische Gründe und soll nicht stören, die beiden linken Spalten funzen…
Mir geht es um folgenden bug:
Wenn ich einschalte, muss ich zuerst “1” drücken, dann funktioniert alles prima. Ich hab alles probiert, das irgendwie zu simulieren, leider erfolglos. Jetzt steh ich auf dem Schlauch :frowning:

Wer könnte helfen?

vielen Dank vorab

PS: bin neu hier und Newbie

Hallo nochmal,

keiner eine Idee?

Hallo,
keine Ahnung, das Ding hat 16 Tasten. Die Lib scheint etwas zu zählen
(//if count=17, then count is reset back to 0)

Dieses "count" finde ich aber im Sketch nicht wieder…

Funktioniert es auch, wenn Du z.B. "3" drückst?
Wenn dem so ist, dann muss der Sketch "angeschubst" werden.
Schaue doch einmal in die Lib.
Gruß und Glück
Andreas

Den count findest du da auch nicht - ist nur eine Subroutine um die 16 pads zu lesen.

Das funktioniert ähnlich bei anderen Tasten auch, ja. Nur ist vda immer was anderes an. Ich denke, meine Hilfsvariablen "stat" müssen i-wie einen im loop gesetzt werden zu anfangs - nur bin ich noch zu doof, zu wissen, wie.
Hab schon alles probiert :frowning:

Kann da keiner helfen?

Hallo,
mit deiner letzten Vermutung liegst du wohl gar nicht so falsch. Zufällig habe ich gerade selbst erst mit dem Keypad experimentiert und bin zu vergleichbaren Ergebnissen gekommen. Setze doch innerhalb "setup()" deine "stats" auf definierte Anfangs-Zustände, und dann dürfte alles funktionieren. Du kannst innerhalb "setup()" die LEDs ebenso ON oder OFF setzen und auch Variablen mit Werten füllen, so wie du es auch in der "loop()" machen würdest.
Gruß, Rudi

Da der Sketch keine Dokumentation beinhaltet, ist dieser nicht sehr übersichtlich.

Auch versteh ich nicht, warum du in den switch/case-Anweisungen unterschiedlichste if-Anweisungen reinsetzt. Hier verstehe ich den Zusammenhang nicht.

Bitte besser dokumentieren.

Da du schreibst, den Sketch hast du umgeschrieben, poste doch bitte mal den original Sketch zum Vergleich.

Ich habe mir den code selber aus vorhandenem zusammengewürfelt. Die if-Anweisungen in den cases dienen mit der Hilfsvariable stateX dazu, dass ich mit einem Taster erst on, dann off schalten kann. * = all on, 0 = all off.
Mein Problem ist nun, dass ich das irgendwie am Anfang in einen definierten Zustand bringen muss.

Mistviech:
Ich habe mir den code selber aus vorhandenem zusammengewürfelt. Die if-Anweisungen in den cases dienen mit der Hilfsvariable stateX dazu, dass ich mit einem Taster erst on, dann off schalten kann. * = all on, 0 = all off.
Mein Problem ist nun, dass ich das irgendwie am Anfang in einen definierten Zustand bringen muss.

Hier " * = all on, 0 = all " brauchst du doch keine if-Anweisung, da reicht doch "stateX=LOW oder HIGH".

Bei den übrigen Case/Switch sehe ich nur bei Case '4' einen Fehler, da hast du "state3" drin.

Lass dir doch auf dem SerialMonitor mal den Inhalt von "keypressed" anzeigen, ob das alles richtig ist.

Hallo,
so richtig komme ich da nicht mit klar…
Nehmen wir einmal Case 4

case '4':
    if (state3 == LOW)
      state3 = HIGH;
    else
      state3 = LOW;
      break;

Wenn mich nicht alles täuscht, dann ist es doch so, das eine IF-Anweisung
etwas prüft. Wenn es geprüft ist, dann wird ein Code in geschweiften
Klammern ausgeführt.

Wenn dieser Code nicht in geschweiften Klammern gesetzt ist, dann ist es doch
die nächste ausführbare Anweisung.

Ich verstehe das so:

if (state3 == LOW) // schön- und jetzt? Spielt doch keine Rolle!?

state3 = HIGH; // das wird ausgeführt, egal wie state3 steht

else // und? läuft doch durch

state3 = LOW;  // das wird ausgeführt, egal wie state3 steht

Wenn Du Case 4 anspringst, dann wird state3 erst auf HIGH- und dann sofort
auf LOW gesetzt.

Ich würde case 4 so aufbauen:

case '4':
    if (state3 == LOW) // Bedingung
{
      state3 = HIGH; // wenn Wahr, mach
}
    else
{
      state3 = LOW; // wenn nicht Wahr, mach
}
      break;

Die Idee mit dem original Sketch ist vielleicht nicht schlecht.
Gruß und Spaß
Andreas

@SkobyMobil

Wenn nur ein Befehl in der if-Anweisung steht, braucht es keine geschweiften Klammern.

Hallo nochmal,

das mit den Klammern bringt auch nix - dasselbe Ergebnis.
hier mal das original, glaub example von Adafruit zum keypad:

/*4x4 Matrix Keypad connected to Arduino
This code prints the key pressed on the keypad to the serial port*/

#include <Keypad.h>

const byte numRows= 4; //number of rows on the keypad
const byte numCols= 4; //number of columns on the keypad
const int ledPin = 13;

//keymap defines the key pressed according to the row and columns just as appears on the keypad
char keymap[numRows][numCols]= 
{
{'1', '2', '3', 'A'}, 
{'4', '5', '6', 'B'}, 
{'7', '8', '9', 'C'},
{'*', '0', '#', 'D'}
};

//Code that shows the the keypad connections to the arduino terminals
byte rowPins[numRows] = {7,6,5,4}; //Rows 0 to 3
byte colPins[numCols]= {3,2,1,0}; //Columns 0 to 3

//initializes an instance of the Keypad class
Keypad myKeypad= Keypad(makeKeymap(keymap), rowPins, colPins, numRows, numCols);

void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
}

//If key is pressed, this key is stored in 'keypressed' variable
//If key is not equal to 'NO_KEY', then this key is printed out
//if count=17, then count is reset back to 0 (this means no key is pressed during the whole keypad scan process
void loop()

{
  char keypressed = myKeypad.getKey();
  if(keypressed)  // Check for a valid key.
  {
    switch (keypressed)
    {
      case '2':
        digitalWrite(ledPin, LOW);
        break;
      case '1':
        digitalWrite(ledPin, HIGH);
        break;
      default:
        Serial.println(keypressed);
    }
  }
}

Kann es sein, dass das Programm bei:

void loop()

{
char keypressed = myKeypad.getKey();

wartet, bis die erste Taste gedrückt wird? Dann würde mich das garnicht wundern.

Hallo,
@HotSystems

und das soll auch bei einer if/else funktionieren?
Dann hätte ich etwas gelernt…
Gruß und Dank
Andreas

@Mistvieh

... wartet, bis die erste Taste gedrückt wird? Dann würde mich das garnicht wundern ...

Genau so verhält es sich wohl.

@SkobyMobil
Es funktioniert in der Tat ohne Klammern, wenn man nur EINEN Befehl nach einem if() benötigt:

if( bedingung )
  mache_dieses();
else
  mache_jenes();

Nutze ich selbst sehr häufig.

Interessant wird es bei "bedingten Zuweisungen",
aber da lassen wir hier erst mal die Finger von
So in der Form von:

ret = ( x == true ) ? 123 : 456;

:slight_smile:

Gruß, Rudi

SkobyMobil:
Hallo,
@HotSystems

und das soll auch bei einer if/else funktionieren?
Dann hätte ich etwas gelernt…
Gruß und Dank
Andreas

Wurde ja schon bestätigt.
Aber, wir lernen doch alle noch dazu. :wink:

Das kann man übrigens abkürzen:

state3 = !state3;

Fertig. Invertiert den Zustand und macht eine Zuweisung

RudiDL5:
@MistviehGenau so verhält es sich wohl.

Na sowas doofes auch. Da ist die Lösung ja ganz simpel. Ich setze die letzten Ausführbefehle zu Anfang.....