Arduino UNO, Programm über einen Pin umschalten

Hi,

Vorab ich bin neu hier, und Blutiger Anfänger im umgang mit dem Arduino. :grinning:
Ich habe mir gedacht, vielleicht kann mir hier einer bei meinem Problem helfen. Ich würde gerne mein Programm so ändern, dass ich auf Knopfdruck einen anderen Programmteil ausführe. Dieser Knopfdruck soll dann durch ein Board ersetzt werden was an einem UNO hängt und einen Kontakt HIGH setzt. Wenn dieses einen Stromausfall hat, (der Kontakt vom UNO somit LOW) soll das UNO dies Merken und einen bestimmten Programmpunkt ausführen. Wie genau kann ich das umsetzen? Leider habe ich noch keine Möglichkeit so richtig im Netz gefunden. Ich hoffe, ich habe das halbwegs verständlich formuliert. :stuck_out_tongue: Unten ist mal mein Programm.

#include <Keypad.h>
char* secretCode = "3007"; // Sicherheitscode
int position = 0; //Variable
const byte rows = 4; //Reihen des Keypads
const byte cols = 4; //Spalten des Keypads
char keys[rows][cols] = 
{
 
 {'1','2','3','A',},
 {'4','5','6','B',},
 {'7','8','9','C',},
 {'*','0','#','D',}
 
};
byte rowPins[rows] = {1, 2, 3, 4}; //Digitale Pinbelegung am Arduino der Reihen des Keypads
byte colPins[cols] = {5, 6, 7, 8}; //Digitale Pinbelegung am Arduino der Spalten des Keypads
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
int redPin = 10; //Pin 10 rote LED
int greenPin = 9; //Pin 9 grüne LED

void setup() 
{
pinMode(redPin, OUTPUT);
pinMode(greenPin, OUTPUT);
setLocked(true); 
}

void loop() 
{

 char key = keypad.getKey();
 if (key == '*' || key == '#') 
 {
   position = 0;
   setLocked(true);
 }

if (key == secretCode[position])
 {
   position ++;
 }
if (position == 4) //Stellen des Sicherheitscodes
 {
   setLocked(false);
 }
 delay(100);
}

void setLocked(int locked)
{
 if (locked)
 {
   digitalWrite(redPin, HIGH); 
   digitalWrite(greenPin, LOW);
 }
 else
 {
   
   digitalWrite(redPin, LOW);
   digitalWrite(greenPin, HIGH);
 }
}

Tim

Hallo Tim,
willkommen im Forum.
Bitte setze deinen Sketch in Code-Tags (Schaltfläche </>) , das kannst du auch nachträglich machen.
Dann können wir den Sketch besser lesen.

Deine einzelnen Programmteile würde ich in Funktionen setzen und mit einem Port der dafür deklariert wird starten.

z.B. folgenden PseudoCode:

const int buttonPin = 2;

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);
}

void loop() {

buttonState = digitalRead(buttonPin);

  if (buttonState == LOW) {
    Funktion1();
  }
  else {
    Funktion2();
  }

  void Funktion1(void) {
    //tu was
  }

  void Funktion2(void) {
    //tu was
  }
}
if(digitalRead(KontaktPin)) {
  // Normaler Programmteil
} else {
  // Stromausfall
}

Hallo Tim,
so würde ich Deine Frage verstehen. Scheint mir etwas einfach, wärst Du wohl auch von alleine drauf gekommen. Wo steckt also das Problem verborgen?

HI,
danke für die Info, habe es mal schnell geändert.
Ich würde das jetzt gerne so ändern das, wenn ich ein Pin habe, der ein HIGH-Signal bekommt das ganz normale Programm durchläuft. Fällt nun dieser Pin auf LOW soll sofort ein anderer Programmteil laufen. Zum Beispiel soll dann alles gleich bleiben bis auf eine LED die dan blinkt. Wie das géht das die blinkt weiß ich inzwischen:D nur nicht, wie ich dahin komme.
Tim

Tim3007:
HI,
danke für die Info, habe es mal schnell geändert.
Ich würde das jetzt gerne so ändern das, wenn ich ein Pin habe, der ein HIGH-Signal bekommt das ganz normale Programm durchläuft. Fällt nun dieser Pin auf LOW soll sofort ein anderer Programmteil laufen. Zum Beispiel soll dann alles gleich bleiben bis auf eine LED die dan blinkt. Wie das géht das die blinkt weiß ich inzwischen:D nur nicht, wie ich dahin komme.
Tim

Das ist doch das was ich oben als Beispiel geschrieben habe, oder?

Hi HotSystem,
Vielen Dank für die schnelle Antwort. Hatte das erst nach meinem Post gesehen. Ich habe das mal in meinem erweitertem Code umgesetzt. Da scheinen aber einige Fehler zu sein. Seit der Änderung wird mir " 'setLocked' was not declared in this scope " angezeigt. Der Fehler war vorher nicht da. In dem Bereich habe ich auch nichts verändert.

#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* secretCode = "3007"; 
int position = 0;  
const byte rows = 4; 
const byte cols = 4; 
char keys[rows][cols] = 
{
  
  {'1','2','3','A',},
  {'4','5','6','B',},
  {'7','8','9','C',},
  {'*','0','#','D',}
  
};
byte rowPins[rows] = {21, 22, 23, 24}; 
byte colPins[cols] = {25, 26, 27, 28}; 
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
const int redPin = 17; 
const int greenPin = 16; 
const int buttonPin = 19;
int buttonState = 0;
int val = 0;
const int Fehler = 18;

void setup() 
{
 pinMode(buttonPin, INPUT_PULLUP);
 lcd.begin(16, 2);
 lcd.setCursor(1,0);
 lcd.print("Starte");
 delay(50);
 lcd.blink();
 delay(3000);
 lcd.noBlink();
 delay(1000);
 
 
 
 lcd.clear();
 pinMode(redPin, OUTPUT);
 pinMode(greenPin, OUTPUT);
 pinMode(buttonPin, INPUT);
 setLocked(true); 
}

void loop() 
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH);
  {
    lcd.setCursor(5, 0);
  lcd.print("AKTIV");
  buttonState = digitalRead(buttonPin);
  val = digitalRead(buttonPin);

  char key = keypad.getKey();
  if (key == '*' || key == '#') 
  {
    position = 0;
    setLocked(true);
  }

if (key == secretCode[position])
  {
    position ++;
  }
if (position == 4) 
  {
    setLocked(false);
  }
  delay(100);
}

void setLocked(int locked)
{
  if (locked)
  {
    
    {
    
    digitalWrite(redPin, HIGH); 
    digitalWrite(greenPin, LOW);
    lcd.clear();
    
    }
    
}

 
  else
  {
    
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    lcd.setCursor(3,1);
    lcd.print("ENTSPERRT");
    delay(1500);
   }
 else
 {
     
    digitalWrite(Fehler, HIGH);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);
    digitalWrite(Fehler,LOW);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);
    lcd.setCursor(1,1);
    lcd.print("Fehler:123121221");
 }

  
 }
  }

Du musst dein Klammern mal überprüfen, da sind einige falsch gesetzt.

Und 2 mal else hinter if geht auch nicht.

Z.B. so:

#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* secretCode = "3007";
int position = 0;
const byte rows = 4;
const byte cols = 4;
char keys[rows][cols] =
{

  {'1', '2', '3', 'A',},
  {'4', '5', '6', 'B',},
  {'7', '8', '9', 'C',},
  {'*', '0', '#', 'D',}

};
byte rowPins[rows] = {21, 22, 23, 24};
byte colPins[cols] = {25, 26, 27, 28};
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
const int redPin = 17;
const int greenPin = 16;
const int buttonPin = 19;
int buttonState = 0;
int val = 0;
const int Fehler = 18;

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.setCursor(1, 0);
  lcd.print("Starte");
  delay(50);
  lcd.blink();
  delay(3000);
  lcd.noBlink();
  delay(1000);



  lcd.clear();
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  setLocked(true);
}

void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH);
  {
    lcd.setCursor(5, 0);
    lcd.print("AKTIV");
    buttonState = digitalRead(buttonPin);
    val = digitalRead(buttonPin);

    char key = keypad.getKey();
    if (key == '*' || key == '#')
    {
      position = 0;
      setLocked(true);
    }

    if (key == secretCode[position])
    {
      position ++;
    }
    if (position == 4)
    {
      setLocked(false);
    }
    delay(100);
  }
}

void setLocked(int locked)
{
  if (locked)
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    lcd.clear();
  }
  else
  {
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    lcd.setCursor(3, 1);
    lcd.print("ENTSPERRT");
    delay(1500);
//    }
//    else
//    {

    digitalWrite(Fehler, HIGH);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);
    digitalWrite(Fehler, LOW);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);
    lcd.setCursor(1, 1);
    lcd.print("Fehler:123121221");
  }
}

Das zweite "else" habe ich einfach mal auskommentiert. Must du noch richtig setzen.

Perfekt danke. Ich werde es gleich mal überarbeiten

Tim3007:
... soll sofort ein anderer Programmteil laufen ...

Diese Aussage und die Verwendung von delay() widersprechen sich. Stattdessen solltest Du auf die blockierungsfreie Nutzung von millis() umsteigen, siehe Beispiel blinkwithoutdelay.

So, ich habe das jetzt mal erfolgreich umgesetzt. Habe jetzt folgendes Problem. Wenn ich das 2. else weg lasse dann startet er sofort den teil für code richtig und buttonPin LOW. was genau muss ich einsetzen das das erste else zu dem bereich buttonPin HIGH zählt und das 2. else in diesem fall passend zum buttonPin LOW teil ist. Im Prinzip muss ich ja nur das 1. else ändern oder?

Das versteh ich nicht.

Beschreibe mal, was du erreichen möchtest, bzw. wann das eintreten soll.

Da der Code nicht dokumentiert (habe ich mal nicht beanstandet :wink: ) ist, ist er auch schwer zu durchschauen.

Und beachte bitte auch was agmue geschrieben hat.

Okay,
Ich hätte gerne das das Programm solange wie buttonPin HIGH ist ganz normal durchlaufen wird

#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* secretCode = "3007";
int position = 0;
const byte rows = 4;
const byte cols = 4;
char keys[rows][cols] =
{

  {'1', '2', '3', 'A',},
  {'4', '5', '6', 'B',},
  {'7', '8', '9', 'C',},
  {'*', '0', '#', 'D',}

};
byte rowPins[rows] = {21, 22, 23, 24};
byte colPins[cols] = {25, 26, 27, 28};
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
const int redPin = 17;
const int greenPin = 16;
const int buttonPin = 19;
int buttonState = 0;
int val = 0;
const int Fehler = 18;

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.setCursor(1, 0);
  lcd.print("Starte");
  delay(50);
  lcd.blink();
  delay(3000);
  lcd.noBlink();
  delay(1000);



  lcd.clear();
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  setLocked(true);
}

void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH);
  {
    lcd.setCursor(5, 0);
    lcd.print("AKTIV");
    buttonState = digitalRead(buttonPin);
    val = digitalRead(buttonPin);

    char key = keypad.getKey();
    if (key == '*' || key == '#')
    {
      position = 0;
      setLocked(true);
    }

    if (key == secretCode[position])
    {
      position ++;
    }
    if (position == 4)
    {
      setLocked(false);
    }
    delay(100);
  }
}

void setLocked(int locked)
{
  if (locked)
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    lcd.clear();
  }
  else
  {
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    lcd.setCursor(3, 1);
    lcd.print("ENTSPERRT");
    delay(1500);
//    }

Sobald nun aber der buttonPin LOW wird soll zum beispiel dieser teil ablaufen

digitalWrite(redPin, LOW);
delay(100);
digitalWrite(redPin, HIGH);
delay(100);

Das was agmue sagte ist nicht nötig da das Arduino automatisch wenn buttonPin auf LOW geht neu gestartet wird (Notstromversorgung über einen 9V Block an einem Relays am öffner) Der buttonPin wird ein Arduino nano sein welches nur dafür da ist das Relais zu steuern und den Pin auf HIGH zu halten. Sollte der Strom ausfallen wird nur das UNO weiter versorgt. Diese soll dann um genau zu sein einen Programmteil starten der dann mehr oder weniger ein Energiesparmodus sein wird. Alles zumsammen soll dann die Steuerung von einem Tresor sein. Ich hoffe das war verständlicher als eben. :slight_smile: Den Code im 2. Kasten ist vorerst nur ein beispiel, ich werde es dann noch weiter anpassen.

Ok, dann sollte das so richtig sein:
Die Änderung habe ich am Ende des "if-Durchlaufes" aingetragen.

#include <Keypad.h>
#include <LiquidCrystal.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* secretCode = "3007";
int position = 0;
const byte rows = 4;
const byte cols = 4;
char keys[rows][cols] =
{

  {'1', '2', '3', 'A',},
  {'4', '5', '6', 'B',},
  {'7', '8', '9', 'C',},
  {'*', '0', '#', 'D',}

};
byte rowPins[rows] = {21, 22, 23, 24};
byte colPins[cols] = {25, 26, 27, 28};
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
const int redPin = 17;
const int greenPin = 16;
const int buttonPin = 19;
int buttonState = 0;
int val = 0;
const int Fehler = 18;

void setup()
{
  pinMode(buttonPin, INPUT_PULLUP);
  lcd.begin(16, 2);
  lcd.setCursor(1, 0);
  lcd.print("Starte");
  delay(50);
  lcd.blink();
  delay(3000);
  lcd.noBlink();
  delay(1000);



  lcd.clear();
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);
  pinMode(buttonPin, INPUT);
  setLocked(true);
}

void loop()
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH)
  {
    lcd.setCursor(5, 0);
    lcd.print("AKTIV");
    buttonState = digitalRead(buttonPin);
    val = digitalRead(buttonPin);

    char key = keypad.getKey();
    if (key == '*' || key == '#')
    {
      position = 0;
      setLocked(true);
    }

    if (key == secretCode[position])
    {
      position ++;
    }
    if (position == 4)
    {
      setLocked(false);
    }
    delay(100);
  }
  else     // dies ist neu
  {
    digitalWrite(redPin, LOW);
    delay(100);
    digitalWrite(redPin, HIGH);
    delay(100);
  }
}

void setLocked(int locked)
{
  if (locked)
  {
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    lcd.clear();
  }
  else
  {
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    lcd.setCursor(3, 1);
    lcd.print("ENTSPERRT");
    delay(1500);
  }
}

Tim3007:
Das was agmue sagte ist nicht nötig da das Arduino automatisch wenn buttonPin auf LOW geht neu gestartet wird (Notstromversorgung über einen 9V Block an einem Relays am öffner) Der buttonPin wird ein Arduino nano sein welches nur dafür da ist das Relais zu steuern und den Pin auf HIGH zu halten. Sollte der Strom ausfallen wird nur das UNO weiter versorgt. Diese soll dann um genau zu sein einen Programmteil starten der dann mehr oder weniger ein Energiesparmodus sein wird. Alles zumsammen soll dann die Steuerung von einem Tresor sein. Ich hoffe das war verständlicher als eben. :slight_smile: Den Code im 2. Kasten ist vorerst nur ein beispiel, ich werde es dann noch weiter anpassen.

Vor meinem geistigen Auge sehe ich die Spannungsversorgung des UNO über einen Umschalter geführt, der entweder zum Netzteil oder zu der 9 V Batterie schaltet. Ist das so richtig?

Ich habe das gerade mal mit 5 V und einem Umschaltrelais probiert: Mein UNO bekommt keinen Reset! Während des Umschaltens halten die Kondensatoren die Spannung. Nun handelt es sich um einen sonst unbeschalteten UNO, es ergibt sich aber doch die Frage: Bist Du hinsichtlich des Resets sicher, daß der auch ausgeführt wird?

Alternativ könntest Du das Programm so universell auslegen, daß die Funktionalität sowohl mit als auch ohne Reset gewährleistet ist.

Top!!! Genau so wollte ich das Vielen dank an euch beide.

So ich habe das jetzt mal alles so aufgebaut. Folgendes Problem:
Wärend buttonPin LOW ist kann ich den secretCode nicht eingeben

Problem 2:
Wie genau mache ich das das Das Display nachdem buttonPin wider HIGH ist den unteren Balken (2x16) resetet. Ich habe erst versucht das lcd.clear am schluss dieses teils kommt, dummerweise wird dann das komplette Display resetet.

Problem 3:
Ich habe jetzt im entsperrbereich nach 2,5min setLocked(true) eingegeben, in der zeit kann man das aber nicht mehr manuell sperren.

Vielen dank schonmal im vorraus und entschuldigt mir die ein oder andere dumme Frage :smiley:

Tim3007:
Vielen dank schonmal im vorraus und entschuldigt mir die ein oder andere dumme Frage :smiley:

Dumm sind nicht die Fragen, sondern die Situation, daß wir einen Sketch betrachten sollen, der uns nicht vorliegt. Oder gibt es eine Webcam auf Deinen Schreibtisch, deren Adresse ich nicht kenne?

Oh stimmt Sorry :slight_smile:
Hier der aktuelle Code

#include <LiquidCrystal.h>
#include <Keypad.h>

LiquidCrystal lcd(8, 9, 4, 5, 6, 7);
char* secretCode = "3007"; 
int position = 0;  
const byte rows = 4; 
const byte cols = 4; 
char keys[rows][cols] = 
{
  
  {'1','2','3','A',},
  {'4','5','6','B',},
  {'7','8','9','C',},
  {'*','0','#','D',}
  
};
byte rowPins[rows] = {21, 22, 23, 24}; 
byte colPins[cols] = {25, 26, 27, 28}; 
Keypad keypad =  Keypad(makeKeymap(keys), rowPins, colPins, rows, cols);
const int redPin = 17; 
const int greenPin = 16; 
const int buttonPin = 19;
int buttonState = 0;
int val = 0;
const int Fehler = 18;

void setup() 
{
 pinMode(buttonPin, INPUT_PULLUP);
 lcd.begin(16, 2);
 lcd.setCursor(1,0);
 lcd.print("Starte ");
 delay(50);
 lcd.blink();
 delay(3000);
 lcd.noBlink();
 delay(500);
 lcd.clear();
 pinMode(redPin, OUTPUT);
 pinMode(greenPin, OUTPUT);
 pinMode(buttonPin, INPUT);
 setLocked(true); 
}

void loop() 
{
  buttonState = digitalRead(buttonPin);

  if (buttonState == HIGH)
  {

    buttonState = digitalRead(buttonPin);
    val = digitalRead(buttonPin);

    char key = keypad.getKey();
    if (key == '*' || key == '#') 
    {
      position = 0;
      setLocked(true);
    }

    if (key == secretCode[position])
    {
    position ++;
    }
    if (position == 4) 
    {
    setLocked(false);
    }
    delay(100);
    }
    else     // dies ist neu
    {
    digitalWrite(Fehler, HIGH);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);
    digitalWrite(Fehler,LOW);
    digitalWrite(redPin, HIGH);
    digitalWrite(greenPin, LOW);
    delay(350);


    }
}

void setLocked(int locked)
{
  if (locked)
    {
    digitalWrite(redPin, HIGH); 
    digitalWrite(greenPin, LOW);
    lcd.clear();
    }
  else
    {
    
    digitalWrite(redPin, LOW);
    digitalWrite(greenPin, HIGH);
    lcd.setCursor(3,1);
    lcd.print("ENTSPERRT");
    delay(150000);
    setLocked(true);
   }
}

Tim3007:
Wärend buttonPin LOW ist kann ich den secretCode nicht eingeben

Dann gehört secretCode eingeben außerhalb von if (buttonState == HIGH) {}

Tim3007:
Wie genau mache ich das das Das Display nachdem buttonPin wider HIGH ist den unteren Balken (2x16) resetet. Ich habe erst versucht das lcd.clear am schluss dieses teils kommt, dummerweise wird dann das komplette Display resetet.

Cursor auf die untere Zeile positionieren und dann 16 Leerzeichen schreiben (ungetestet):

if (buttonState && !altbuttonState) {
lcd.setCursor(1,0);
 lcd.print("                ");
}
altbuttonState = buttonState;

agmue wie genau meinst du das? Wenn ich secretCode außerhalb von buttonState setze bin ich doch wider da womit ich angefangen habe. Wie genau soll das denn aussehen?