Countdown per RFID-Chip beenden

Hallo zusammen
Ich will eine Art Alarmanlage bauen, die durch einen PIR-Sensor (Bewegung) ausgelöst wird. Bevor aber das "Piepsen" beginnt, gibt es noch einen Countdown, der auf einer 8x8 LED Matrix von 9 auf 0 herunterzählt und am Ende ein trauriges Smiley anzeigt, und ein Buzzer mit dem Alarmton angeht. Bis hierhin funktioniert alles prima. Nun soll ich das Ganze aber mit einem RFID-Chip beenden können. Ich dachte an eine while-Funktion, die den Countdown so lange laufen lässt, bis ein Chip erkannt wurde. Wenn das mit dem while funktioniert, wie kann ich die Frage dauern "aktualisieren", ob ein Chip erkannt wurde, der es dann beendet. Ist das überhaupt möglich, während einer xyz() etwas ständig abfragen zu lassen? Microcontroller sind bekanntlich nicht sehr multitasking-freudig... Ach ja, wenn der Alarm "entschärft" worden ist, soll es ein Smiley anzeigen :slight_smile:
Ganz herzliche Grüsse
Dan

int DIN = 7;
int CS =  6;
int CLK = 5;
int buzzer_pin =3;
int PIR_motion_pin = 4;

int val = LOW;

#include <SPI.h>
#include <MFRC522.h>

#include <LedControl.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN);

byte neun[8] = {B00000000,B00011000,B00100100,B00100100,B00011100,B00000100,B00100100,B00011000}; 
byte acht[8] = {B00000000,B00011000,B00100100,B00100100,B00011000,B00100100,B00100100,B00011000}; 
byte sieben[8] = {B00000000,B00111100,B00100100,B00000100,B00001000,B00010000,B00010000,B00010000}; 
byte sechs[8] = {B00000000,B00011000,B00100100,B00100000,B00011000,B00100100,B00100100,B00011000}; 
byte funf[8] = {B00000000,B00111100,B00100000,B00100000,B00111000,B00000100,B00100100,B00011000}; 
byte vier[8] = {B00000000,B00001100,B00010100,B00100100,B00111100,B00000100,B00000100,B00000100}; 
byte drei[8] = {B00000000,B00011000,B00100100,B00000100,B00011000,B00000100,B00100100,B00011000}; 
byte zwei[8] = {B00000000,B00011000,B00100100,B00000100,B00001000,B00010000,B00100000,B00111100}; 
byte eins[8] = {B00000000,B00001000,B00011000,B00001000,B00001000,B00001000,B00001000,B00011100}; 
byte zero[8] = {B00000000,B00011000,B00100100,B00100100,B00100100,B00100100,B00100100,B00011000}; 
byte frown[8] = {0x3C,0x42,0xA5,0x81,0x99,0xA5,0x42,0x3C};
byte smile[8] = {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};

LedControl lc=LedControl(DIN,CLK,CS,0);

void setup(){
 lc.shutdown(0,false);
 lc.setIntensity(0,15);
 lc.clearDisplay(0);

 pinMode(PIR_motion_pin,INPUT);
 pinMode(buzzer_pin,OUTPUT);
 
 SPI.begin();
 mfrc522.PCD_Init();
}

void playTone(long duration, int freq) {
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
        digitalWrite(buzzer_pin,HIGH);
        delayMicroseconds(period / 2);
        digitalWrite(buzzer_pin, LOW);
        delayMicroseconds(period / 2);
        elapsed_time += (period);
    }
}

void countdown(){
  printByte(neun);
  delay(1000);
  printByte(acht);
  delay(1000);
  printByte(sieben);
  delay(1000);
  printByte(sechs);
  delay(1000);
  printByte(funf);
  delay(1000);
  printByte(vier);
  delay(1000);
  printByte(drei);
  delay(1000);
  printByte(zwei);
  delay(1000);
  printByte(eins);
  delay(1000);
  printByte(zero);
  delay(1000);
  printByte(frown);
  while(3<5){  
    playTone(300, 160);
    delay(150);
    printByte(frown);}
}

void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}

void loop() {
  val = digitalRead(PIR_motion_pin);      
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
        
        byte myid[4] ={0x86, 0x13, 0xDB, 0xA0};   //Deine id
        byte isok= 0;
        for (byte i = 0; i < mfrc522.uid.size; i++) {
          if (mfrc522.uid.uidByte[i]==myid[i]) {
             isok= isok+1;
          }
        }
     if (val == HIGH) {
      countdown();}
     else if (isok == 4) {
      printByte(smile);
      delay(2000);
      lc.clearDisplay(1);
     }
}

Du brauchst die While-Schleife nicht, wenn du alles in der Loop laufen lässt.

Poste deinen Sketch hier in Code-Tags und wir können weiter helfen.
Schaltfläche </> verwenden, oben links im Editor-Fenster.

danscho:
Ist das überhaupt möglich, während einer xyz() etwas ständig abfragen zu lassen? Microcontroller sind bekanntlich nicht sehr multitasking-freudig...

Ja, einfach nach jedem Countdown Schritt nachfragen ob in der Zwischenzeit eine RFID Karte erkannt worden ist, wenn nicht --> weiterzählen.

Poste bitte deinen Code dann geht alles viel einfacher.

Gruß Jan

Kleiner Denkfehler: der RFID sollte IMMER abgefragt werden - egal ob Alarm an oder NOCH nicht an....wenn du es doch innerhalb der 10 Sekunden nicht schaffst den aus der Tasche zu kramen geht der Alarm los. Der soll dann nicht mehr abschaltbar sein via RFID und pausenlos rumheulen? :wink:

AlphaRay:
Kleiner Denkfehler: der RFID sollte IMMER abgefragt werden - egal ob Alarm an oder NOCH nicht an....wenn du es doch innerhalb der 10 Sekunden nicht schaffst den aus der Tasche zu kramen geht der Alarm los. Der soll dann nicht mehr abschaltbar sein via RFID und pausenlos rumheulen? :wink:

Genau so soll es sein; wenn man es nicht entschärfen kann, soll es pausenlos rumheulen. Wie kann ich das anstellen, dass es IMMER abgefragt wird?
Grüsse Dan

danscho:
Genau so soll es sein; wenn man es nicht entschärfen kann, soll es pausenlos rumheulen. Wie kann ich das anstellen, dass es IMMER abgefragt wird?
Grüsse Dan

Wie ich schon schrieb, immer in der Loop laufen lassen.

HotSystems:
Wie ich schon schrieb, immer in der Loop laufen lassen.

Wie stellst du dir das vor? Code-mässig

danscho:
Wie stellst du dir das vor? Code-mässig

Z.B. machst du es mit Funktionen:

void loop() {
  readPIR();
  readRFID();
  setDisplay();
}

void readPIR() {

// hier deinen Code zum prüfen des PIR

}

void readRFID() {

// hier deinen Code zum prüfen des RFID

}

void setDisplay() {

// hier deinen Code zum schreiben des Display

}

Natürlich musst du die Funktionen untereinander verbinden. Das machst du z.B. mit globalen Variablen.

Auf keinen Fall darfst du delays einsetzen, so wie in deinem Sketch.
Die bremsen deinen Sketch und während des delays wartet der Controller aber führt keine deiner Aktionen aus.

Statt der delays verwendest du millis (Beispiel BlinkWithoutDelay in der IDE)

danscho:
... Wie kann ich das anstellen, dass es IMMER abgefragt wird?

Wenn Du mehrere Dinge gleichzeitig machen möchtest, musst Du auf jeden Fall auf delay() verzichten. Evtl. hilft das hier.

Gruß

Gregor

int DIN = 7;
int CS =  6;
int CLK = 5;
int buzzer_pin =3;
int PIR_motion_pin = 4;
int x = 9;
int rfid = false; 

unsigned long previousMillis = 0;
const long interval = 1000;

int val = LOW;
int val2 = 0; 

#include <SPI.h>
#include <MFRC522.h>

#include <LedControl.h>

#define SS_PIN 10
#define RST_PIN 9

MFRC522 mfrc522(SS_PIN, RST_PIN);

byte neun[8] = {B00000000,B00011000,B00100100,B00100100,B00011100,B00000100,B00100100,B00011000}; 
byte acht[8] = {B00000000,B00011000,B00100100,B00100100,B00011000,B00100100,B00100100,B00011000}; 
byte sieben[8] = {B00000000,B00111100,B00100100,B00000100,B00001000,B00010000,B00010000,B00010000}; 
byte sechs[8] = {B00000000,B00011000,B00100100,B00100000,B00011000,B00100100,B00100100,B00011000}; 
byte funf[8] = {B00000000,B00111100,B00100000,B00100000,B00111000,B00000100,B00100100,B00011000}; 
byte vier[8] = {B00000000,B00001100,B00010100,B00100100,B00111100,B00000100,B00000100,B00000100}; 
byte drei[8] = {B00000000,B00011000,B00100100,B00000100,B00011000,B00000100,B00100100,B00011000}; 
byte zwei[8] = {B00000000,B00011000,B00100100,B00000100,B00001000,B00010000,B00100000,B00111100}; 
byte eins[8] = {B00000000,B00001000,B00011000,B00001000,B00001000,B00001000,B00001000,B00011100}; 
byte zero[8] = {B00000000,B00011000,B00100100,B00100100,B00100100,B00100100,B00100100,B00011000}; 
byte alles[8] = {B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111,B11111111}; 
byte weg[8] = {B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000,B00000000}; 
byte frown[8] = {0x3C,0x42,0xA5,0x81,0x99,0xA5,0x42,0x3C};
byte smile[8] = {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};

LedControl lc=LedControl(DIN,CLK,CS,0);

void setup(){
 lc.shutdown(0,false);
 lc.setIntensity(0,15);
 lc.clearDisplay(0);

 pinMode(PIR_motion_pin,INPUT);
 pinMode(buzzer_pin,OUTPUT);
 
 SPI.begin();
 mfrc522.PCD_Init();
}

void playTone(long duration, int freq) {
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
        digitalWrite(buzzer_pin,HIGH);
        delayMicroseconds(period / 2);
        digitalWrite(buzzer_pin, LOW);
        delayMicroseconds(period / 2);
        elapsed_time += (period);
    }
}


void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}


void loop() {
  byte myid[4] ={0x86, 0x13, 0xDB, 0xA0};   //Deine id
  byte isok= 0;
  for (byte i = 0; i < mfrc522.uid.size; i++) {
    if (mfrc522.uid.uidByte[i]==myid[i]) {
      isok= isok+1;
    }
  }
  if (isok == 4) {rfid = true;} 
  else {rfid = false;}
  unsigned long currentMillis = millis();
  val = digitalRead(PIR_motion_pin);
  if (val == HIGH) {val2 = 1;}
  if (val2 == 1 && rfid == false) {

  if (currentMillis - previousMillis >= interval) {previousMillis = currentMillis;
    if (rfid == true) {printByte(smile);}
    if (x == 9) {printByte(neun);x=8;} 
      else if (x == 8) {printByte(acht); x=7;}
      else if (x == 7) {printByte(sieben);x=6;} 
      else if (x == 6) {printByte(sechs);x=5;}
      else if (x == 5) {printByte(funf);x=4;}
      else if (x == 4) {printByte(vier);x=3;}
      else if (x == 3) {printByte(drei);x=2;}
      else if (x == 2) {printByte(zwei);x=1;}
      else if (x == 1) {printByte(eins);x=0;}
      else if (x == 0) {printByte(zero);x=-1;}
      else if (x == -1) {printByte(frown);}
  }
}
}

Das Auslösen des Countdowns funktioniert problemlos. Aber er schaltet nicht ab, wenn ich den RFID-Chip an den Sensor halte! Sieht jemand den/ einen Fehler? Ich wäre euch sehr dankbar :slight_smile:

Ich sehe nicht, dass du innerhalb deiner Countdown-Routine den RFID abfragst, dann kann er auch nicht ausschalten.

Hast du einen Vorschlag wie ich das tun könnte? Also so, dass es immer abfägt, ob ein Signal reingekommen ist?

danscho:
Hast du einen Vorschlag wie ich das tun könnte? Also so, dass es immer abfägt, ob ein Signal reingekommen ist?

Wenn Du mehrere Dinge gleichzeitig machen möchtest, könnte das hier helfen. Und der folgende Abschnitt auch.

Gruß

Gregor

gregorss:
Wenn Du mehrere Dinge gleichzeitig machen möchtest, könnte das hier helfen. Und der folgende Abschnitt auch.

Gruß

Gregor

Das hab ich schon gelesen, komme aber nicht wirklich draus :confused: Hast du eine konkrete Idee? Ich wäre dir wirklich sehr dankbar :slight_smile:

P.S.: Bin neu in der Arduino-Szene

danscho:
... Hast du eine konkrete Idee? Ich wäre dir wirklich sehr dankbar :slight_smile:

Nein, sorry.

Es kommt im Grunde darauf an, die „Pausen-Denke“ zu ändern. Denke nicht mehr an Pausen, die eingelegt werden sollen, sondern an Zeitpunkte, zu denen etwas geschehen soll.

danscho:
P.S.: Bin neu in der Arduino-Szene

Dann hast Du ja vielleicht mit meinen anderen Weekendern Spaß.

Viel Erfolg!

Gregor

Nachtrag: agmue hat einmal erklärt, wie ein endlicher Automat funktioniert. Vielleicht kommst Du damit besser zurecht.

gregorss:
Es kommt im Grunde darauf an, die „Pausen-Denke“ zu ändern. Denke nicht mehr an Pausen, die eingelegt werden sollen, sondern an Zeitpunkte, zu denen etwas geschehen soll.

In Ordnung. Ich sage dem Arduino, er soll zum Zeitpunkt 0, nachdem der PIR-Sensor ausgelöst wurde, eine 9 anzeigen. Zum Zeitpunkt 1 dann eine 8, usw. In der Zwischenzeit befehle ich ihm nichts. Wie kann ich ihm sagen, dass er in dieser Zeit immer darauf achten muss, dass vielleicht ein Signal vom RFID-Sensor kommen könnte und dann ggf. etwas anderes tun muss? (Es muss nicht unbedingt RFID sein, von mir aus kann es auch ein anderes, zB ein einfacher Knopf sein.)
Grüsse Dan

Ist wirklich so kompliziert ?

Zwischen den einzelnen Zeitpunkten fragst du immer den Zustand des RFID ab.
Du must nur darauf achten, das alles schnell durchläuft, ohne delay.

danscho:
... In der Zwischenzeit befehle ich ihm nichts.

Das ist der springende Punkt. Du musst den Countdown-Ablauf so programmieren, dass während dessen Ablaufs immer wieder geguckt wird, ob ein Knopf gedrückt oder ein RFID-Ding erkannt wurde.

Ungefähr so:

...
bool countdownAusgeloest;
bool knopfGedruecktOderRFIDDingErkannt;
long int millisMerker;
...
void loop()
{ ...
  if ((countdownAusgeloest==true) & (knopfGedruecktOderRFIDDingErkannt==false))
  {
    if(millis()-millisMerker>1000)
    { aktualisiereAnzeige(); millisMerker=millis(); }
  }

  guckNachObKnopfGedruecktOderSo();
  ...
}

So läuft loop() ständig durch, aktualisiert die Anzeige und guckt nach, ob ein Knopf gedrückt wurde oder so.

Ich hoffe, das ist verständlich :slight_smile:

Gruß

Gregor

Vielen Dank an alle, die sich die Mühe machten, mir zu helfen :slight_smile: Es funktioniert jetzt! Den Code stelle ich hier rein, damit alle, die so etwas Ähnliches machen wollen, eine kleine Referenz haben. Verbesserungsvorschläge nehme ich selbstverständlich gerne entgegen.
Freundliche Grüsse Dan

/*Was macht dieses Programm? 
 *  Wird der Bewegungsmelder ausgelöst, fängt der Motor an zu drehen und der Countdown 
 *  auf der LED-Matrix beginnt, von 9 herunterzuzählen. Bei 0 zeigt es einen traurigen 
 *  Smiley an und der Buzzer macht einen Alarmton. Will man das verhindern, muss man 
 *  den richtigen RFID-Chip and den RFID-Sensor halten und schon hört der Countdown 
 *  auf herunterzuzählen, und der Motor zu drehen. Ein Smiley wird angezeigt. :) Um 
 *  es von Neuem starten zu lassen, muss der Reset-Knopf auf dem Board gedrückt werden.  
 * 
 * Pinbelegung für 
 *     -RFID-Sensor 
 *     -LED 8x8 Matrix 
 *     -Relais 
 *     -PIR-Sensor (Bewegungsmelder) 
 *     -Buzzer 
 *     
 *      -"Pinbeschreibung"--> Pinbelegung auf Board 
 *RFID-Sensor: 
 *      -"SDA"--> 10 
 *      -"SCK"--> 13 
 *      -"MOSI"--> 11
 *      -"MISO"--> 12 
 *      -"IRQ"--> X (nicht angeschlossen) 
 *      -"GND"--> GND 
 *      "RST"--> 9 
 *      -"3.3V"--> 3.3V 
 * 
 *LED 8x8 Matrix: 
 *      -"VCC"--> 5V 
 *      -"GND"--> GND 
 *      -"DIN"-> 7 
 *      -"CS"--> 6 
 *      -"CLK"--> 5 
 *      
 *Relais: 
 *      -"S"--> 2 
 *      -"+"--> 5V 
 *      -"-"--> GND 
 *      
 *PIR-Sensor: 
 *      -"VCC"--> 5V 
 *      -"OUT"--> 4 
 *      -"GND"--> GND 
 *      
 *Buzzer: 
 *      -"+"--> 3 
 *      -"-"--> GND  
 */

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9

bool rfid_erkannt = false; 
unsigned long previousMillis = 0;
const int interval = 1000; 
int x = 0; 

const int PIR_IN = 4;
bool PIR_ausgelost = false; 
int val = LOW; 


int DIN = 7;
int CS =  6;
int CLK = 5;
int buzzer_pin = 3;
int relais_pin = 2; 

#include <LedControl.h>

byte neun[8] = {B00000000,B00011000,B00100100,B00100100,B00011100,B00000100,B00100100,B00011000}; 
byte acht[8] = {B00000000,B00011000,B00100100,B00100100,B00011000,B00100100,B00100100,B00011000}; 
byte sieben[8] = {B00000000,B00111100,B00100100,B00000100,B00001000,B00010000,B00010000,B00010000}; 
byte sechs[8] = {B00000000,B00011000,B00100100,B00100000,B00011000,B00100100,B00100100,B00011000}; 
byte funf[8] = {B00000000,B00111100,B00100000,B00100000,B00111000,B00000100,B00100100,B00011000}; 
byte vier[8] = {B00000000,B00001100,B00010100,B00100100,B00111100,B00000100,B00000100,B00000100}; 
byte drei[8] = {B00000000,B00011000,B00100100,B00000100,B00011000,B00000100,B00100100,B00011000}; 
byte zwei[8] = {B00000000,B00011000,B00100100,B00000100,B00001000,B00010000,B00100000,B00111100}; 
byte eins[8] = {B00000000,B00001000,B00011000,B00001000,B00001000,B00001000,B00001000,B00011100}; 
byte frown[8] = {0x3C,0x42,0xA5,0x81,0x99,0xA5,0x42,0x3C};
byte smile[8] = {B00111100,B01000010,B10100101,B10000001,B10100101,B10011001,B01000010,B00111100};

LedControl lc=LedControl(DIN,CLK,CS,0);





MFRC522 mfrc522(SS_PIN, RST_PIN);

void setup() {
 lc.shutdown(0,false);
 lc.setIntensity(0,15);
 lc.clearDisplay(0);

 pinMode(buzzer_pin,OUTPUT);
  
  SPI.begin();
  mfrc522.PCD_Init();

  pinMode(PIR_IN, INPUT); 
  pinMode(relais_pin, OUTPUT); 
}





void playTone(long duration, int freq) {
    duration *= 1000;
    int period = (1.0 / freq) * 1000000;
    long elapsed_time = 0;
    while (elapsed_time < duration) {
        digitalWrite(buzzer_pin,HIGH);
        delayMicroseconds(period / 2);
        digitalWrite(buzzer_pin, LOW);
        delayMicroseconds(period / 2);
        elapsed_time += (period);
    }
}





void printByte(byte character [])
{
  int i = 0;
  for(i=0;i<8;i++)
  {
    lc.setRow(0,i,character[i]);
  }
}








void loop() {
  digitalWrite(buzzer_pin, LOW); 
  val = digitalRead(PIR_IN); 
  if (val == HIGH) {PIR_ausgelost = true;} 
  
  unsigned long currentMillis = millis(); 
  
  if (PIR_ausgelost == true) {
  if (currentMillis - previousMillis > interval && x == 0 && PIR_ausgelost) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(neun); x= 1; digitalWrite(relais_pin, HIGH);}}
    
  if (rfid_erkannt == true) {
    if (x == 30 || x == 0){rfid_erkannt=false;} 
    else if (x != 0) {x=20; printByte(smile); digitalWrite(relais_pin, LOW);} }
  
     
  if (currentMillis - previousMillis > interval && x == 1) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(acht); x= 2;}
    
  if (currentMillis - previousMillis > interval && x == 2) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(sieben); x= 3;}
          
  if (currentMillis - previousMillis > interval && x == 3) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(sechs); x= 4;}
  
  if (currentMillis - previousMillis > interval && x == 4) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(funf); x= 5;}
              
  if (currentMillis - previousMillis > interval && x == 5) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(vier); x= 6;}
 
  if (currentMillis - previousMillis > interval && x == 6) {
   previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(drei); x= 7;}
   
  if (currentMillis - previousMillis > interval && x == 7) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(zwei); x= 8;}
                   
  if (currentMillis - previousMillis > interval && x == 8) {
    previousMillis = currentMillis; digitalWrite(buzzer_pin, LOW); printByte(eins); x= 10;}
    
  if (currentMillis - previousMillis > interval && x == 10 or x == 30) {
    previousMillis = currentMillis;
    printByte(frown); 
    playTone(300, 160); delay(150); x = 30; 
  }
                      
  
  if ( ! mfrc522.PICC_IsNewCardPresent()) {
    return;
  }

  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) {
    return;
  }
        
        byte myid[4] ={0x86, 0x13, 0xDB, 0xA0};                 //ID des RFID-Chips, der der Richtige sein soll 
        byte isok= 0;
        for (byte i = 0; i < mfrc522.uid.size; i++) {
          if (mfrc522.uid.uidByte[i]==myid[i]) {
             isok= isok+1;
          }
        }
 
        if (isok==4){
          rfid_erkannt=true; 
          }
        
        
           else if (isok < 4){
            rfid_erkannt=false;
           }
}