Mai 2020, Hurra es geht schonwieder weiter mit der Gleisbesetztanzeigerei. Ich wußte gar nicht mehr, daß ich noch LDRs im Bastelkisterl hab. Das passiert normalerweise nur dem Weib, wenns irgendwelches Gwamst aus ihrem schwarzen Loch (a.k.a. Kleider Kasten) hervorzaubert und meint: "Da schau her, ich wußte gar nicht, daß ich das hab".
Naja jedenfalls hab ich mich über 3 wundervolle, nagelneue LDRs gefreut und gleich mal was zusammengebastelt. Auf dem Sackl ist nur A9060 draufgestanden, das exakte Modell kann ich nicht mehr sagen.
Für die Unwissenden, Light Dependent Resistor oder auch Fotowiderstand. Näheres siehe https://de.wikipedia.org/wiki/Fotowiderstand
Hier die Schaltung, ähnlich zur IR Lichtschranke, nur halt ohne Sender. Der Sender ist quasi das Umgebungslicht. Habs spaßhalber mit zwei LDRs aufgebaut. Der LDR fungiert mit einem 100k Widerstand als Spannungsteiler und je nach Lichteinfall wird die Spannung von einem Analogport des Arduino gemessen. Die AnzeigeLEDs mit je 1k Vorwiderstand sind eh schon alter Hut.
Das Arduino Modell ist relativ blunzn, ich hab einen Nano genommen, aber auch Uno und dergleichen sind ok. Für eine Betriebsspannung von 3,3V (z.B. Due) müßt ma halt die Vorwiderstände der AnzeigeLEDs anpassen, fürn LDR- Spannungsteiler bleibt sichs wurscht.
Auch der Sketch ist relativ ähnlich dem von der IR Lichtschranke. Mit der genialen Erweiterung der Autokalibrier- Funktion. In der Setup Routine wird einfach der aktuelle Lichtwert gemessen und als Referenz- bzw. Schwellwert herangezogen.
/* LDR track occupancy detector - for track occupied signal for a model railway provided from www.kraweuschuasta.at without any warranty or license 2020 for personal use only Array used for more LDRs, LOW Signal = Active One Set per Track necessary (1x LDR Analogue Input, 2x indicator LED Digital Output) LDR autocalibration feature = while setup routine LDR average is calculaked and used as Threshold If ambient light is changed heavily it might be necessary to reset Arduino to force new LDR autocalibration. tested successfully on NANO (5V operating voltage) Schematic (example with 2 Sensors for 2 Tracks) ======================== Light Dependent Resistor (Analog input!) VCC----100k----LDR0-------GND | Arduino (A2) VCC----100k----LDR1-------GND | Arduino (A3) INDICATOR LEDs VCC----1k----red LED-------(Arduino (2) VCC----1k----green LED-----(Arduino (3) VCC----1k----red LED-------(Arduino (4) VCC----1k----green LED-----(Arduino (5) Schematic End =========================================================== */ // ================ INIT section starts here ========================== byte Red_Led[] = {2, 4}; //Red indicator LED Array byte GreenLed[] = {3, 5}; //Green indicator LED Array byte LDR_IN_Pin[] = {A2, A3}; //LDR ANALOGUE input Array !!! int Indicator_interval[] = {1000, 1000}; //interval in milliseconds that indicator LEDs are on (can be set for each Sensor Set red/green) long lngserial_display_interval = 500; //interval in milliseconds for Serial Monitor output (parametizing and debugging only) // ================ INIT section END ================================== byte i; //Counter variable, internal byte avg_counter; //Counter variable for average value check, internal int LDR_Invalue[(sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0]))]; //Array for Sensor values long lastmillis4serialprintln; //variable to keep timestamp for Serial monitor (delay() replacement) long LastMillis[(sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0]))]; //Array to keep timestamp for indicator duration (delay() replacement) int Triggervalue[(sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0]))]; //Triggervalue for LDR - occupied or not int intIRtotal, intLDRaverage = 0; //sum for average calculation for triggervalue, internal void setup() { Serial.begin(9600); Serial.println("Arr_Size = " + String((sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0])))); //Debug output Serial.println("Setup started."); for (byte i = 0; i < (sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0])); i++) { //Loop for declaring input/output + test Indicator LEDs //every led set is switched on for 500ms pinMode(Red_Led[i], OUTPUT); pinMode(GreenLed[i], OUTPUT); pinMode(LDR_IN_Pin[i], INPUT); digitalWrite(Red_Led[i], LOW); digitalWrite(GreenLed[i], LOW); Serial.println("LED Test started for Led " + String(i)); delay (500); } for (byte i = 0; i < (sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0])); i++) { //set all Indicator LEDs to off digitalWrite(Red_Led[i], HIGH); digitalWrite(GreenLed[i], HIGH); intIRtotal = 0; // get average value for LDR (100 iterations) for (avg_counter = 0; avg_counter <= 100; avg_counter++) { LDR_Invalue[i] = analogRead(LDR_IN_Pin[i]); intIRtotal = intIRtotal + LDR_Invalue[i]; intLDRaverage = (intIRtotal / avg_counter); } Serial.println("average for Sensor " + String(i) + " " + String(intLDRaverage)); intLDRaverage = intLDRaverage + 10; // set Trigger value = average + 10 Serial.println("Threshold for Sensor " + String(i) + " set to " + String(intLDRaverage)); Triggervalue[i] = intLDRaverage; LastMillis[i] = millis(); // update last millis for correct time calculations } Serial.println("Setup done."); } void loop() { if (lastmillis4serialprintln > millis() ) { // if millis() is restarted - re-set lastmillis timestamp lastmillis4serialprintln = millis(); for (byte i = 0; i < (sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0])); i++) { LastMillis[i] = millis(); } } for (byte i = 0; i < (sizeof(LDR_IN_Pin) / sizeof(LDR_IN_Pin[0])); i++) { // loop thru Array for every LDR LDR_Invalue[i] = analogRead(LDR_IN_Pin[i]); // read values from Sensor into Array if (millis() - lastmillis4serialprintln >= lngserial_display_interval) { // check duration and write Value to Serial Monitor Serial.println("LDR " + String(i) + " Value: " + String(LDR_Invalue[i])); lastmillis4serialprintln = millis(); // re-set last timestamp memory } if (LDR_Invalue[i] > Triggervalue[i] ) { // LDR is triggered? Serial.println("Triggered -- Sensor " + String(i)); digitalWrite(Red_Led[i], LOW); // Indicator RedLeds are switched on digitalWrite(GreenLed[i], HIGH); // Indicator GreenLeds are switched off } else { // if not (no Train on Track) if ((LastMillis[i] + Indicator_interval[i]) <= (millis())) { digitalWrite(Red_Led[i], HIGH); // Indicator RedLeds are switched off digitalWrite(GreenLed[i], LOW); // Indicator GreenLeds are switched on LastMillis[i] = millis(); // re-set last timestamp memory } } } }
Der Sketch ist wieder unter Verwendung von Arrays aufgebaut, damit mans recht einfach erweitern kann. Einfach in die relevanten Arrays die hinzugekommenen LED Ports eintragen, neu kompilieren & auf den Arduino schießen.
Und hier ist die Teststrecke. Ich hatte leider nicht die Zeit, Hill Valley maßstäblich dazu aufzubauen und anzumalen, tut mir leid.
Die LDRs passen bei H0 super über eine Schwelle, ohne Lokomotiven zu behindern, beim fliegenden Aufbau stehens bissl auf, bei einer fixen Anlage müsste mans ankleben.
Pauline gibt uns wieder die Ehre und fährt testhalber über die LDRs.
Weil die Pauline so hübsch ist, hier ein Video vom Test. Und natürlich, damit man die Gleisbesetztmeldung besser sehen kann.
Gleisbelegtanzeige mit LDR ist gar keine schlechte Alternative, allerdings habe ich sie nicht bei grober Finsternis getestet.
Vorteile: Einfacher Aufbau, kleine Größe, geringer Preis
Nachteile: Funktioniert nicht im Dunklen, bei Änderung der Lichtverhältnisse (z.B. Licht einschalten) muss der Arduino neu kalibriert bzw. resettet werden
Zurück auf die Eisenbahnelektronikseite