Automatischer Fressnapf - brauche Hilfe!

Hallo,
zum Projekt.

Ich habe 2 Katzen, die eine frisst der anderen aber alles weg.
Daher will ich einen Fressnapf bauen, der mittels RFID eine Klappe (über Servo) am Katzennapf öffnet.
Solange dir Katze mit dem RFID Tag davor steht, soll die Klappe offen bleiben, sobald sie weg geht dann logischerweise schließen.

Grundsätzlich funktioniert auch bisher alles. Allerdings weiß ich nicht, welchen Befehl ich verwende, damit die Klappe offen bleibt solange der Tag in der Nähe ist.

Momentan habe ich den Sketch so geschrieben, dass der Servo um 90° öffnet, direkt danach wieder schließt.
Mit einem Delay kann ich natürlich beliebig verändern wie lange die 90° geöfnet bleiben, aber es soll ja so lange offen bleiben wie der Tag am Sensor ist.

Hier mal der Code. Ich hoffe ihr könnt mir auf die Sprünge helfen!

EDIT:

Habe jetzt einen etwas anderen Code verwendet. Leider funktioniert die While schleife nicht so wie sie soll… der Servo beginnt immer wieder zurück zu fahren, bis er dann merkt, dass er noch offen bleiben soll :-/ Ich kann das zwar mit Delays beherrschbar machen, perfekt ist es jedoch nicht.x

#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);
  }

versuch es mal so

    if(code == (unsigned long) 0x367AA379)
    {
     myservo.write(90);              // tell servo to go to position 90°
    }
    else myservo.write(0);          // tell servo to go to position 0°

Hi

Wenn das Servo dauern 'unter Strom' ist, kannst Du auch nur die gewünschte Endposition übertragen.
Ich sehe aber nicht, wo Du das Servo wieder zu fährst.

Zu Deinem Problem:
Du musst schauen, ob der Tag 'JETZT' gefunden wird - dann einen Countdown mit 10 Sekunden starten (Zählerwert=10).
Wenn Klappe==ZU && Countdown>0 --> Servo auf AUF
Wenn Klappe==AUF && Countdown==0 --> Servo auf ZU

Jede Sekunde ziehst Du 1 ab, bei Null schließt Du die Klappe.
Allerdings, jedes Mal, wenn der TAG gesehen wird, wird der Countdown erneut auf 10 gesetzt und somit wird die Klappe (noch lange nicht) geschlossen,

Das 'AUF' und 'ZU' musst Du Dir natürlich im Programm merken.
Bei der Initialisierung das Servo gezielt in eine Position verfahren - also entweder beim Einschalten Servo auf AUF und Countdown auf 10, oder ZU und Null.

(würde AUF und 10 nehmen, da macht die Klappe direkt was beim Einstecken ... man ist ja Spielkind)

MfG

PS: Die 90 müssen nicht unbedingt Grad sein anmerk

ardubu : Die If Funktion wie du sie nennst wird zu dem gleichen Problem führen wie ich es aktuell habe. Hatte es auch schon mit IF probiert...

Ino:

Dein Vorschlag ist quasi genau das was ich gesucht habe!!! Vielen Dank schonmal dafür!
Ich bin allerdings blutiger Anfänger und muss mir jetzt erst mal lange den Kopf zerbrechen um das um zu setzen.
Vor allem, weil ich nicht den eindeutigen befehl kenne, welcher das auslesen des Tags veranlasst... :confused:

Hi

Naja - Versuch macht Kluch (Versuch macht klug)

Diese Zeile:
if ( ! mfrc522.PICC_ReadCardSerial())
scheint mir was mit dem (NICHT) Auslesen des Tag zu tun zu haben.

Solange KEINE Karte gefunden wird, wird diese IF ausgeführt - RETURN beendet diese 'Runde in der loop' direkt, womit wir die loop direkt erneut starten und wieder hier ankommen.

Wenn eine Karte gefunden wurde, kommen wir hinter der IF an, wo der TAG, bzw. Dessen Nummer, ausgegeben wird:

Dort wird eine Karte ausgewählt, wenn erfolgreich, geht's weiter, sonst wird 'diese Runde der loop' erneut beendet.

Dahinter angekommen werden die Einzel-Bytes ausgegeben und in einem String 'zusammen geklebt' (müsste zumindest dieses content.concat bedeuten (bin halt auch kein Fachmensch in C++).

Darunter wird verglichen, ob diese Karte berechtigt ist und dann das Servo angesteuert.

Dahinter prüfst Du sogar erneut, ob eine neue Karte gefunden wurde und bastelst die Karten-ID zusammen, im Grunde so, wie ich Das auch machen würde.
Nur: Bei EINER Fehl-Lesung verlässt Du die While-Schleife, Die die Klappe oben hält.

Mein Weg wäre:

  • per IF prüfen, ob die Karte berechtigt ist
  • ein Flag setzen (in diesem Fall eine Variable auf 1 setzen oder auf die Nummer der Karte, Die gefunden wurde (bei 12 möglichen Katzen dann vll. die 'Karte 8', somit die 8 in diese Variable.
  • Einen Zähler (= Variable, BYTE reicht hier dicke) auf 10 setzen
  • Einen Merker (LONG), Der Sich den aktuellen millis()-Wert ... äh ... merkt
  • das Servo auf AUF fahren
  • JETZT kommt die WHILE-Schleife, aber mit der Prüfung, ob der Zähler >0 ist
  • innerhalb der WHILE-Schleife wird ununterbrochen nach einer neuen Karte gesucht und die ID zusammen gebastelt
  • nach jedem erfolgreichem Bastel-Versuch wird die aktuell erkannte ID mit
    -- a - den erlaubten IDs verglichen (wenn Klappe offen, darf JEDE Katze weiter fressen)
    -- b - der auslösenden ID verglichen (nur die auslösende Katze darf fressen, andere Kartennummern werden hier ignoriert)
  • wenn der Vergleich erfolgreich war, wird der Countdown (Zähler) auf 10 gesetzt und der Merker auf millis(); gesetzt
  • wenn if (millis()-Zähler>=1000){ Zähler--;} Das zählt eine Sekunde runter, wenn die letzte Sekunde keine gültige Karte gefunden wurde
  • hier endet die While-Schleife - solange eine gültige Karte gefunden wird (binnen 10 Sekunden), wird der Countdown erneut gestartet. Erst nach 10 Sekunden ohne Erkennung, geht's dahinter weiter
    -Klappe auf 0 absenken (das Servo fährt genau so schnell zu, wie auf!!)
    Wenn hier eine 'smoothe' Bewegung gewünscht ist, kann man hier das Servo auch 'runterzählen' und jedes Mal ein paar ms warten - aber NICHT mit Delay, sondern mit der millis()-Variante, da man so 'in der Zwischenzeit' prüfen kann, ob sich eine bekannte Katze am Napf befindet - vll. müssen wir ja direkt wieder auf machen.

Wenn wir hier beim Absenken bereits eine berechtigte Katze erkennen, direkt zu 'Klappe AUF' (mit Setzen des Countdown ect.pp.)
Wenn nicht, ist die Klappe zu und wir prüfen 'in jeder Runde der loop' auf einen gültigen RFID-Tag.

So, nun ist Es wieder an Dir, Das in einen halbwegs funktionierenden Code zu gießen.
Du hast ja in dem Code-Beispiel so ziemlich Alles drin, was ich hier auch verwendet habe.
Zu millis() schaust Du am Besten hier:
Blink without Delay

Hoffe, ich habe Dich jetzt nicht zu sehr vor den Kopf gestoßen - in Deinem Anfangs-Sketch ist wirklich schon soweit Alles drin - Es will nur noch richtig kombiniert werden.
Du musst 'nur' erkennen, was welcher Block/welche Zeile für einen Sinn hat und diese 'Sinne' in die richtige Reihenfolge bringen.

Wenn Du zuerst eine Art Ablauf-Aufzählung machst?
10 Scanne Karten
15 ohne Erfolg: Abbruch
20 Baue Karten-ID auf
30 Prüfe gefundene ID mit erlaubten IDs
40 ohne Erfolg Abbruch
...

Wenn Du darin mehrere Stellen hast, wo gleiche Blöcke hintereinander stehen, kann man Diese 'ausgliedern' - Da kommen wir aber erst zu, wenn das Grundgerüst die Katzen auch fressen lässt.

MfG