RFID Katzennapf

Guten Abend allerseits.
Ich habe die letzten Stunden damit verbracht.... einen Countdown in meinen bestehenden Sketch einzubauen.... ABSOLUT erfolglos. Aber fangen wir vorne an:

Ich will einen Fressnapf bauen, der per RFID geöffnet wird.
Die Katze hat also ein Halsband mit Tag an. Sobald sie an den Napf geht, öffnet sich eine Klappe und sie kann fressen.

Damit will ich verhindern dass meine Fette Katze, meiner kleinen Mietze alles wegfrisst :smiley:

Die Materialien habe ich. Ein grundsätzlicher Sketch steht schon....allerdings habe ich das Problem, dass ich gerne einen Countdown einfügen möchte. Aktuell mache ich es mit einem Delay, sodass die Klappe beim auslesen des Tags öffnet und anschließend nach "x" sekunden wieder schließt.
Wenn dann jedoch die Katze noch am fressen ist, schließt sich die Klappe vor Ihrer Nase....
Daher würde ich gerne einen Countdown einfügen, der Quasi bei auslesen des Tags startet. Sobald der Tag erneut (bzw immernoch) gelesen wird, soll der Countdown reseted werden, damit die Katze noch Zeit zum fressen hat.
Sollte der Tag dann irgendwann nicht mehr erkannt werden (weil die Katze satt ist) und der Countdown abgelaufen sein, soll die Klappe schließen.

Ich habe allerdings KEINE Ahnung, wie ich einen Countdown in Arduino schreibe, genauso wenig weiß ich, wie ich das auslesen des Tags mit dem Reseten in Verbindung bringe....
Ich habe mir von hier den Sketch eines "einfachen" Countdowns genommen und versucht in meinen Sketch einzufügen. Aber entweder schaffe ich es nicht in fehlerfrei zu kompilieren, oder aber er wird hochgeladen, funktioniert aber nicht.

Es wäre super wenn mir jemand sagen könnte, wie ich da nun einen Countdown einfügen soll. Ich weiß leider nicht mal wo, da ich mittlerweile soviel herumprobiert habe, dass ich mit meinen schleifen total durcheinander komme :smiley:

Anbei mal mein bisheriger Sketch (OHNE Countdown):

#include <SPI.h>
#include <MFRC522.h>
#include <Servo.h>
 
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.
Servo myServo; //define servo name
 
void setup() 
{
  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  mfrc522.PCD_SetAntennaGain(mfrc522.RxGain_max);
  myServo.attach(2); //servo pin
  myServo.write(0); //servo start position
 
  Serial.println("Put your card to the reader...");
  Serial.println();

}
void loop() 
{
  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial()) 
  {
    return;
  }
  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content= "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
     content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();
  while (content.substring(1) == "36 7A A3 79") //change here the UID of the card/cards that you want to give access
  {
    Serial.println("Authorized access");
    Serial.println();
    myServo.write(90);
 
    // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent()) 
  {
   
  }
      for (byte i = 0; i < mfrc522.uid.size; i++) 
  {
     Serial.print(mfrc522.uid.uidByte[i], HEX);
     content.concat(String(mfrc522.uid.uidByte[i]));
   
  }
    
    
    delay(50);
 
    }
    delay(2500);
    myServo.write(0);
  }

Dann lies doch den Tag immer wieder in der Loop aus und solange der gelesen wird bleibt die Klappe offen.

Ich hoffe, der Tag ist nah genug am Leser, sonst verhungert die Katze an der geschlossenen Klappe.

Guter Ansatz:

Damit will ich verhindern dass meine Fette Katze, meiner kleinen Mietze alles wegfrisst

Beißt sich meines Erachtens aber damit:

Sobald der Tag erneut (bzw immernoch) gelesen wird, soll der Countdown reseted werden, damit die Katze noch Zeit zum fressen hat.

Heißt, wenn die fette Katze einfach nur gierig ist wird sie einfach alles wegfuttern, Du willst das automatische Schließen ja offenbar verhindern.

Ergo: fette Katze bleibt fett, kleine Mietze hat Hunger, Zeit zum Basteln kannst Du anderweitig verbringen (z.B. kleine Mietze von Hand füttern).

Ich habe ihn so verstanden, dass nur die kleine Katze einen Chip hat und den Napf öffnen kann.
Die große muss dann hungern oder schiebt die kleine weg :wink:

Gruß Tommy

noiasca:
Klappe zu
kleine Katze mit richtigem Chip kommt zum geschlossenen Napf - Klappe auf
kleine Katze mit richtigem Chip am offenen Napf - Klappe bleibt auf
kleine Katze mit richtigem Chip nicht mehr vorm Napf - Zeitablauf - Klappe zu
dicke Katze mit falschem Chip / ohne Chip vorm Napf und Klappe ist zu - keine Statusänderung

Irgendwer würde nach einer Statemachine rufen.
:wink:

Das grenzt ja fast an Tierquälerrei, wenn die große Katze hungrig vor der geschlossen Klappe sitzt.

Und ich befürchte, beide Katzen verhungern, da der Tag nie dicht genug am Reader ankommt.
Aber dazu fehlt noch die Aussage des TO.

Nach meinen Erfahrungen mit den RFIDs macht isNewCardPresent() wirklich das was der Name sagt. Die 522er Lib speichert die ID. Solange die sich nicht ändert, gibt es kein "new".
Gruß Walter

Erstmal danke für die vielen Antworten. Auch wenn keine davon bisher meine Problematik aufgreift. aber wir arbeiten uns ran :smiley:

Schön zu sehen dass hier anscheined noch ein paar Katzenverrückte da sind, bzw Leute die dafür verständis haben :smiley:
Mit meiner dicken Katze reden bringt leider wenig...sie hat unheimlich große Kulleraugen und legt sich immer auf den Rücken wenn man mit ihr schimpft....nicht wirklich förderlich für ein ernstes Gespräch :smiley:

Noiasca hat die funktion schön zusammengefasst. So soll es funktionieren... hoffentlich....

HotSystems:
Dann lies doch den Tag immer wieder in der Loop aus und solange der gelesen wird bleibt die Klappe offen.

Ich hoffe, der Tag ist nah genug am Leser, sonst verhungert die Katze an der geschlossenen Klappe.

Naja die Idee hatte ich auch, aber sobald dann der Tag auch mal nur kurz zu weit vom Sensor weg kommt, was unweigerlich passieren wird während dem fressen, geht die Klappe direkt zu, obwohl die Katze direkt vor dem Napf steht.

Von der Reichweite her habe ich keine Bedenken. Der aktuelle Sketch baut zwar auf dem 522 auf. Ich habe allerdings schon einen RDM6300 geordert der auch die Tage ankommen sollte. Damit dürfte die Reichweite absolut kein Problem sein, wobei es selbst mit dem 522 machbar wäre.

Aber dennoch komme ich nicht wirklich dahinter, wie ich das ganze in einen Sketch packen soll. Ich stehe einfach auf dem Schlauch und weiß nicht wo ich welche Kommandos für den Countdown einfügen soll...
Zumal ich immer wieder das Problem habe, dass wenn ich den Countdown im void_setup "Voreinstelle" und später am Ende in der Loop einfügen will Fehlermeldungen bekomme weil anscheind nie die Schleife erreicht wird, die den Countdown starten soll. Bzw kann dieses Kommando keinen Bezug zu dem definierten Countdown schaffen.... Sehr eigenartig jedenfalls. Hab diese Sketches jedenfalls garnicht erst wieder abgespeichert. Daher kann ich sie leider hier nicht anhängen.

Bisher habe ich nur recht einfache Projekte gemacht die in der Regel nicht mehrere Loops benötigt haben (Z.b. einen Gasdetektor der immer wieder nur werte ausmisst und anzeigt).
Aber dieses Projekt habe ich mir doch deutlich einfacher vorgestellt....

Flori-the-Rock:
... einen Countdown in meinen bestehenden Sketch einzubauen...

Vermutlich hast Du einen unglücklichen Denkansatz: Du willst den Countdown starten, wenn die Katze weggeht. Ich fände es besser, ein retriggerbares Monoflop zu programmieren. Die Katze erreicht den Napf, Zeit startet und wird in jedem loop neu gesetzt, solange der Chip erkannt wird. Läuft die Zeit ab, geht die Klappe zu.

Wie schon geschrieben, nimm das Blink without delay Beispiel und verschiebe previousMillis = currentMillis; in eine Bedingung, wo der Chip abgefragt wird.

Aus der Bastelkiste:

const byte taster = 2;
const uint16_t maxUnterbrechung = 5000;
uint32_t zeit;
bool rfid;

void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  pinMode(taster, INPUT_PULLUP);  // LOW = Katze nicht am Napf
}

void loop()
{
  rfid = digitalRead(taster);
  if (rfid) zeit = millis();
  if (!rfid && (millis() - zeit > maxUnterbrechung))
  {
    digitalWrite(LED_BUILTIN, 0);  // Futterklappe zu
  } else
  {
    digitalWrite(LED_BUILTIN, 1);  // Futterklappe auf
  }
}

Mein Tipp:
Oben im Regal füttern.

Die Dürre hat kein Problem dahin zu kommen.
Die Dicke, muss erst dürrer werden...

Flori-the-Rock:
Bisher habe ich nur recht einfache Projekte gemacht die in der Regel nicht mehrere Loops benötigt haben (Z.b. einen Gasdetektor der immer wieder nur werte ausmisst und anzeigt).
Aber dieses Projekt habe ich mir doch deutlich einfacher vorgestellt....

Hast Du wirklich versucht, mehrere Loop-Funktionen anzulegen? Das geht schief.
Oder ist das nur ungünstig formuliert?

Gruß Tommy

Hi

Dein Grundproblem ist, daß Du Dich geistig schon in einer Lösung verrannt hast.
Dir wurde bereits geschrieben, daß Du keinesfalls einen Countdown startest, wenn 'die Dürre' nicht mehr erkannt wird und an Dessen Ende was zu erledigen.

Stell Dir vor, Du bist der RFID-Sensor:

  • ich sehe 'die Dürre', schaue auf die Uhr und merke mir DIESE Zeit
    .....
  • ich sehe 'die Dürre', schaue auf die Uhr und merke mir DIESE Zeit (dieses Mal ist's später geworden, also immer eine frische Zeit merken)
    ...
    wenn ich jetzt 'die Dürre' nicht mehr sehe, schaue ich auf meine Uhr und berechne, wie lange ich Sie nicht mehr gesehen habe.
    Wenn 'die Dürre' erneut erscheint, neue Zeit merken.
    Wenn die 'nicht mehr gesehen Zeit' Deiner Maximalzeit entspricht oder Diese überschreitet, schließt Du die Klappe

Alles in einer einzigen loop() - unter Zuhilfenahme von millis() - Sie kreierten soeben eine State-Maschine (springt je nach Bedingung zwischen verschiedenen Status (englisch state) hin und her.
Diese Bedingung kann das Erkennen des RFID-Chip sein, oder der Ablauf einer Differenz-Zeit, oder oder oder ...
Du kannst hiermit auch die Katzenklappe über die Nacht sperren - wobei der Arduino hier binnen Tage aus der Zeit hinauslaufen wird (hier wäre eine RTC anzuraten, nur Nebenbei).

MfG

Danke für eure Antworten.
Nach längerem überlegen und probieren kam ich zum entschluss mal komplett von vorne zu beginnen.
Hierbei nahm ich nun auf den RDM6300.
Ich habe nun quasi einen Countdown eingefügt bekommen der sogar funktioniert.
Die Klappe öffnet und schließt wie sie soll.
Jedoch funktioniert die Sache mit dem reset des countdowns eher bedingt.
Der Reset soll folgendes machen.
Es dauert etwa 10 sekunden, bis dieser Reset übernommen wird. Ich kann dafür im Sketch auch keinerlei Ursachen erkennen und habe schon alles mögliche (teils auch absolut sinnloses) probiert, aber ich bekomme das einfach nicht weg.

In der Praxis sieht das so aus (Zahlen stellen den aktuellen Timer dar):

10 Ich halte den Tag an den Empfänger, 10 sek. Countdown beginnt, klappe öffnet.
9
8
7 Ich halte den Tag erneut an den Empfänger, der Countdown SOLLTE nun wider auf 10 springen
6 ...tut er nicht....
5
4
3 ....langsam wird es eng....
2
1
0 Klappe schließt
-1
-2 Klappe öffnet wieder, Timer springt wieder auf 10
10.....

Das ganze lässt sich beliebig oft wiederholen.
Auch durch permanentes "taggen". Es dauert imm 8-10 Sekunden bis der Impuls umgesetzt wird.

Ich hoffe man versteht was das Problem ist....
Woran könnte das liegen?! Das Problem lässt sich natürich leicht umgehen indem ich den Timer höher stelle auf 30 Sekunden. Aber es wäre natürlich schön wenn es reibungslos läuft.

#include <SoftwareSerial.h>
#include <Servo.h>

SoftwareSerial ssrfid = SoftwareSerial(6,8);
int ssvalue;
int timer = 0;
Servo servo;

void setup() {
Serial.begin(9600);

ssrfid.begin(9600);
ssrfid.listen();

servo.attach(7); //servo pin
servo.write(0); //servo start position

Serial.println("INIT DONE");
}
void loop() {

delay(1000);
timer--;
Serial.println("Timer");
Serial.println(timer);
if (timer <= 0) {servo.write(0);}
if (timer > 0) {servo.write(90);}
if (ssrfid.available() > 0){

int ssvalue = ssrfid.read(); // read
if (ssvalue == -1) { // no data was read
return;
}
if (ssvalue == 2) { // RDM630/RDM6300 found a tag => tag incoming
servo.write(90); timer=30; Serial.println(timer);
}

}
}

Könnte es sein, der Servo klaut bei geöffneter Klappe dem RFID-Leser den Strom?

Tipp: +t in der IDE formatiert das Programm mit Einrückungen, macht es gemeinhin lesbarer.

Es ist löblich, zu prüfen, ob ein Tag erkannt wurde "if (ssvalue == 2) "

Es ist bedenklich nur alle 1 Sekunde ein Byte zu lesen.
Das ist ein Stock in den Speichen.

Denn der Leser sendet 14 Byte, wenn er ein Tag gefunden hat. (stimmt das?)
Das macht 14 Sekunden, bevor die nächste Aktion durchgeführt werden kann.

Also kann das mit deinen 10 Sekunden so nicht klappen.

Hi

Bitte vergiss delay()!
Zum Endprellen EINES Tasters mag Das ja noch ok sein (delay(20); ) - aber hier hältst Du in jedem loop()-Durchlauf das Programm komplett an.
In dieser Sekunde hast Du aber viel zu tun - Du musst prüfen, ob 'die Dürre' wieder erkannt wurde und ob Du Dir eine neue Start-Zeit (Mehrere schrieben bereits ... schau Dir millis(), den Nachtwächter, Blink_without_delay aus der IDE, ... an) merken musst.
Weiter musst Du quasi IMMER prüfen, ob die aktuelle Zeit minus die Startzeit >= Deiner Verweilzeit geworden ist.
DAS ist Dein Zeichen für 'Klappe zu'.

Bei Deinem Sketch wirst Du, wenn Du den Countdown auf 30 stellst feststellen, daß sich der Countdown erst nach 30 Sekunden 'resetten' lässt - Das könnte dieses Mal vll. nicht am delay() liegen, sondern an der längeren Abarbeitungszeit von 'servo(90);' statt von 'servo(0);'.
Wenn Du Das wirklich verifizieren willst, mit kürzeren Wartezeiten passiert das Gleiche, eben nach der kürzeren Wartezeit - Du kannst also auch 5 nehmen und Dich wundern, warum Du nur alle 5 Sekunden resetten kannst.
(30 dauert halt länger, da ist man Opa, bevor man mit Testen fertig ist)

Stricke den Code auf millis() um und prüfe, ob Servo und RFID überhaupt zusammen funktionieren.
Vll. kannst Du Servo auch für die RFID-Erkennung abschalten?

MfG

PS: Oha, Das mit 'jeweils nur ein Byte' hatte ich gar nicht gesehen :wink: