Hifle - Programmierung Servo-Türsteuerung

Moin,
im voraus möchte ich euch erstmal sagen, dass ich ein völliger Neuling bin, was so große Projekte amgeht.
Und dann auch schon zu meinem Problem.
Ich habe mir aus dem Internet eine Vorlage für ein RFID-Türschloss heruntergeladen, diese ein bisschen umgeschrieben und dann auf den Arduino an unserer Haustür geladen; das funktioniert auch alles super.
Nun wollte ich das ganze auch für unsere Wohnungstür basteln, allerdings scheitere ich hier bei der Programmierung.
Ich habe momentan diesen Sketch auf dem NANO-Board, den Rest des Codes findet ihr im Anhang

///////////////////////////////////////// Main Loop ///////////////////////////////////
void loop () {
  do {
    successRead = getID(); 	// sets successRead to 1 when we get read from reader otherwise 0
    if (programMode) {
      cycleLeds();              // Program Mode cycles through RGB waiting to read a new card
    }
    else {
      normalModeOn(); 		// Normal mode, blue Power LED is on, all others are off
    }
  }
  while (!successRead); 	//the program will not go further while you not get a successful read
  if (programMode) {
    if ( isMaster(readCard) ) { //If master card scanned again exit program mode
      Serial.println(F("Master Card Scanned"));
      Serial.println(F("Exiting Program Mode"));
      Serial.println(F("-----------------------------"));
      programMode = false;
      return;
    }
    else {
      if ( findID(readCard) ) { // If scanned card is known delete it
        Serial.println(F("I know this PICC, removing..."));
        deleteID(readCard);
        Serial.println("-----------------------------");
      }
      else {                    // If scanned card is not known add it
        Serial.println(F("I do not know this PICC, adding..."));
        writeID(readCard);
        Serial.println(F("-----------------------------"));
      }
    }
  }
  else {
    if ( isMaster(readCard) ) {  	// If scanned card's ID matches Master Card's ID enter program mode
      programMode = true;
      Serial.println(F("Hello Master - Entered Program Mode"));
      int count = EEPROM.read(0); 	// Read the first Byte of EEPROM that
      Serial.print(F("I have "));    	// stores the number of ID's in EEPROM
      Serial.print(count);
      Serial.print(F(" record(s) on EEPROM"));
      Serial.println("");
      Serial.println(F("Scan a PICC to ADD or REMOVE"));
      Serial.println(F("-----------------------------"));
    }
    else {
      if ( findID(readCard) ) {	// If not, see if the card is in the EEPROM
        Serial.println(F("Welcome, You shall pass"));
        granted();        	// Open the door lock for 300 ms
      }
      else {			// If not, show that the ID was not valid
        Serial.println(F("You shall not pass"));
        denied();
      }
    }
  }
}

/////////////////////////////////////////  Access Granted    ///////////////////////////////////
void granted() {
  digitalWrite(blueLed, LED_OFF); 	// Turn off blue LED
  digitalWrite(redLed, LED_OFF); 	// Turn off red LED
  digitalWrite(greenLed, LED_ON); 	// Turn on green LED
  if(state == 1){
    servoschloss.write(180);
    state = 0;
  }
  else{
    servoschloss.write(0);
    state = 1;
  }
 Serial.print("1 = OFFEN / 0 = GESCHLOSSEN  Status: ");
 Serial.println(state);
 Serial.print("Gradzahl Servo:  ");
 Serial.println(servoschloss.read());
 delay(1000); 						// Hold green LED on for a second
}

Ich habe nun folgendes Problem. Und zwar ist an unserer Wohnung noch ein altes Buntbartschloss, weshalb ich hier einen Servo verwenden will, welcher sich zum öffen und zum schließen jeweils um 180Grad verstellen soll. Zum ausprobieren habe ich dieses Programm geschrieben:

#include <Servo.h>

#define button 24
int state;
Servo servoschloss;
 
void setup()
{
  servoschloss.attach(22);
  pinMode(button, INPUT);
  
  Serial.begin(9600);
}
 
void loop()
{
 if(digitalRead(button) == HIGH){
  servo();
 }
}

void servo()
{
  if(state == 1)
 {
  servoschloss.write(180);
  state = 0;
 }
 else
 {
  servoschloss.write(0);
  state = 1;
 }
 Serial.print("1 = OFFEN / 0 = GESCHLOSSEN  Status: ");
 Serial.println(state);
 Serial.print("Gradzahl Servo:  ");
 Serial.println(servoschloss.read());
 delay(500);
}

Dieses funktioniert auch super. Drückt man den Knopf verstellt sich der Servo auf 180Grad und bleibt auch auch 180Grad. Drückt man den Knopf dann nochmal, stellt sich der Serbo wieder auf 0Grad und bleibt dort, wie es sein soll.

Also habe ich mir gedacht; das funktionert ja gut; dann füg es doch gleich in das Haupt-Programm ein.
Also bin ich in den Teil gegangen, an dem der RFID-Zugang gewährt wird:

/////////////////////////////////////////  Access Granted    ///////////////////////////////////
void granted() {
  digitalWrite(blueLed, LED_OFF); // Turn off blue LED
  digitalWrite(redLed, LED_OFF); // Turn off red LED
  digitalWrite(greenLed, LED_ON); // Turn on green LED
  if(state == 1){
    servoschloss.write(180);
    state = 0;
  }
  else{
    servoschloss.write(0);
    state = 1;
  }
 Serial.print("1 = OFFEN / 0 = GESCHLOSSEN  Status: ");
 Serial.println(state);
 Serial.print("Gradzahl Servo:  ");
 Serial.println(servoschloss.read());
 delay(1000); // Hold green LED on for a second
}

Und habe meinen Teid dort hinzugefügt. Wenn ich jetzt aber mit der RFID-Karte den Zugang gewähren lasse, stellt sich der Servo auf 180Grad und dann wieder auf 0Grad, obwohl er doch auf 180Grad bleiben soll. Wieso tut er das? Vielen Dank für eure Hilfe.

Ein weiteres Problem ist, dass ich nicht weiß, wo ich den Teil mit dem Schalter ins Haupt-Programm einfügen soll:

if(digitalRead(button) == HIGH){
  servo();
 }

Liebe Grüße
Peach32

sketch_nov24a.ino (532 Bytes)

T_r_Schloss_OBEN.ino (16.9 KB)

Hier nochmal der ganze CODE

[url=http://pastebin.com/D4bYddJ9
Pastebin CODE

stellt sich der Servo auf 180Grad und dann wieder auf 0Grad, obwohl er doch auf 180Grad bleiben soll. Wieso tut er das?

Das macht er im angehängten Sketch (nov24a) im 0.5 sec Takt solange der Taster betätigt ist, in diesem hier im 1 sec takt solange er nach granted() kommt.

Und wo etwas in loop() eingefügt wird, sollte egal sein, weil das Ende von loop () der Anfang von loop() ist.
Wenn es nicht egal ist, ist in deiner Logik was falsch. Meist hängt der sketch in einem delay() und soll also absichtlich nichts machen. :frowning: (Selbst dann ist es egal, wo das, was nicht rechtzeitig drankommt, steht)

Hey,
den Delay am Ende habe ich reingesetzt, damit wenn man den schalter zulange drückt der Servo sich nicht gleich wieder zurück stellt, aber das hat doch nichts damit zutun, dass es ind dem einzelnen Sketch funktioniert und im Ganzen nicht mehr, es ist doch vom Aufbau her gleich.
Lg

Also genau genommen ist es nicht egal ob am Anfang oder am ende der loop. Aber lassen wir es mal gelten.

Dieses Phänomen hatte ich auch öfters, einzeln läufts und im gesamten Sketch nicht.
Nimm mal alles was mit Serial zu tun hat raus und probiere so.

Osder lass SerialMonitor drin und sag was es anzeigt:

Wie oft siehst du denn "Welcome, You shall pass" ?
und "1 = OFFEN / 0 = GESCHLOSSEN Status: "

Was sagt denn überhaupt der SerialMonitor?

skorpi08:
Also genau genommen ist es nicht egal ob am Anfang oder am ende der loop.

Wie meints du das, meinst du den delay() am Anfang oder am Ende, oder was meinst du mit nicht egal.

skorpi08:
Dieses Phänomen hatte ich auch öfters, einzeln läufts und im gesamten Sketch nicht.
Nimm mal alles was mit Serial zu tun hat raus und probiere so.

Hab grad mal jedes Serial rausgenommen, keine Veränderung.

michael_x:
Osder lass SerialMonitor drin und sag was es anzeigt:

Wie oft siehst du denn "Welcome, You shall pass" ?
und "1 = OFFEN / 0 = GESCHLOSSEN Status: "

Was sagt denn überhaupt der SerialMonitor?

Ich SerialMonitor jetzt wieder drin.
Wenn ich einmal die Zugangskarte ranhalte, rührst sich der Servo nicht, weil er ja sich ja schon in 0Grad zustand ist. Der SerialMonitor zeigt dann:

Access Control v3.3
MFRC522 Software Version: 0x88 (unknown)
-------------------
Master Card's UID
344B0BE
-------------------
Everything Ready
Waiting PICCs to be scanned
Scanned PICC's UID:
4925335
Welcome, You shall pass
1 = OFFEN / 0 = GESCHLOSSEN  Status: 1
Gradzahl Servo:  0

Wenn ich die Karte ein zweites mal ranhalte, stellt sich der Servo auf 180 und nach der Sekunde delay wieder auf 0. Im SerialMonitor wird dann folgendes angezeigt.

Access Control v3.3
MFRC522 Software Version: 0x88 (unknown)
-------------------
Master Card's UID
344B0BE
-------------------
Everything Ready
Waiting PICCs to be scanned
Scanned PICC's UID:
4925335
Welcome, You shall pass
1 = OFFEN / 0 = GESCHLOSSEN  Status: 1
Gradzahl Servo:  0
Scanned PICC's UID:
4925335
Welcome, You shall pass
1 = OFFEN / 0 = GESCHLOSSEN  Status: 0
Gradzahl Servo:  180

Was mir eben beim Einschalten noch aufgefallen ist, dass wenn ich den Arduino power der Servo auch einmal dreht, wie weit kann ich nicht sagen, aber könnten auch gut wieder 180 Grad sein, und dann wieder zuruck auf 0 Grad. Das ist doch in dem Sketch auch nicht gesagt oder? Wenn ich nur den Sketch (nov24a) also den nur mit den Button Programm, dann macht er das zumindest nicht.
Lg

Dafür sind Serial Ausgaben ja gedacht!

Hat er beim zweiten Mal die Karte zweimal gescannt, oder zumindest zweimal successRead=true geliefert.

Kannst du in deinem Testsketch auch erreichen, wenn du nur lang genug die Taste gedrückt hältst.

michael_x:
Dafür sind Serial Ausgaben ja gedacht!

Hat er beim zweiten Mal die Karte zweimal gescannt, oder zumindest zweimal successRead=true geliefert.

Kannst du in deinem Testsketch auch erreichen, wenn du nur lang genug die Taste gedrückt hältst.

Er hat die Karte nur einmal gescannt.

Was kann ich in meinem Test-Sketch auch erreichen?
Das sich der Servo auch beim einschalten schon dreht oder was meinst du?
Wenn ich die Taste langgenug drücke, also länger als der delay ist, geht er wieder zurück, dass soll er ja auch, aber doch noch nicht, wenn ich die Karte nur einmal kurz gegen den reader halte.
Lg

Er hat die Karte nur einmal gescannt.

Na ja, hieraus

Scanned PICC’s UID:
4925335
Welcome, You shall pass
1 = OFFEN / 0 = GESCHLOSSEN Status: 1
Gradzahl Servo: 0
<hier muss 1000 ms delay gewesen sein>
Scanned PICC’s UID:
4925335
Welcome, You shall pass
1 = OFFEN / 0 = GESCHLOSSEN Status: 0
Gradzahl Servo: 180

man kann leicht nachvollziehen, was passiert ist.
Nach dem delay(1000) kommt er nach GetID()

int getID() {
  // Getting ready for Reading PICCs
  if ( ! mfrc522.PICC_IsNewCardPresent()) { //If a new PICC placed to RFID reader continue
    return 0;
  }
  if ( ! mfrc522.PICC_ReadCardSerial()) {   //Since a PICC placed get Serial and continue
    return 0;
  }
  // There are Mifare PICCs which have 4 byte or 7 byte UID care if you use 7 byte PICC
  // I think we should assume every PICC as they have 4 byte UID
  // Until we support 7 byte PICCs
  Serial.println(F("Scanned PICC's UID:"));
  for (int i = 0; i < 4; i++) {  //
    readCard[i] = mfrc522.uid.uidByte[i];
    Serial.print(readCard[i], HEX);
  }
  Serial.println("");
  mfrc522.PICC_HaltA(); // Stop reading
  return 1;
}

mfrc522.PICC_IsNewCardPresent() liefert evtl. true auch wenn keine neue RFID erkannt wird ?
Hängen irgendwo mehrere Lese-Ergebnisse und werden erst später gemeldet ?

Genaueres kriegst du nur mit Tests, die direkt die library-Funktionen prüfen…

Ist denn Absicht, dass das Schloss auf/zu umschalten soll mit jedem RFID-Erkennen ?

[/quote]

michael_x:
Ist denn Absicht, dass das Schloss auf/zu umschalten soll mit jedem RFID-Erkennen ?

Ja das ist Absicht, weil man wenn man in der Wohnung ist ja nicht immer die Karte benutzen soll um mal kurz in der Hausflur zu gehen. Deswegen Karte ranhalten = Tür offen. Und wenn man später weg geht , nochmal ranhaltem = Tür wieder abgeschlossen.

Da wo du sagtest <hier muss 1000 ms delay gewesen sein>
Das stimmt , der ist ja dafür da die grüne lediglich noch eine Sekunde anzuhalten und später wenn der Knopf mit im Programm ist dafür zu sorgen, dass man wenn man den Knopf ausversehen zu lange drückt der Servolenkung nicht automatisch wieder zurück stellt.

Das was du sagst was leicht nachzuvollziehen ist , ist für mich nicht so leicht nachzuvollziehen.
Mir erklärt sich leider immer noch nicht warum der Servo in der gewünschten Stellung bleibt, nachdem man die RFID-Card gelesen hat.
Lg

Anstatt das Servo zu betätigen, toggle eine Statusvariable bei erfolgreichem Lesen eines Rfid Chips. Also da, wo write(180) steht. nimm beide servi.write raus. Und am Ende des Loops steuerst du den Servo entsprechend dem Zustand der Statusvariable an.

Weiss nicht ob das einen Unterschied macht. Er kommt ja mindestens zweimal durch loop, vermutlich noch häufiger, mit "gleiche Karte" und/oder "keine Karte" dazwischen.

Evtl. besser, erstmal rauszukriegen, warum die lib eine Sekunde nachdem die Karte schon weg ist, nochmal "neue Karte" meldet. Vielleicht die "noch gleiche Karte" und "keine Karte" Information der Library anzeigen. Und warum nur zwei mal und warum (vermutlich) reproduzierbar ?
Falls das zuviel Text wird, nur alle 100 ms RFID abfragen, oder mit LED signalisieren ?

ElEspanol:
Anstatt das Servo zu betätigen, toggle eine Statusvariable bei erfolgreichem Lesen eines Rfid Chips. Also da, wo write(180) steht. nimm beide servi.write raus. Und am Ende des Loops steuerst du den Servo entsprechend dem Zustand der Statusvariable an.

Danke hat gut geholfen, es funktioniert jetzt. Ich habe es erst gemacht, wie du sagtest, dann noch ein bisschen rumprobiert und letzten endes ist es fast wieder wie am Anfang bist auf die Tatsache, dass es komischerweise jetzt funktioniert. Und so schaut es jetzt aus.

///////////////////////////////////////// Main Loop ///////////////////////////////////
void loop () {

  do {
    successRead = getID();  // sets successRead to 1 when we get read from reader otherwise 0
    if (programMode) {
      cycleLeds();              // Program Mode cycles through RGB waiting to read a new card
    }
    else {
      normalModeOn();     // Normal mode, blue Power LED is on, all others are off
    }
  }
  while (!successRead);   //the program will not go further while you not get a successful read
  if (programMode) {
    if ( isMaster(readCard) ) { //If master card scanned again exit program mode
      Serial.println(F("Master Card Scanned"));
      Serial.println(F("Exiting Program Mode"));
      Serial.println(F("-----------------------------"));
      programMode = false;
      return;
    }
    else {
      if ( findID(readCard) ) { // If scanned card is known delete it
        Serial.println(F("I know this PICC, removing..."));
        deleteID(readCard);
        Serial.println("-----------------------------");
      }
      else {                    // If scanned card is not known add it
        Serial.println(F("I do not know this PICC, adding..."));
        writeID(readCard);
        Serial.println(F("-----------------------------"));
      }
    }
  }
  else {
    if ( isMaster(readCard) ) {   // If scanned card's ID matches Master Card's ID enter program mode
      programMode = true;
      Serial.println(F("Hello Master - Entered Program Mode"));
      int count = EEPROM.read(0);   // Read the first Byte of EEPROM that
      Serial.print(F("I have "));     // stores the number of ID's in EEPROM
      Serial.print(count);
      Serial.print(F(" record(s) on EEPROM"));
      Serial.println("");
      Serial.println(F("Scan a PICC to ADD or REMOVE"));
      Serial.println(F("-----------------------------"));
    }
    else {
      if ( findID(readCard) ) { // If not, see if the card is in the EEPROM
        Serial.println(F("Welcome, You shall pass"));
        granted();
      }
      else {      // If not, show that the ID was not valid
        Serial.println(F("You shall not pass"));
        denied();
      }
    }
  }
}

/////////////////////////////////////////  Access Granted    ///////////////////////////////////
void granted(){
  if(state == 1){
    digitalWrite(blueLed, LED_OFF);   // Turn off blue LED
    digitalWrite(redLed, LED_OFF);  // Turn off red LED
    digitalWrite(greenLed, LED_ON);   // Turn on green LED
    servoschloss.write(180);
    delay(1000);
    state = 0;
  }
  else{
    digitalWrite(blueLed, LED_OFF);   // Turn off blue LED
    digitalWrite(redLed, LED_OFF);  // Turn off red LED
    digitalWrite(greenLed, LED_ON);   // Turn on green LED
    servoschloss.write(0);
    delay(1000);
    state = 1;
  }
}

Das hat mir erstmal sehr weiter geholfen.
Nun stehe ich aber auch schon vor meinem nächsten Problem.
Wie bereits gesagt, würde ich Parallel zu dem RFID Reader auch noch einen Taster zur Aktivierung benutzen.

 if(digitalRead(button) == HIGH){
    Serial.println(F("Welcome, You shall pass by Button"));
    granted();
  }

Nur weiß ich momentan nicht, wo ich das in den Loop einfügen soll.
Lg und danke im Voraus

Hättest du eine Statusvariable eingefügt und den Servo in einer gesonderten Funktion damit angesteuert, müsstest du jetzt nur die Statusvariable toggeln.
Wenn du nun mit

 if(digitalRead(button) == HIGH){
    Serial.println(F("Welcome, You shall pass by Button"));
    granted();
  }

granted aufrufst, fehlt u.U. das korrekte state

P.S. Ich habe mich nicht durch den kompletten Code gegraben, sondern schiesse so ins Blaue anhand der Schnipsel.

ElEspanol:
Hättest du eine Statusvariable eingefügt und den Servo in einer gesonderten Funktion damit angesteuert, müsstest du jetzt nur die Statusvariable toggeln.
Wenn du nun mit

 if(digitalRead(button) == HIGH){

Serial.println(F("Welcome, You shall pass by Button"));
    granted();
  }


granted aufrufst, fehlt u.U. das korrekte state

P.S. Ich habe mich nicht durch den kompletten Code gegraben, sondern schiesse so ins Blaue anhand der Schnipsel.

ICh hab das schon wieder sö geändert, dass in granted() alles drin ist, was zum servo schalten nötig ist. Von daher müsste ich nur noch wissen, wo ich den button part reinhauen muss.
lg

wegen mir am Anfang von loop

ElEspanol:
wegen mir am Anfang von loop

Ich habe momentan am Anfang aber dort funktioniert es nicht, aber Servolenkung bewegt sich ganz kurz aber mehr auch nicht

Mach es mit einer Statusvariable und es wird funktionieren. und den Taster solltest du auch noch debouncen.