RailFX-Waldarbeiten Modul

Dieses Modul des RailFX-Systems ist vom Fallender-Baum-Set von NOCH inspiriert, zu dem ich eine Anfrage bekommen hatte. Hier nun also gleich eine ganze Einsatzstelle. Es hat folgende Funktionen: Fallender Baum Ladekran (Links, Rechts, Aufnehmen, Ablassen) drei Paar blinkende Warnleuchten Fahrzeugbeleuchtung Einsatzstellen-Beleuchtung Da es nicht möglich ist, das Soundmodul DFPlayer gleichzeitig mit Servomotoren zu verwenden, gibt es auf diesem Modul kein leider keine Soundausgabe. Allerdings kann dafür das unabhängige RailFX-Soundmodul (gerade in Arbeit) nutzen. Schaltplan D10: Servo »Fallender Baum« D11: Kranservo Drehung D12: Kranservo Winde D2 – D7: LEDs für Blinklichter D8, D9: Fahrzeugbeleuchtung A1 – A3: Arbeitslicht (die analogen Inputs werden als digitale Outputs verwendet) Achtung: Am Pin A4 wird das Control-Signal des RailFX Control-Moduls angelegt. Es steuert die Tageszeit und ist zwingend erforderlich. Bauteile 1x LED-Set 3x Servo-Motoren (Es kann Sinn ergeben, bessere Servos zu kaufen, weil diese relativ häufig auslösen müssen.) Einstellungen im Code Auch dieses Modul bietet eine Reihe an Einstellmöglichkeiten. Zum einen sollten alle Zielzustände der Servos eingestellt werden. Es gibt für jeden der drei Servos jeweils zwei Zustände, z.B. baumLiegt und baumSteht. Dabei handelt es sich um die Gradzahl, auf die sich der Servo einstellen soll. Dabei ist zu beachten, dass der Bereich zwischen 0 und 180 liegen sollte, obwohl Servos oft nicht diese Extremwerte erreichen können. Deshalb müssen diese Grenzen ausprobiert werden. Ich schlage vor, sich vorsichtig an diese Grenzen heranzutasten, z.B. 30 – 150, 20 – 160 … Des Weiteren muss baumLiegt größer sein als baumSteht, kranRechts größer als kranLinks und windeOben größer als windeUnten. Der fallende Baum wird per Zufall ausgelöst. Je kleiner die Variable fallenderBaumZufall ist, desto öfter fällt der Baum um. Der Beladekran vollzieht eine Animation, die zeitgesteuert abläuft. Die Dauer der einzelnen Phasen lässt ich über das Array kranTimeouts bestimmen. Hier werden die Zeiten in Millisekunden angegeben (1000ms=1s). Die Animation hat folgende Phasen: Warten (Wahrscheinlichkeit) Aufnehmen Warten Drehen Warten Ablassen Warten (Wahrscheinlichkeit) Aufnehmen Warten Drehen Warten Ablassen Position 0 und 6 (Die erste Stelle im Array ist immer 0) legen eine Wahrscheinlichkeit fest, mit der der Kran weiter arbeitet: je höher, desto seltener wird die nächste Animationsphase ausgeführt. Dadurch entsteht ein zufälligeres Arbeitsbild. Die Drehgeschwindigkeit der beiden Kranservos (Winde und Drehung) lassen sich über die Variablen kranWindeSpeedund kranDrehungSpeed einstellen. Je größer der Wert, desto langsamer bewegen sich die Servos. Es gibt drei Warnlicht-Paare, die unterschiedlich schnell blinken. Die Frequenz kann man über das Array warnlichtTimer einstellen. Eine leichte Varianz in der Frequenz erzeugt ein realistischeres Blinkbild. /* ***** ***** Einstellungen ***** ***** ***** ***** */ int baumLiegt = 120; // Servoposition des liegenden Baumes int baumSteht = 30; // Servoposition des stehenden Baumes long fallenderBaumZufall = 200000; // je kleiner der Wert, desto öfter fällt der Baum /* Legt die Wartezeiten der Kranabfolge fest: warten (Wahrscheinlichkeit), aufnehmen, warten, drehen, warten, ablassen, warten (Wahrscheinlichkeit), aufnehmen, warten, drehen, warten, ablassen -&amp;gt; Position 0 und 6 legen eine Wahrscheinlichkeit fest, mit der der Kran weiter arbeitet: je höher, desto seltener */ int kranTimeouts[] = {1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000}; int kranWindeSpeed = 10; // Geschwindigkeit der Kranwinde (größer = langsamer) int kranDrehungSpeed = 10; // Geschwindigkeit der Krandrehung (größer = langsamer) int windeOben = 120; // Servoposition der eingezogenen Kranwinde int windeUnten = 60; // Servoposition der herabgelassenen Kranwinde int kranRechts = 160; // Servoposition des Kranturms Rechts int kranLinks = 30; // Servoposition des Kranturms Links int warnlichtTimer[3] = {800, 700, 650}; // Warnlicht Blitzfrequenz Beim Upload muss man darauf achten, dass das richtige Board im Arduino-Menü ausgewählt ist. Dazu muss ebenfalls im Werkzeuge-Menü im Unterpunkt Prozessor »ATmega328P (Old Bootlaoder)« ausgewählt sein. Der folgende Programmcode kann mit den oben erwähnten Änderungen einfach kopiert und auf das Arduino-Nano geladen werden. Code für das Modul: RailFX-Waldarbeiten /* Rail-FX Waldarbeiten-Modul StartHardware.org Permalink: https://starthardware.org/railfx-waldarbeiten-modul/ */ #include <Servo.h> /* ***** ***** Einstellungen ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */ int baumLiegt = 120; // Servoposition des liegenden Baumes int baumSteht = 30; // Servoposition des stehenden Baumes long fallenderBaumZufall = 200000; // je kleiner der Wert, desto öfter fällt der Baum /* Legt die Wartezeiten der Kranabfolge fest: warten (Wahrscheinlichkeit), aufnehmen, warten, drehen, warten, ablassen, warten (Wahrscheinlichkeit), aufnehmen, warten, drehen, warten, ablassen -> Position 0 und 6 legen eine Wahrscheinlichkeit fest, mit der der Kran weiter arbeitet: je höher, desto seltener */ int kranTimeouts[] = {1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000, 1000, 3000}; int kranWindeSpeed = 10; // Geschwindigkeit der Kranwinde (größer = langsamer) int kranDrehungSpeed = 10; // Geschwindigkeit der Krandrehung (größer = langsamer) int windeOben = 120; // Servoposition der eingezogenen Kranwinde int windeUnten = 60; // Servoposition der herabgelassenen Kranwinde int kranRechts = 160; // Servoposition des Kranturms Rechts int kranLinks = 30; // Servoposition des Kranturms Links int warnlichtTimer[3] = {800, 700, 650}; // Warnlicht Blitzfrequenz /* ***** ***** Ab hier beginnt der Programmcode, der nicht angepasst werden muss ***** ***** ***** ***** */ int warnlichtPins[6] = {2, 3, 4, 5, 6, 7}; // Warnlicht Pins int fahrzeugbeleuchtungPins[2] = {8, 9}; // Pins der Fahrzeugbeleuchtung int beleuchtungsPins[3] = {15, 16, 17}; // an diesem Pin ist die Einsatzstellen-Beleuchtung angebracht int baumServoPin = 10; int kranServoPin = 11; int windeServoPin = 12; /* State Variablen */ int baumStatus = 0; // 0 = nichts, 1=fällt, 2=liegt, 3=aufrichten int kranStatus = 0; /* Speicher-Variablen */ int baumPosition; int windePosition; int kranPosition; /* Timer Variablen */ long kranTimer; long baumTimer; long kranDrehungTimer; long kranWindeTimer; int baumTimeout = 100; int baumTimeoutMax = 100; /* Objekte anlegen */ Servo baumServo; Servo kranServo; Servo windeServo; /* Variablen vom Controlmodul um die Uhrzeit festzustellen*/ boolean receive = false; boolean receiveStarted = false; int receiveTimeout = 10; long receiveTimer = 0; int receivedTime = 0; int receivePulse = 0; int lastReceivePulse = 0; int receivePin = 18; int myTime = 0; #define PAYLOAD_SIZE 2 // nötig für die Kommunikation zum Master int uhrzeit = 0; // speichert die uhrzeit vom Master-Modul (0 und 255) byte nodePayload[PAYLOAD_SIZE]; // speichert die Daten vom Master-Modul zwischen void setup() { Serial.begin(115200); // started die serielle Kommunikation for (int i = 0; i < 3; i++) { // Für die Anzahl der Beleuchtung-Pins pinMode(beleuchtungsPins[i], OUTPUT); // Deklariere den Pin als Output digitalWrite(beleuchtungsPins[i], HIGH); // Schalte die LED an diesem Pin ab } for (int i = 0; i < 2; i++) { // Für die Anzahl der Fahrzeugbeleuchtung-Pins pinMode(fahrzeugbeleuchtungPins[i], OUTPUT); // Deklariere den Pin als Output digitalWrite(fahrzeugbeleuchtungPins[i], HIGH); // Schalte die LED an diesem Pin ab } for (int i = 0; i < 6; i++) { // Für die Anzahl der Warnlicht-Pins pinMode(warnlichtPins[i], OUTPUT); // Deklariere den Pin als Output digitalWrite(warnlichtPins[i], HIGH); // Schalte die LED an diesem Pin ab } baumServo.attach(baumServoPin); kranServo.attach(kranServoPin); windeServo.attach(windeServoPin); } void loop() { receiveFunction(); // Führe Anweisungen für Empfang aus if (receiveStarted == false) { // Falls gerade keine Daten empfangen werden: if (myTime > 22) { // ***** Später Abend ***** warnlichtAn(); // Warnlichter einschalten beleuchtungAn(); // Beleuchtung einschalten fahrzeugbeleuchtungAn(); // Fahrzeugbeleuchtung einschalten baumAn(); // Fallenden Baum einschalten kranAn(); // Kranbewegungen einschalten } else if (myTime > 18) { // ***** Abend ***** warnlichtAn(); // Warnlichter einschalten beleuchtungAn(); // Beleuchtung einschalten fahrzeugbeleuchtungAn(); // Fahrzeugbeleuchtung einschalten baumAn(); // Fallenden Baum einschalten kranAn(); // Kranbewegungen einschalten } else if (myTime > 12) { // ***** Nachmittag ***** warnlichtAn(); // Warnlichter einschalten beleuchtungAus(); // Beleuchtung ausschalten fahrzeugbeleuchtungAus(); // Fahrzeugbeleuchtung ausschalten baumAn(); // Fallenden Baum einschalten kranAn(); // Kranbewegungen einschalten } else if (myTime > 9) { // ***** Vormittag ***** warnlichtAn(); // Warnlichter einschalten beleuchtungAus(); // Beleuchtung ausschalten fahrzeugbeleuchtungAus(); // Fahrzeugbeleuchtung ausschalten baumAn(); // Fallenden Baum einschalten kranAn(); // Kranbewegungen einschalten } else if (myTime > 7) { // ***** Morgen ***** warnlichtAn(); // Warnlichter einschalten beleuchtungAus(); // Beleuchtung ausschalten fahrzeugbeleuchtungAus(); // Fahrzeugbeleuchtung ausschalten baumAn(); // Fallenden Baum einschalten kranAn(); // Kranbewegungen einschalten } else { // ***** Nacht ***** warnlichtAus(); // Warnlichter einschalten beleuchtungAus(); // Beleuchtung einschalten fahrzeugbeleuchtungAn(); // Fahrzeugbeleuchtung einschalten baumAus(); // Fallenden Baum ausschalten } } } void fahrzeugbeleuchtungAn() { digitalWrite(fahrzeugbeleuchtungPins[0], LOW); digitalWrite(fahrzeugbeleuchtungPins[1], LOW); } void fahrzeugbeleuchtungAus() { digitalWrite(fahrzeugbeleuchtungPins[0], HIGH); digitalWrite(fahrzeugbeleuchtungPins[1], HIGH); } void beleuchtungAn() { if (random(2000) <= 1) digitalWrite(beleuchtungsPins[0], LOW); if (random(2000) <= 1) digitalWrite(beleuchtungsPins[1], LOW); if (random(2000) <= 1) digitalWrite(beleuchtungsPins[2], LOW); } void beleuchtungAus() { for (int i = 0; i < 3; i++) { digitalWrite(beleuchtungsPins[i], HIGH); } } void warnlichtAn() { for (int i = 0; i < 4; i++) { if (millis() % warnlichtTimer[i] < warnlichtTimer[i] / 2) { digitalWrite(warnlichtPins[i * 2], HIGH); digitalWrite(warnlichtPins[i * 2 + 1], LOW); } else { digitalWrite(warnlichtPins[i * 2], LOW); digitalWrite(warnlichtPins[i * 2 + 1], HIGH); } } } void warnlichtAus() { for (int i = 0; i < 8; i++) { digitalWrite(warnlichtPins[i], HIGH); } } void kranAn() { if ((kranStatus != 0) || (kranStatus != 6)) { if (kranTimer + kranTimeouts[kranStatus] < millis()) { kranStatus++; if (kranStatus > 11) kranStatus = 0; kranTimer = millis(); Serial.print("Kranstatus="); Serial.println(kranStatus); } } switch (kranStatus) { case 0: // warten if (random(kranTimeouts[0]) < 1) kranStatus = 1; break; case 1: // aufnehmen if (kranWindeTimer + kranWindeSpeed < millis()) { if (windePosition < windeOben) { windePosition++; windeServo.write(windePosition); } kranWindeTimer = millis(); } break; case 2: // pause break; case 3: // drehen if (kranDrehungTimer + kranDrehungSpeed < millis()) { if (kranPosition < kranRechts) { kranPosition++; kranServo.write(kranPosition); } kranDrehungTimer = millis(); } break; case 4: // pause break; case 5: // ablassen if (kranWindeTimer + kranWindeSpeed < millis()) { if (windePosition > windeUnten) { windePosition--; windeServo.write(windePosition); } kranWindeTimer = millis(); } break; case 6: // warten if (random(kranTimeouts[6]) < 1) kranStatus = 7; break; case 7: // aufnehmsen if (kranWindeTimer + kranWindeSpeed < millis()) { if (windePosition < windeOben) { windePosition++; windeServo.write(windePosition); } kranWindeTimer = millis(); } break; case 8: // pause break; case 9: // drehen if (kranDrehungTimer + kranDrehungSpeed < millis()) { if (kranPosition > kranLinks) { kranPosition--; kranServo.write(kranPosition); } kranDrehungTimer = millis(); } break; case 10: // pause break; case 11: // ablassen if (kranWindeTimer + kranWindeSpeed < millis()) { if (windePosition > windeUnten) { windePosition--; windeServo.write(windePosition); } kranWindeTimer = millis(); } break; } } void baumAn() { switch (baumStatus) { case 0: if (baumTimer + baumTimeout < millis()) { if (random(fallenderBaumZufall) < 1) { baumStatus = 1; baumTimeout = baumTimeoutMax; } } break; case 1: if (baumTimer + baumTimeout < millis()) { if (baumPosition < baumLiegt) { baumPosition++; baumTimeout -= 2; baumServo.write(baumPosition); } else { baumTimeout = 10000; baumStatus = 2; } delay(1); baumTimer = millis(); } break; case 2: if (baumTimer + baumTimeout < millis()) { baumStatus = 3; baumTimeout = baumTimeoutMax; } break; case 3: if (baumTimer + baumTimeout < millis()) { if (baumPosition > baumSteht) { baumPosition--; baumServo.write(baumPosition); } else { baumTimeout = 1000; baumStatus = 0; } delay(1); baumTimer = millis(); } break; } /**/ } void baumAus() { if (baumPosition > baumSteht) { if (baumTimer + baumTimeout < millis()) { baumPosition--; baumServo.write(baumPosition); } } } /* ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** ***** */ void receiveFunction() { // Empfängt die Uhrzeit vom Control-Modul receivePulse = digitalRead(receivePin); // Lies den Empfangspin aus if ((receiveTimer + receiveTimeout < millis()) && (receiveStarted == true)) { // Bei Timeout und aktivem Empfang receiveStarted = false; // beende aktiven Empfang myTime = receivedTime - 1; // speichere die empfangene Zeit receivedTime = 0; // setze die Hilfsvariable zum Zeitempfang zurück Serial.println(myTime); // serielle Ausgabe } // falls ein Puls am Empfangspin erfasst wird, der vorher nicht da war if ((receivePulse == 0) && (lastReceivePulse == 1)) { receiveTimer = millis(); // starte Timer neu if (receiveStarted == false) receiveStarted = true; // starte aktiven Empfang, wenn noch nicht geschehen receivedTime++; // es gab einen Puls, also erhöhe die Hilfsvariable zum Zeitempfang } lastReceivePulse = receivePulse; // aktuellen Zustand am Pin für nächsten Durchlauf merken } Alle RailFX-Module Ansehen » Der Beitrag RailFX-Waldarbeiten Modul erschien zuerst auf Arduino Tutorial.

zum Artikel gehen

Ausbildung Neuraltherapie

Termine der Ausbildung Neuraltherapie: Modul 1 – 22. + 23.04.2023 Modul 2 – 03. + 04.06.2023 Modul 3 – 23. + 24.09.2023 Modul 4 – 09. + 10.11.2023 – auch einzeln buchbar, Dozent: Karl Vetter, Heiko Prigge Das Modul 4 (Blaue Karte) findet im Rahmen der Jah

zum Artikel gehen

Transparente TFT-Displays: Data Modul führt zwei Modelle ein

Data Modul erweitert sein Portfolio um transparente TFT-Panels von JDI. Die Rælclear-Displays in 12,3 Zoll und 20,8 Zoll sollen sich [] The post Transparente TFT-Displays: Data Modul führt zwei Modelle ein first appeared on invidis.

zum Artikel gehen

DaVinci NT

BEWOTEC hat das Reiseveranstalter-System neu gedacht und setzt DaVinci NT nun Modul für Modul um.  Cloud, Docker, modernste User Interfaces The post DaVinci NT first appeared on BEWOTEC GmbH.

zum Artikel gehen

Divi Anker-Link bei verstecktem Modul (mobile Version / desktop Version)

Problem: Ankerlink auf die mobile Version eines Moduls funktioniert nicht. Lösungsbausteine: CSS-ID und die Klasse in die Zeile-Modul-Einstellung eintragen: Desktop-Modul CSS-ID: busines-desktop CSS-Klasse: desktop-menu-item Mobil-Modul CSS-ID: busines-de

zum Artikel gehen

RailFX-Raumbeleuchtung: Tag und Nacht für die Modellbahn

Dieses Modul des RailFX-Systems steuert die Raumbeleuchtung der Modellbahn-Anlage. Dazu wird ein RGBW-LED-Strip als Lichtquelle verwendet. Natürlich ist auch dieses Modul vom Miniatur-Wunderland inspiriert :-) Schaltplan Der LED-Strip besteht au

zum Artikel gehen