bestimmter Sensor und/oder Hilfe gesucht

RFID hat aber trotzdem einen Nachteil, die Reichweite zwischen Sender/Empfänger und Tag.
Da musst du für deine Spur G Eisenbahn, schon eine gute Antenne kaufen.
Die üblichen 1cm Entfernung dürften da nicht ausreichen. :wink:

Diese packt max. 60cm Reichweite. sowas würde ich empfehlen. Zur not selbst bauen wenn sie zu teuer ist.
https://www.feig.de/produkte/identification/produkt/id-iscant310310/

Haha,
Dankeschön. Das ist für Platzierung in den Gleisen etwas groß.

Ich habe mich etwas in die 125khz-Tematk eingelesen und jetzt auch ein rdm6300-Modul hier zum testen.
Ich habe auch das hier im Forum gefunden
https://forum.arduino.cc/index.php?topic=145244.0
Im vierten Beitrag ist ein Demo-Sketch von "jurs".
Ich habe diesen hier nur leicht modifiziert um mein jetziges Problem darzustellen.

// RFID demo sketch by "jurs" for Arduino Forum Deutsch

// start text character
#define STX 2
// end text character
#define ETX 3

// buffer to hold the last code read from Serial
char rfidBufferLastRead[13];

boolean readRFID() 
{
  if (!Serial.available()) return(false); // nothing available to read
  char rfidBuffer[13];
  char c=0;
  int i=0;
  memset(rfidBuffer,0,sizeof(rfidBuffer)); // clear receive buffer
  delay(50); // wait for code to appear in the Serial input buffer
  while (Serial.available()&& c!=STX) // watch out for start of text character
    c=Serial.read();
  while (Serial.available()&& i<12 && c!=ETX) // watch out for end of text character
  {
    c=Serial.read();
    rfidBuffer[i] = c;
    i++;
  }
  if (i!=12) return(false); // less than 12 characters read from Serial
  if (Serial.available()) c=Serial.read();
  if (c!=ETX) return(false);
  strncpy(rfidBufferLastRead,rfidBuffer,sizeof(rfidBuffer)); // copy into global variable rfidBufferLastRead
  return(true); // if we reach this line, we have read 12 digits from Serial
}


void setup()
{
  Serial.begin(9600);
  Serial.println("waiting for RFID...");
}

void loop()
{
  if (readRFID())
  {
    if (strcmp(rfidBufferLastRead,"6C00679D1F89")==0)
        {
        Serial.println("lok 1");
        delay(3000);      //Hier eine zusätzliche Wartezeit
        }
    else if (strcmp(rfidBufferLastRead,"123456789012")==0)
      Serial.println("Hello Bill!");
    else if (strcmp(rfidBufferLastRead,"800C4C028042")==0)
      Serial.println("Hello Bob!");
    else 
    {
      Serial.print("Fuck off! ");  
      Serial.println(rfidBufferLastRead);
    }  
  }
}

Im loop-Bereich wird mein rfid-Tag erkannt und ich habe ein relay von 3 Sekunden eingefügt.
Wenn ich das Programm starte und Tag rund ein bis zwei Sekunden an die Antenne halte wird dieser erkannt. Der Text erscheint im Seriellen Monitor und nach drei Sekunden eben noch einmal ... und noch einmal ... und noch einmal. Bis das sieben oder acht mal erschienen ist. Das dauert so knapp 20 Sekunden.

Wenn ich statt des delay ein Relais ansteuerte, das zum Beispiel für eine Minute einen Stromfluss unterbrechen soll, wird das auch mehrmals ausgelöst.

Ich möchte gerne das Relais nur einmal auslösen und erst wenn der Tag wieder im Eingangsbereich ist ein weiteres mal.
Ich hoffe ich habe mich verständlich ausgedrückt.

Hoplost:
... Wenn ich statt des delay ein Relais ansteuerte ...

Was ist in diesem Zusammenhang ein Delay, wenn es kein Relais mit Tippfehler ist?!

Gruß

Gregor

Hallo Gregor,
Das war, von mir, schlecht dargestellt.

In dem geposteten Beispielcode nutze ich den delay-Befehl um es anschaulich darzustellen.

Auf meiner Modellbahn soll bei erkennen des richtigen rfid-Tag, also der richtigen Lok, nach einer Verzögerung die Stromzufuhr, für rund eine Minute, unterbrochen werden um ein Pendelbetrieb für eine andere Lok auszulösen. Im Beispielcode sähe das dann ungefähr so aus.

// RFID demo sketch by "jurs" for Arduino Forum Deutsch

// start text character
#define STX 2
// end text character
#define ETX 3

int relaisPin = 5;

// buffer to hold the last code read from Serial
char rfidBufferLastRead[13];

boolean readRFID()
{
  if (!Serial.available()) return(false); // nothing available to read
  char rfidBuffer[13];
  char c=0;
  int i=0;
  memset(rfidBuffer,0,sizeof(rfidBuffer)); // clear receive buffer
  delay(50); // wait for code to appear in the Serial input buffer
  while (Serial.available()&& c!=STX) // watch out for start of text character
    c=Serial.read();
  while (Serial.available()&& i<12 && c!=ETX) // watch out for end of text character
  {
    c=Serial.read();
    rfidBuffer[i] = c;
    i++;
  }
  if (i!=12) return(false); // less than 12 characters read from Serial
  if (Serial.available()) c=Serial.read();
  if (c!=ETX) return(false);
  strncpy(rfidBufferLastRead,rfidBuffer,sizeof(rfidBuffer)); // copy into global variable rfidBufferLastRead
  return(true); // if we reach this line, we have read 12 digits from Serial
}


void setup()
{
  Serial.begin(9600);
  Serial.println("waiting for RFID...");
}

void loop()
{
  if (readRFID())
  {
    if (strcmp(rfidBufferLastRead,"6C00679D1F89")==0)
        {
        Serial.println("lok 1");
        delay(3000);      //Hier eine zusätzliche Wartezeit bis das Relais auslöst
        digitalWrite(relaisPin, HIGH); // Relais am Pin 5 auslösen
        delay(60000); // eine Minute warten
        digitalWrite(relaisPin, LOW);
        }
    else if (strcmp(rfidBufferLastRead,"123456789012")==0)
      Serial.println("Hello Bill!");
    else if (strcmp(rfidBufferLastRead,"800C4C028042")==0)
      Serial.println("Hello Bob!");
    else
    {
      Serial.print("Fuck off! "); 
      Serial.println(rfidBufferLastRead);
    } 
  }
}

Auch hier wird das Relais aber mehrmals angesprochen.
--> Ich halte den Tag an in den Empfangsbereich. Ein bis Zwei Sekunden
--> Der Tag wird, in dieser Zeit, mehrmals erkannt -- z.B. acht mal.
--> das Relais wird acht mal hintereinander ausgelöst.

Ich möchte einen RFID-Tag-Aufkleber unter die Lok kleben und die Antenne ins Gleisbett legen. Die Lok überfährt dann die Antenne und der Tag wird erkannt und löst das Relais aus.
Ich kann nicht steuern, wie oft der Tag erkannt wird, möchte das Relais bei einer Überfahrt aber nur einmal auslösen.

Ich hoffe das war verständlicher
Gruß
Thilo

Ich habe den Eindruck, Du möchtest eine Schrittkette (= finite state machine = endlicher Automat) programmieren.

Hallo,

Das müsste ich erst einmal googeln :).
Da bin ich unsicher.
Eigentlich möchte ich nur erreichen das bei erkennen der lok das Relais nur einmal ausgelöst wird. Der Arduino scheint sich aber irgendwie zu merken wie oft er den Rfid-Tag hintereinander erkannt hat. So oft läuft er dann schön sein Programm ab.

Evtl. Besteht ja die Möglichkeit den Arduino nach auslösen des Relais auszuschalten und gleich wieder ein.

Gruß Thilo

Hoplost:
Das müsste ich erst einmal googeln :).

Im Forum könntest Du nach "agmue anleitung" suchen, da habe ich als Anfänger was für Anfänger geschrieben. Ich übernehme keine Garantie, daß es Dir hilft, aber einen Versuch wäre es wert und den Autor könntest Du fragen :wink:

Bitte beachte auch die dort gesammelten Links zu anderen Erklärungen.

Moin,

du schriebst, dass LEDs nicht gehen, weil das sichbare Licht nervt.

Nimm ne IR Led.
Das Licht siehst du nicht und die Lösung ist super einfach.

Lieben Gruß,
Chris

Hoplost:
Der Arduino scheint sich aber irgendwie zu merken wie oft er den Rfid-Tag hintereinander erkannt hat. So oft läuft er dann schön sein Programm ab.

Ja, im Prinzip ist das so. Die serielle Schnittstelle hat einen Puffer, und da liegen dann alle empfangenen Telegramme drin ( zumindest soviele, wie der Puffer fasst ). Durch deine delays können die aber nicht alle sofort gelesen werden. Nachdem das erste gelesen wurde, schaltest Du das Relais an, und dann macht der Arduino eine Minute lang nichts kann also den Empfangspuffer auch nicht leeren. Erst nach der Minute wird dann das nächste Telegramm aus dem Puffer gelesen und alles beginnt von vorn.

Fazit:
zum einen musst Du ohne delays programmieren, so dass der Puffer auch geleert werden kann, während das Relais angezogen ist.
Zum anderen darfst Du während das Relais angezogen ist, nicht auf weitere Telegramme reagieren.

Hi

Besonders der 2.te (also letzte) Hinweis ist der Knackpunkt.
RFID-Erkennen (IMMER)
Du erkennst keinen RFID-Tag ... dann machen wir auch Nichts!
Wir sind NICHT in der Wartezeit oder der Nachlaufzeit und Du erkennst einen der RFID-Tags Lok1, Bill oder Bob - Du merkst Dir die Zeit, daß Du das Relais AN hast und schaltest das Unterbrechungs-Relais an.
Das Relais ist AN und die Wartezeit um? Nein -> wir machen (wieder) Nichts (auch kein delay()!!!)
Das Relais ist AN und die Wartezeit um? Ja -> Du merkst Dir die zeit, daß wir in der Nachlaufzeit sind und schaltest das Relais wieder ab.
// hier wird der RFID-Tag wohl immer noch erkannt, die Lok steht ja noch auf dem Sender ...)
Wir sind in der Nachlaufzeit und die Wartezeit ist um? Nein -> Du ahnst Es ... Nichts wird gemacht
Wir sind in der Nachlaufzeit und die Wartezeit ist um? Ja -> Wir vergessen, daß wir in der Nachlaufzeit sind - ab jetzt werden wieder RFIDs ausgewertet.

Ungefähr so sollte Das klappen.

MfG

Hallo Thilo,
ich hab das mal in einen kleinen Sketch gegossen :wink: . Für den Anschluß des Rfid-Lesers habe ich SoftwareSerial verwendet, dann sind die Schnittstellen für den Leser und die für den seriellen Monitor sauber getrennt.
Für das einfache hantieren mit Zeitverzögerungen ( der EggTimer ) musst Du die MobaTools installieren. Das geht einfach über den Bibliotheksmanager ( im Suchfeld 'mobatools' eingeben ).

#include <MobaTools.h>
#include <SoftwareSerial.h>
// start text character
#define STX 2
// end text character
#define ETX 3
const byte rxPin = 8;       // hier wird der Rfid-Leser angeschlossen
const byte txPin = 9;
SoftwareSerial rfidSerial = SoftwareSerial( rxPin, txPin );

EggTimer delayTimer; // für Zeitverzögerungen

int relaisPin = 5;

// buffer to hold the last code read from Serial
char rfidValue[13];

boolean readRFID(char (&rfidBuf)[13])
{   // die Zeichen vom Rfid-Leser werden gelesen. Die Funktion muss im loop() ständig
    // aufgerufen werden, und schaut dann nach, ob Zeichen angekommen sind.
    // Sobald ein komplettes Telegramm empfangen wurde, ist der Funktionswert 'true', und
    // das Telegramm wird in den übergebenen Puffer kopiert.
    static byte rfidIx = 0; // Index im Empfangspuffer
    static char buf[13];    // interner Empfangspuffer
    char c;
    boolean fertig = false;
    while (rfidSerial.available()) { // Zeichen aus Puffer lesen
        c=rfidSerial.read();
        if ( c == STX ) {
            // Start einer Übertragung
            rfidIx = 0;
        } else if ( c == ETX ) {
            // Übertragungsende 
            if ( rfidIx == 12 ) {
                // komplettes Telegramm empfangen
                buf[12]=0;
                strcpy( rfidBuf,buf);
                fertig = true;
            }
        } else {
            // Zeichen in Puffer eintragen
            if ( rfidIx < 12 ) {
                buf[rfidIx++] = c;
            }
        }
    }
    return fertig;
}


void setup()
{
  Serial.begin(9600);
  rfidSerial.begin(9600);
  while(!Serial);
  Serial.println("waiting for RFID...");
}

enum state_t {WARTEN,VORLAUF,RELAIS};   // Die möglichen Zustände der Schrittkette
state_t zustand = WARTEN;               // aktueller Zustand der Schrittkette

void loop()
{
    boolean gotRfid; 
    gotRfid = readRFID(rfidValue); // Empfang vom Rfid-Leser ( bei jedem loop-Durchlauf aufrufen! )
    
    switch ( zustand ) {
      case WARTEN: //------ warten bis Rfid Tag erkannt ------------
        if (gotRfid) {
             if (strcmp(rfidValue,"0462D7E57723")==0) {
                Serial.println("lok 1");
                delayTimer.setTime(3000);      //Hier eine zusätzliche Wartezeit bis das Relais auslöst
                zustand = VORLAUF;      // zum nächsten Schritt weiterschalten
                }
            else if (strcmp(rfidValue,"123456789012")==0)
              Serial.println("Hello Bill!");
            else if (strcmp(rfidValue,"800C4C028042")==0)
              Serial.println("Hello Bob!");
            else
            {
              Serial.print("Fuck off! ");
              Serial.println(rfidValue);
            }
        }
        break;
      case VORLAUF: // warten bis Vorlaufzeit abgelaufen
        if ( !delayTimer.running() ) {
            digitalWrite(relaisPin, HIGH);
            Serial.println("Relais EIN");
            delayTimer.setTime(60000); // Relais 1 Minute einschalten
            zustand = RELAIS;      // zum nächsten Schritt weiterschalten
        }
        break;
      case RELAIS: // wenn Timer abgelaufen, Relais abschalten udn wieder von vorn
        if( !delayTimer.running() ) {
            digitalWrite(relaisPin, LOW);
            Serial.println("Relais AUS");
            zustand = WARTEN;
        }
    } // Ende der Schrittkette
}

Wie Du siehst, enthält der Code kein einziges delay mehr.

Hi

@microbahner - warum kein const byte bei der Pin-Definition? Schadet nicht, frisst kein Brot und der geneigte Anfänger lernt, wie's sein sollte.

Sonst eine saubere Umsetzung.
Anmerkung: Für mehrere parallele Verzögerungen braucht's hier dann mehrere EggTimer.
Hier sind die Verzögerungen hintereinander, also kommt man hier mit Einem aus.
Wenn man aber parallel dazu eine weitere State-Maschine laufen lassen will (was problemlos mit diesem Rezept möglich ist), dürfen sich diese beiden Verzögerungen nicht gegenseitig stören.

MfG

postmaster-ino:
warum kein const byte bei der Pin-Definition?

Bei von mir neu eingefügten Zeilen ist das ja so. Ok, bei den unveränderten Zeilen habe ich es nicht korrigiert - sonst erkennt Thilo seinen Sketch ja garnicht mehr wieder :wink: . Aber das kann er dann ja selbst machen.

postmaster-ino:
Für mehrere parallele Verzögerungen braucht's hier dann mehrere EggTimer.

Ja, wenn er den Sketch weiter aufbohren möchte ist das so. Aber solange der Speicher reicht :wink: kann er sich beliebig viele anlegen - braucht 5 Byte Ram/Instanz.

Hallo,

Ich bin beeindruckt. Meine Probleme werden schneller gelöst als ich sie vollumfänglich erkennen kann.

Das ist alles sehr interessant. Ich benötige wohl einen Augenblick das zu verstehen und umzusetzen.

Dankeschön!
Thilo

Auch wenn der TO sich scheinbar bereits auf RFID eingeschossen hat möchte ich hier noch eine andere Alternative einwerfen.

Statt einem Magneten, der einen Hallsensor oder einen Reed-switch schaltet, könnte man auch einfach eine LED mit 36KHz pulsen und in die Lok oder den Wagen einbauen.

Als Empfänger kann man dann einen TSOP1736, wie er für Infrarotfernbedienungen genutzt wird, in die Schiene bauen.

Jedes Mal, wenn die LED (also der Wagen oder die Lok in der diese eingebaut ist) über den Empfänger fährt, gibt dieser dann einen Impuls aus.

Dadurch kann man zwar nur einen Zug erkennen, aber so wie ich den Eröffnungspost lese, reicht das dem TO.

Moin,

Die Carrera Bahnen machen das mit unterschiedlichen Frequenzen je Auto. So kann man also auch per IR unterschiedliche Züge erkennen.

(Mein Post #21 wurde aber auch vollstädig ignoriert. So ist das wohl heutzutage)

Hallo Chris,

Entschuldige bitte, es war nicht mein Ziel Deinen Post nicht zu beachten.
Ich habe das gestern sogar noch nachgeschlagen. In der letzten zehn Tagen habe ich mich fast ausschließlich mit Rfid-Technik und entsprechend der Arduino-programmierung beschäftigt. Das mit den IR-LED mag gut funktionieren, Ich mag im Moment aber erst einmal weiterhin mit dem Rfid-Ansatz weiterverfolgen.

Für mich ist vieles neu und kostet entsprechend Zeit. Ich brauche oft ein wenig bis ich antworte.

Viele Grüße
Thilo

@ agmue, MicroBahner und postmaster-ino, es dauert noch ein wenig bis ich da durchgestiegen bin.

@ Frank501 im Moment erst einmal RFID. Ich hätte mir am Anfang auch einen Reed-kontakt bestellt. Der war aber leider nicht sensibel genug.

themanfrommoon:
(Mein Post #21 wurde aber auch vollstädig ignoriert. So ist das wohl heutzutage)

Ich habe Deinen Beitrag gelesen, aber nicht verstanden, zumindest nicht so, wie Du ihn gemeint hattest. Ich war gedanklich bei Lichtschranken. Sei also bitte gnädig mit dem TO und vorsichtig mit Verallgemeinerungen.

Mit einem kleinen µC wie dem ATtiny85 könnte man auch ein Bitmuster wie bei einer IR-Fernbedienung senden und dadurch verschiedene Züge unterscheiden. Ob das dann hinsichtlich der Bewegungsgeschwindigkeit reicht, kann ich aber nicht einschätzen, wäre zu testen.

Meine erste Wahl bleibt aber RFID.

Ich finde es eben völlig daneben überhaupt nicht auf einen Post zu reagieren. Denn kann man sich die Beteiligung an einer Lösungsfindung auch gleich schenken.
Es ging um mehrere verschiedene Varianten.
Lichtschranke geht nicht, weil verschiedene Züge unterschieden werden sollen.
Dann war die Idee nur einem Zug ein Licht einzubauen, dass durch einen Empfänger erkannt werden kann. Das war doof, weil der TO nicht möchte, das ein Licht an einem Zug leuchtet wo es normalerweise nicht hingehört. Wenn das das einzige Problem ist, nimmt man eine IR LED, die leuchtet nicht im sichtbaren Bereich -> Problem gelöst.
Wenn man nun mehrere Züge unterscheiden will, dann kann man die IR LEDs verschieden modulieren und so verschiedene Züge unterscheiden -> Problem gelöst
Zur Geschwindigkeit: So wird es bei Carrera Bahnen gemacht, die unterscheiden 6 Fahrzeuge voneinander mit einer 3mm IR LED. Mit der gleichen IR LED werden auch Weichen geschaltet und Zeiten gestoppt. Die Zeiten werden in Millisekunden ausgegeben. Das sollte für jeden Zug reichen. -> Problem gelöst
Ich finde RFID auch gut, ist aber wesentlich aufwendiger und baut vor allem auch sehr viel größer.
Wenn man nun die verschiedenen Ideen mal gegenüberstellt kann man sie auch gegeneinander abwägen und sich für die eine oder andere Lösung entscheiden.

Hallo Chris,
Ich verstehe Deinen Ansatz, nichtsdestotrotz habe ich auch geschrieben mich erst einmal in die RFID-Thematik einzulesen. Nebenbei habe ich es mit Reed-Schaltern versucht. Hinzu kommt einen endlichen Automaten zu verstehen. Im Moment bin ich damit ganztags ausgelastet. Im meinem sonstigem Alltag habe ich nichts mit Elektronik, Elektrotechnik oder programmieren zu tun.
Die IR-LED-Thematik interessiert mich aber auch und steht auch auf meiner Liste. Ich denke ich versuche das als nächstes. Dann kann ich auch vergleichen.
Ich danke Dir für Dein teilnehmen hier im Thema und hoffe Du kannst meine Entschuldigung im Beitrag #30 annehmen.
Viele Grüße
Thilo