• Die Forumsregeln und Nutzungsbedingungen findet ihr in der Navbar unter Impressum !
    Bitte unbedingt beachten!
    Wie überall im Leben gibt es Spielregeln, so auch hier!
    Die Datenschutzerklärung zum DSGVO findet ihr ebenfalls in der Navbar unter Datenschutzerklärung !
    Hinweis nach DSGVO :
    Es ist hier keinerlei Angabe erforderlich. Alle Angaben in diesem Bereich sind öffentlich sichtbar und werden freiwillig gemacht. Mit einem Eintrag in diesem Bereich erkenne ich dieses an, und bestätige die Datenschutzerklärung zur DSGVO für das Forum gelesen zu haben.

    Danke
  • Hallo Gast, beschränke dich hier bitte auf den Bereich der Elektronik. Die Fahrzeuge oder Gebäude, wo diese Elektronik eingebaut wird bitte in dem passenden Fachbereiich behandeln. Auch wenn Teile des Projektes dadurch im Forum doppelt vorhanden sind! Danke.

Arduino Truck Licht und Funktions Modul mit Bus Erweiterung

Magraina

New member
Registriert
17.03.2010
Beiträge
237
Hallo zusammen,

Parallel zum bau meiner Trucks überlege ich schon eine Weile, wie die Zukünftige Generation an Licht- und Funktionsmodulen in meinen Fahrzeugen aussehen wird.
In meinem SK war Ursprünglich ein simpler fertiger Schaltbaustein, für all das Zuständig. Sowie eine zusätzliche Kanalerweiterung der Futaba F14 Fernbedienung.

Im Peterbilt schlummert mein erstes Eigenbau Modul. Welches ich ohnehin Überarbeiten muss, da sich gezeigt hat, dass die Steuerung sich deutlich verändern wird.

Im Hilux bleibt das Modul so wie es ist, aber es Bedarf eventuell einer Software-Technischen Verbesserung.
Bedingt durch den 4 Kanal Empfänger sind alle Funktionen auf 2 Kanäle verteilt. Was bei einem Crawler allerdings nicht tragisch ist.

Nun zum neuen Projekt.
Voller Motivation habe ich einfach mal losgelegt mit der Programmierung und mir überlegt wie ich das anstellen könnte.
Auf die besten Ideen kommt man einfach, wenn man sie versucht umzusetzen.

Zu meinem Konzept:

Im Truck soll es ein Modul geben, welches die in erster Linie Licht und Spezielle Funktionen bereitstellt.

Es wird einerseits an die Funk Erweiterung meiner Futaba F14 gekoppelt.
Das sind einzelne Schalter, welche am Empfänger normalerweise über einen speziellen Encoder ausgewertet werden.
Dieser Encoder verwendet ein PPM Signal, welches in bestimmten Abständen, die einzelnen Schalterzustände wiedergibt.
Das hatte ich Mal hier ausführlich erklärt:
Futaba/Robbe Multiswitch Decoder mit Arduino

Dieses PPM Signal wird das Truck Modul auswerten.
Das PWM Signal des Lenkservo soll ebenfalls ausgewertet werden, um den Blinker Realitätsgetreu abschalten zu können.
Zusätzlich werden zwei Digitale Eingänge die Brems und Rückfahrlicht Ausgänge des Servonaut Fahrtenregler auswerten.

In meiner Überlegung wie der Auflieger versorgt werden soll, kam ich zum Entschluss, dies per Bus (I2C) zu realisieren. So benötige ich nur 3-4 Drähte als Verbindung, anstatt für jede Funktion einzelne. Zusätzlich habe ich so die Möglichkeit je nach Auflieger, mehr oder weniger Funktionen zu integrieren.

Für spezielle Funktionen will ich außerdem seperate Module als eine Art I/O Erweiterung verwenden.

Außerdem soll das Programm sehr flexibel aufgebaut sein. So dass ich bestimmte Funktionen je nach Modul ein und aus schalten kann.
So zum Beispiel soll es entsprechende Unterschiede geben wenn es sich um ein EU oder US Fahrzeug handelt. Also ein Programm für alle Modelle.
So kann es besonders beim US Fahrzeug eine Kombination der Blinker und Bremsleuchten geben. Während es beim EU Modell seperate Funktionen sind.

So haben sich jetzt 4 verschiedene Module ergeben, welche per Bus (I2C) miteinander kommunizieren sollen.

Das Hauptmodul ist das Truck Modul mit Folgenden Funktionen:
- Auswertung des Empfänger Signals
- Auswertung weiterer Funktionen
- Standlicht Ausgang
- Abendlicht Ausgang mit PWM für Stand/Abend/Fernlicht
- Fernlicht Ausgang
- Nebelscheinwerfer Ausgang
- Blinker jeweils Links und Rechts sowie jeweils vorne und hinten (mindestens die US Variante benötigt Hinten seperat / Abschalten durch Lenkservo)
- Bremlicht und Rückfahrlicht (Signal über Servonaut Fahrregler)
- Zusatzfunktionen

Auflieger Modul:
- Standlicht Ausgang
- Blinker jeweils Links und Rechts (Beim US in Kombi mit Bremslicht/Standlicht)
- Bremslicht (Beim US in Kombi mit Standlicht)
- eventuell Spezielle Funktionen wie z.b. Kippen o.ä. (noch nicht genauer spezifiziert).

Rundumleuchten Modul:
- Mehrere Rundumleuchten welche über je 4 LEDs als Sequenz (Lauflicht) leuchten sollen. Da es LEDs sind kommt hier eine PWM Ansteuerung zum Einsatz, um ein Glühbirnen ähnliches verzögertes An und Abschalten zu realisieren (Fading).

Erweiterungsmodul für spezielle Funktionen:
- z.b. Kippfunktion (noch nicht genauer spezifiziert).

Die Trennung der Module hat einerseits den Hintergrund Ausreichend Ein und Ausgänge zur Verfügung zu haben. In der Planung ist hierfür je ein Arduino Micro (mein lieblings Arduino ;) ).
Aber auch um die Prozessorlast zu verteilen.
So hat zum Beispiel das Truck Modul schon eine spezielle Aufgabe, die Eingangssignale des Empfängers (per Interrupt) auszuwerten.
Das Rundumlichtmodul hat eine spezielle Last aufgrund der wenigen PWM Ausgänge, so werden die Ausgänge per Software PWM realisiert.
Außerdem lassen sich so Funktionen auch beliebig verteilen.
Auf die weiße hat jedes Modul genug Reserve seine eigene Aufgabe zu erledigen, ohne das Signale verloren gehen oder Funktionen nicht richtig ausgeführt werden.

So habe ich ein Modulares Konzept, was ich auf meinen Fuhrpark und kommenden Modelle anwenden kann. Desto durchdachter es letztendlich wird, desto individueller kann ich es für die Zukunft weiter verwenden.
Soweit Mal mein Plan.

Realisiert habe ich jeweils schon kleine Grundprogramme welche allerdings noch nicht wirklich eine Funktion haben, sondern vielmehr nur definition der Pins etc.

Vieles muss noch programmiert werden und Schaltpläne sowie Elektronik gefertigt werden.
Davon werde ich dann nach und nach Berichten.

Was ich allerdings schonmal testweise realisiert habe ist das Rundumlicht Modul.
Da ich eine Soft PWM Funktion noch nicht verwendet habe, wollte ich besonders sehen, wie gut das rüber kommt.
Außerdem habe ich dem Truck Modul zumindest Mal die Funktion eines Testbefehl per I2C an das Rundumlicht Modul gegeben.

Das Truck Modul sendet im Wechsel von 5 Sekunden einen Ein oder Aus Befehl.

Das ganze kann man schonmal hier sehen:
Um diese Inhalte anzuzeigen, benötigen wir die Zustimmung zum Setzen von Drittanbieter-Cookies.
Für weitere Informationen siehe die Seite Verwendung von Cookies.


Den gesamten Code stelle ich auf GitHub zur Verfügung (Kommentare etc. sind weitestgehend aktuell in Englisch, Deutsch kommt zum Teil noch zum Verständnis bzw. auf Nachfrage .
Truck Modul:
https://github.com/SheepCreativeSoftware/truckLightAndFunction
Auflieger Modul:
https://github.com/SheepCreativeSoftware/trailerLightAndFunction
Rundumlicht Modul:
https://github.com/SheepCreativeSoftware/truckBeaconLightModule
Erweiterungsmodul (noch in Planung)

Über Ideen, Anregungen und Wünsche freue ich mich sehr.
Ich berichte wieder, wenn es den nächsten Fortschritt gibt! :D
 
Hallo Marina,

schönes Projekt :ok
Ich hatte mir so etwas auch einmal überlegt, aber mit I²C bin ich nicht so firm. Mir fehlt aber ein bisschen die Übersicht über dem Projekt. Du rufst ja noch diverse Unterfunktionen auf wie z.B. EU oder US Trucks, wo finde ich die denn?
Ein Schaltplan oder Blockschaltbild währe auch ganz nett.
Wegen der Rechenleistung muss man sich meiner Meinung nach keine Gedanken machen. Wenn man allerdings mehr Leistung braucht währe ein STM32 (blue pill) noch ein Option. Der ist mit 52 mm etwas länger, aber das ist in den meisten Modellen sicher noch akzeptabel.
 
Hallo Bert,

ja wobei ich denke, das I2C mit der Arduino Wire Library doch recht simpel ist. Ich tue mich da weniger schwer, da ich Beruflich mit allerlei Bussystemen zu tun hab. Da gehört I2C sicher zu den einfachsten.

Ja das Verstehe ich, aktuell fehlt noch ein wenig die Übersicht. Es ist bisher vielmehr eine Ansammlung von Ideen.
Ich mach einfach mal und schaue was daraus wird.
Hier fehlt ja noch einiges. Ich muss ja erst noch das ganze programmieren und Pläne erstellen.
Und so nach und nach, werde ich hier Berichten und auch einzelne Funktionen im Detail erklären.

Die Umschaltung ist bisher so geplant, dass es eine Konstante im Programm gibt, mit welcher man die Programmteile sozusagen umschalten kann.
Diese Muss man dann je nach Modell einmalig einstellen. Dazu werde ich aber mehr Berichten, wenn ich den entsprechenden Teil programmiert habe. Weswegen du da noch nichts finden wirst ;)

Das ich die Prozessorlast sprenge glaube ich auch nicht wirklich, Tatsache ist aber, dass mir I/Os für all die Aufgaben fehlen und dazu kommt, dass ich Zeitkritische Dinge verarbeite.
Also Zeitkritisch ist die Auswertung vom PPM und PWM Signal des Empfängers und auch die Kommunikation mit den Modulen.
Ich finde die Modularität so gar nicht so schlecht. Weil ich so Teile einfach weg lassen kann oder eben nicht. Also es hat ja nicht jeder LKW ein Rundumlicht. So habe ich nacher auch eine Platine, die bei allen LKWs gleich sein kann. Und die Anbindung des Anhänger per Bus ist einfach deutlich einfacher.

Eine kleine Beispielskizze habe ich mal gemacht, vielleicht Hilft das dem Verständnis?
Unbenannt.png
 
Zum besseren Verständnis werde ich einiges was in meinem Code vor sich geht hier nach und nach erklären.
Das hilft Hoffentlich dem Verständnis und vielleicht kann der eine oder andere daraus etwas lernen!?

Ein wie ich denke Komplizierteres Thema möchte ich hier mal aufgreifen.
In meinem Programm werden viele Dinge über sogenannte "Precompiler Directiven" konfiguriert.
Das ist sicher ein Thema, welches nicht für jeden Verständlich ist.
Diese Direktiven Beginen alle mit einer Raute: "#".

Dieser Art von Programmcode wird beim Kompilieren ausgeführt.
So können zum Beispiel je nach Modul Programmteile komplett deaktiviert werden, aber nicht im Sinne das Sie nicht ausgeführt werden, sondern dass Sie gar nicht erst in den Microcontroller kommen.

Veranschaulichen wir das ganze mal mit ein wenig Programmcode von meinem aktuellen Stand:

Code:
#define wireCom true                     	         //Aktiviert die Kommunikation zu anderen Modulen 
#if (wireCom == true)                                //Inhalt wird nur Teil des Programms, wenn Variable true ist
	#define truckAdress 1                     	//I2C Adresse für Modul: Truck
	#define beaconAdress 2                  	//I2C Adresse für dieses Modul: Rundumlicht Extension
	#define trailerAdress 3                  	//I2C Adresse für Modul: Auflieger
	#define extFunctionAdress 4               //I2C Adress for Module: Special function for example Servos Steering
#endif
#define debugLevel 1
#define numberOfBeacons 2                       // Anzahl der Rundumleuchten
#define beaconSampleTime 1000		//Zeit um alle LEDs einmal leuchten zu lassen (all 4 LEDs)
#define beaconTimeVariation beaconSampleTime/10  // Variation für mehrere Rundumlichter

#define singleBeaconSampleTime beaconSampleTime/4    //Berechnung der Leuchtdauer für eine einzelne LED

Mit "#define variable wert" können wir eine Konstante bilden. Im Prinzip das selbe wie "const int variable = wert;".
Allerdings mit dem Unterschied, das diese Art der Definition bereits vom Kompiler verstanden wird.
Somit hat die Variable bereits während der Kompilierung eine Wertigkeit.

Am Anfang des Beispiel habe ich mit "#define wireCom true" eine Definition mit welcher ich die Kommunikation ein und aus schalte.
Wenn die Variable den Wert "true" hat, dann werden alle Teile des Programms, die mit der Kommunikation zu tun haben, in den Programmcode aufgenommen, der zum Microcontroller geht.
Wenn Sie "false" ist, dann wird der Kompiler die Teile des Programmcodes einfach auslassen, sozusagen entfernen.
Auf diese Weiße kann ich das Programm auf die Bereiche begrenzen, welche für mich gerade Relevant sind. Das ist auch zur Fehlersuche Hilfreich.

Damit das geht habe ich an entsprechenden stellen "IF-Bedingungen", wie "#if (wireCom == true).......#endif". Dieser Teil des Programms existiert am Schluss also nur, wenn die Variable den Wert "true" hat.

Ein weiterer Vorteil von solchen Direktiven ist, dass ich Berechnungen schon vorab machen kann, die ohnehin nur einmal ausgeführt werden.
So berechne ich hier direkt die Zeit für die Leuchtdauer der einzelnen LEDs bereits vorab.
Code:
#define beaconSampleTime 1000		//Zeit um alle LEDs einmal leuchten zu lassen (all 4 LEDs)
#define singleBeaconSampleTime beaconSampleTime/4    //Berechnung der Leuchtdauer für eine einzelne LED
Vorteil dabei ist, das der Microcontroller, dass nicht mehr Berechnen muss. Er wird dadurch entlastet.
Sicher ist das ein Simples Beispiel, welches man so nicht braucht, aber je nachdem hat man vielleicht mal Komplizierte Berechnungen, welche nur einmalig Ausgeführt werden muss.
Und vielleicht hat man Daraufhin Bedingungen, die entsprechend dessen einen Programmcode Bilden.

Mit dem "#debugLevel 1" aktiviere ich Programmcode, welchen ich nur zum testen des Programms benötige (gängige Vorgehensweise) in der Software Entwicklung.
Damit kann ich z.b. den Seriellen Monitor aktivieren und mir anschauen, was das Programm, an welcher Stelle macht.
Warum mache ich das so?
Ich könnte ja auch solche Funktionen nach der Entwicklung wieder löschen. Oder nur Bedarfs weiße hinein Programmieren.
Denn später braucht es diese nicht mehr. Und je nach Umfang kostet es eventuell Prozessorleistung und Speicherressourcen.
Auf die weiße habe ich die Diagnosefunktion immer auf Abruf, um auch später Fehler zu finden oder neue Funktionen zu testen.
 
Hallo Marina,
schönes Projekt. Ich bleibe mal am Ball.
Ich gespannt was da raus kommt, wenn es mal fertig ist. Insbesondere, da ich mich ja selber auch mit dem Themenbereich beschäftige.
 
Hi,

Hört sich super interessant an, hab zwar von dem Thema Arduino und Licht Technik nicht die wahnsinnige Ahnung (man könnte auch sagen „von und tuten und blasen keinen Schimmer“), aber als Anwendungsentwickler kann ich hier sicher viel lernen ;)
Ich bleib dran :)

Gruß
 
Moin Marina,

ich bastel ja auch gerne mit Arduinos, allerdings eher im Bereich des Fahrverhaltens. Da bleibe ich mal dran... ;)
 
Hallo Marina,
bei I2C ist ein wenig Vorsicht geboten (will nicht als Lehrer, sondern als Tipgeber meine Meinung loswerden).
Je nach Pullup-Widerstand, Übertragungsgeschwindigkeit, Teilnemeranzahl und Leitungslänge kommt es schnell zu Störungen (Motorzuleitung ist sehr "Böse").
Ein Bit entscheidet ob geschrieben oder gelesen wird!
Hab schlechte und kostspielige Erfahrungen gesammelt.
Daher der Tip: Möglichst bald ein Vollausbau mit langen Kabel, und viel mit Oscilloscope messen.
Bin jetzt beim 485er-Ring-Bus gelandet.

Grüße aus Heufeld, Johann
 
Hallo Johann,

ja das ist sicher nicht verkehrt. Denn Tipp nehme ich gerne wahr :ok
Ist wie bei jedem Bussystem wichtig.
Wir werden sehen wo mich das hinführt.

RS485 ist im Vergleich zu anderen Physikalisch sehr robust aufgebaut.
Sowas will ich eigentlich vermeiden, denn dann bräuchte ich zusätzliche Hardware (Was ich da hätte, aber halt nicht verbauen will).

Es ist mit ein Grund, warum ich mit der Kommunikation begonnen habe zu programmieren.
Bei der Kommunikation bin ich aktuell soweit, dass ich nach Bedarf senden kann.
Dabei gleichzeitig feststellen kann, ob das Telegramm ankam, sowie ob es fehlerfrei ankam.
Im Slave überprüfe ich das Empfangene ebenfalls auf Vollständigkeit und gebe das dem Master zurück.
Als nächstes kommt noch eine CRC Prüfung dazu.
Sobald das steht und ich erste Tests durch hab, berichte ich!
 
Hallo Marina,

wenn du mit einer Checksumme arbeitest ist das schon sehr störsicher. Macht man ja beim CAN Bus auch so.
Auf jeden Fall ein interessantes Projekt!
 
Hallo Bert,

ja ich finde eine Checksumme oder zumindest etwas vergleichbares ist besonders wichtig für eine zuverlässige Kommunikation. Ich hab ja schon verrückte Dinge gesehen, bei Dingen, wo das nicht so war.
Störungssicher wird es dadurch definitiv.
Aber wie Störungsfrei das im Realbetrieb dann wird, zeigt sich dann noch. Denn zu viel Störungen führen dann zu kaum bis keiner Kommunikation.
Hängt maßgeblich von der Umgebung ab.
Da bin ich sehr gespannt darauf, wie sich das auswirkt.

Wenn das nicht gut genug läuft, dann werde ich gezwungenermaßen auf eine Alternative setzen müssen.
Die Serielle Schnittstelle (UART) wird alleine sehr wahrscheinlich die gleichen Probleme bringen wie I2C. Also bräuchte es eine entsprechende Wandlung, auf eine andere Schnittstelle (was im Grunde auch nicht schwer ist).
Das heißt, wenn das nicht klappt, dann werde ich gezwungenermaßen auf RS485 wechseln (das ist CAN sogar Recht Ähnlich)
Besser kann es dann eigentlich nicht mehr gehen.
Aber solange ich nicht weiß, das ich es brauche, verzichte ich erstmal darauf. Denn I2C ist insgesamt sowohl in der Software als auch Hardware sehr simpel zu Hand haben.
Naja wir werden sehen.
 
Hallo Marina,

die Arduino Eingänge sind ja recht hochohmig, da kamm man aber auch 2,2k Ohm extern dranschalten, dann fließen da schon einmal 2,5mA, da muss die EMV dann schon hoch sein um das zu stören.
Ansonsten habe ich mit Ferritkernen gute Erfahrungen gemacht.
 
So die Woche über kam ich nicht wirklich weiter.
Heute wollte ich mal erste Tests machen an einem Modell. Aber wie sich gezeigt hat ist heute nicht so mein Tag.

Dabei habe ich unglücklicherweiße den falschen Pin erwischt, was der Arduino mit einem typischen Elektronischen Geruch quittierte :(

Also dann einen anderen hergenommen. Soweit hat alles geklappt und das auch Störungsfrei.
Auch auf dem Oszilloskop sieht alles wunderbar aus.

Allerdings konnte ich mein Servonaut Fahrregler nicht zum laufen bekommen.
Ich bin zwar der Meinung das mein Akku ausreichend voll sein sollte, aber vielleicht sieht das der Fahrregler anders.
Der Akku ist für die Lagerung nur etwa zu 60% geladen.
Also werde ich ihn erstmal voll laden und sofern es das war werde ich bald mehr darüber Berichten.

Zum testen habe ich mir über den Seriellen Monitor diverse Mögliche Meldungen generiert
Hier mal ein Beispiel:
Code:
12:44:53.833 -> 0x00:send success
12:44:53.935 -> 0x05:request transmited
12:44:53.935 -> 0x10:answer transmit successfull
12:44:58.803 -> 0x00:send success
12:44:58.905 -> 0x05:request transmited
12:44:58.905 -> 0x10:answer transmit successfull
12:45:03.808 -> 0x02:received NACK on transmit of address
12:45:08.813 -> 0x00:send success
12:45:08.915 -> 0x05:request transmited
12:45:08.915 -> 0x10:answer transmit successfull
12:45:13.826 -> 0x00:send success
12:45:13.928 -> 0x05:request transmited
12:45:13.928 -> 0x10:answer transmit successfull
12:45:18.832 -> 0x00:send success
12:45:18.934 -> 0x05:request transmited
12:45:28.905 -> 0x06:answer timed out
12:45:33.802 -> 0x02:received NACK on transmit of address
12:45:38.832 -> 0x00:send success
12:45:38.934 -> 0x05:request transmited
12:45:38.934 -> 0x10:answer transmit successfull

Die Wire Library überprüft bereits selbst, ob das Telegramm angekommen ist, wenn nicht dann gibt es einen entsprechenden Fehlercode:
Code:
int sendError = Wire.endTransmission();        	// stop transmitting | 0:success; 1:data too long to fit in transmit buffer;
													// 2:received NACK on transmit of address; 3:received NACK on transmit of data;
													// 4:other error
Das werte ich entsprechend auch aus und bringe es zur Anzeige. (Theoretisch können Fehlercode 2 oder 3 entstehen; NACK -> Not Acknowledged -> Keine Bestätigung-Antwort).
Das reicht eigentlich später auch aus.

Zusätzlich überprüfe ich was der Teinehmer empfangen hat, indem ich eine zusätzliche anfrage schicke.
Mit der Antwort, finde ich dann heraus, ob das Telegram wirklich fehlerfrei ankam (Das ist vielleicht letztendlich übertrieben, aber zumindest zum testen ein Weg mehr zu erfahren von der Master-Seite aus).
Der CRC Check fehlt mir allerdings noch.

Gesendet wird nur bei Bedarf. Sendet man zu viel kann man sehen, wie die SoftPWM auf dem Rundumlicht Modul in eine ruckelige Frequenz über geht.
Das bestätigt schonmal meine Erwartung, was die SoftPWM angeht. Letzendlich werde ich aber nur Bedarfsweiße senden.

Hier mal ein groben Überblick auf das bisherige Programm, für interessierte ;) (Ich hab da noch etwas an Kommentaren gespart)
Bisher gibt es nur die Kommunikation und das Rundumlicht.
Truckmodul:
Code:
/************************************ 
 * truckLightAndFunction v0.0.5
 * Date: 10.05.2020 | 17:09
 * <Truck Light and function module>
 * Copyright (C) 2020 Marina Egner <info@sheepindustries.de>
 *
 * This program is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. 
 * If not, see <https://www.gnu.org/licenses/>.
 ************************************/

/************************************
 * Configuration Programm
 ************************************/
#define ContryOption EU                   //Setup Region EU or US for Truck
#define HeadLightCombine false            //High => Low and High Beam on both Head Light output Pins | False => Seperate Pins for High and Low Beam 
#define wireCom true                     //Activate Communication to other modules via I2C 
#if (wireCom == true)
	#define truckAdress 1                     //I2C Adress for this Module: Truck
	#define beaconAdress 2                    //I2C Adress for Module: Beacon Lights Extension
	#define trailerAdress 3                   //I2C Adress for Module: Trailer 
	#define extFunctionAdress 4               //I2C Adress for Module: Special function for example Servos Steering
#endif
#define debugLevel 3	
/************************************
 * Include Files
 ************************************/
#if (wireCom == true)
#include <Wire.h>                         //Include I2C Library
#endif

/************************************
 * Definition IO Pins
 ************************************/
// TODO: setup correct pins
//Pinout Arduino Micro:
//I2C 2+3 | PWM 3, 5, 6, 9, 10, 11, 13 | LED 13
//Servo Lib deactivates PWM functionality on pins 9 and 10

//Inputs
#define inFunctionControlPPM 0            //PPM Signal from Remote Control Extension | Interrupt Needed
#define inSteerControlPPM 1               //Steering Servo Signal from Receiver  | Interrupt Needed
// Pin 2+3 reserved for I2C!
#define inBrakeSignal 4                   //Brake Signal from Servonaut Speed Controller
#define inReverseSignal 7                 //Reverse Signal from Servonaut Speed Controller

//Outputs
#if (debugLevel >=1)
	#define outStatusLed 13					//Arduino status LED output Pin
#endif
#define outParkingLight 8                 //Parking light output pin
#define outLowBeamLight 9                 //Head light low beam output pin | PWM
#define outHighBeamLight 10               //Head light high beam output pin
#define outFogLight 12                    //Fog light output pin
#define outFrontLeftFlashLight 14         //Front left flashing light output pin
#define outFrontRightFlashLight 15        //Front right flashing light output pin
#define outRearLeftFlashLight 5           //Rear left flashing light output pin | PWM Needed for US
#define outRearRightFlashLight 6          //Rear right flashing light output pin | PWM Needed for US
#define outReverseLight 16                //Reverse light output pin
#define outBrakeLight 11                  //Brake light output pin | PWM for Parking Light
#define outAuxLight 17                    //Reserved for Special Auxiliary Light
//Free IOs 18, 19
/************************************
 * Definition and Initialisation 
 * Global Vars, Classes and Functions
 ************************************/
bool pulseStatus = false;
unsigned long StatusPreviousMillis = 0;
unsigned long blinkOnTime = 0;
unsigned long waitForAnswer = 0;
bool sendDirection = false;
unsigned int reciveTimeout = 10000;
unsigned int waitAfterSend = 100;
//Functions
bool controllerStatus(bool);
int blink(unsigned int);
unsigned int wireComunicationSend(int, unsigned int, unsigned int);
unsigned int wireComunicationRecive(unsigned int);
unsigned int checkCRC(unsigned int, unsigned int, unsigned int);


void setup() {
	// put your setup code here, to run once:
	#if (wireCom == true)
	Wire.begin(truckAdress);                 // join I2C bus (address optional for master)
	#endif
	#if (debugLevel >=2)
	Serial.begin(9600);  // start serial for output
	#endif
	delay(5000);
// TODO: Setup IO pins
}
unsigned int pulseTest = false;
unsigned int lastPulseTest = false;
unsigned int sendSucess = 0x99;
void loop() {                             // put your main code here, to run repeatedly:
	#if (debugLevel >=1)
		bool errorFlag = false;                 	// local var for error status
	#endif


	// Example For later Communication with other Module
	// TODO: Setup Communication
	pulseTest = blink(10000);
	// delay(5000);
	#if (wireCom == true)
	
	if(pulseTest != lastPulseTest) {
		sendSucess = wireComunicationSend(beaconAdress, 0x01, pulseTest);
		lastPulseTest = pulseTest;
	}
	wireComunicationRecive(beaconAdress);
	#endif
	#if (debugLevel >=1)
		controllerStatus(errorFlag);
	#endif
}
#if (debugLevel >=1)
bool controllerStatus(bool errorFlag) {
	if(errorFlag) {
		return true;
	} else {
		unsigned long currentMillis = millis();
    if (currentMillis - StatusPreviousMillis >= 1000) { //Zeitverzoegerte Abfrage
		StatusPreviousMillis = currentMillis;
		pulseStatus = !pulseStatus;
    } else if (currentMillis < StatusPreviousMillis) {  //Reset
		StatusPreviousMillis = currentMillis; 
    }
    return pulseStatus;                 //Flash if everything is OK
	}
}
#endif
int blink(unsigned int blinkTimeMillis) {
	if((blinkOnTime == 0) || (blinkOnTime > millis())){ //Reset blinkOnTime on startup and on overflow.
		blinkOnTime = millis();
	}
		unsigned long blinkTime = millis() - blinkOnTime;
	if(blinkTime%blinkTimeMillis >= blinkTimeMillis/2){ //ON/OFF Interval at half of Time.
		return 0;
	} else {
		return 1;
	}

}

#if (wireCom == true)
unsigned int wireComunicationSend(int sendAdress, unsigned int RegisterAdress, unsigned int data) {
	unsigned int sendError = 0xFF;
	if(sendDirection == false) {
		unsigned int dataCRC = checkCRC(RegisterAdress, data);
		Wire.beginTransmission(sendAdress); 		// transmit to Beacon Module
		Wire.write(RegisterAdress);       			// send bytes
		Wire.write(data);       					// send bytes
		Wire.write(dataCRC);       					// send bytes
		sendError = Wire.endTransmission();        	// stop transmitting | 0:success; 1:data too long to fit in transmit buffer;
													// 2:received NACK on transmit of address; 3:received NACK on transmit of data;
													// 4:other error
		waitForAnswer = millis();
	} 

	#if (debugLevel >=3)
		//Serial.println("Wire Com Status Message:");         // Sending Error Debug Message
		switch (sendError) {
			case 0x00:
				Serial.println("0x00:send success");         		// Send Status Message
			break;
			case 0x01:
				Serial.println("0x01:data too long to fit in transmit buffer");	// Send Status Message
			break;
			case 0x02:
				Serial.println("0x02:received NACK on transmit of address");	// Send Status Message
			break;
			case 0x03:
				Serial.println("0x03:received NACK on transmit of data");		// Send Status Message
			break;
			case 0x04:
				Serial.println("0x04:other transmit error");	// Send Status Message
			break;
			case 0xFF:
			//Do Nothing
			break;
			default:
				Serial.println("0x99:Error code not defined:");	    // Send Status Message
				Serial.println(sendError);	    // Send Status Message
			break;
		}	
	#endif
	return sendError;
}

unsigned int wireComunicationRecive(unsigned int sendAdress) {
	unsigned int sendError = 0xFF;
	if(sendDirection == true) {
		while(Wire.available()) { 					// slave may send less than requested
			sendError = Wire.read(); 				// receive a byte as character
			sendDirection = false;
				
		}
		if((millis() >= waitForAnswer+reciveTimeout) && (sendDirection == true)) {
			sendDirection = false;
			sendError = 0x06;
			
		}
	}	
	if((millis() >= waitForAnswer+waitAfterSend) && (sendDirection == false) && (sendSucess == 0x00)) {
			Wire.requestFrom(sendAdress, 1);    // request 6 bytes from slave device #8
			sendDirection = true;
			waitForAnswer = millis();
			sendError = 0x05;
			sendSucess = 0x99;
	}
	
	#if (debugLevel >=3)
		//Serial.println("Wire Com Status Message:");         // Sending Error Debug Message
		switch (sendError) {
			case 0x05:
				Serial.println("0x05:request transmited");		// Send Status Message
			break;
			case 0x06:
				Serial.println("0x06:answer timed out");		// Send Status Message
			break;
			case 0x10:
				Serial.println("0x10:answer transmit successfull");		// Send Status Message
			break;
			case 0x11:
				Serial.println("0x11:answer CRC Check failed");		// Send Status Message
			break;
			case 0x12:
				Serial.println("0x12:answer to much information");	// Send Status Message
			break;
			case 0xFF:
				//Do Nothing
			break;
			default:
				Serial.println("0x99:Error code not defined:");	    // Send Status Message
				Serial.println(sendError);	    // Send Status Message
			break;
		}	
	#endif
	return sendError;
}
	
unsigned int checkCRC(unsigned int registerAdress, unsigned int data){
	return 1;
}
#endif

Rundumlicht Modul
Code:
/************************************ 
 * truckBeaconLightModule v0.0.8
 * Date: 10.05.2020 | 17:09
 * <Beacon Light Module for Truck Light and function module>
 * Copyright (C) 2020 Marina Egner <info@sheepindustries.de>
 *
 * This program is free software: you can redistribute it and/or modify it 
 * under the terms of the GNU General Public License as published by the 
 * Free Software Foundation, either version 3 of the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
 * See the GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along with this program. 
 * If not, see <https://www.gnu.org/licenses/>.
 ************************************/

/************************************
 * Configuration Programm
 ************************************/
#define wireCom true                     	//Activate Communication to other modules via I2C 
#if (wireCom == true)
	#define truckAdress 1                     	//I2C Adress for Module: Truck
	#define beaconAdress 2                  	//I2C Adress for this Module: Beacon Lights Extension
	#define trailerAdress 3                  	//I2C Adress for Module: Trailer 
	#define extFunctionAdress 4               	//I2C Adress for Module: Special function for example Servos Steering
#endif
#define numberOfBeacons 2
#define beaconSampleTime 1000				//time for one run through (all 4 LEDs)
#define beaconTimeVariation beaconSampleTime/10
#define debugLevel 3						//
/************************************
 * Include Files
 ************************************/
#if (wireCom == true)
	#include <Wire.h>                         	//Include I2C Library
#endif
#include <SoftPWM.h>						//https://github.com/bhagman/SoftPWM

/************************************
 * Definition IO Pins
 ************************************/
// TODO: setup correct pins
//Pinout Arduino Micro:
//I2C 2+3 | PWM 3, 5, 6, 9, 10, 11, 13 | LED 13
//Servo Lib deactivates PWM functionality on pins 9 and 10

//Inputs
// Pin 2+3 reserved for I2C!


//Outputs
#if (debugLevel >=1)
	#define outStatusLed 13
#endif
#if (numberOfBeacons >= 1)                   	//Arduino status LED output Pin
	#define outFirstBeaconLight1 4            	//First Beacon light 1 output pin
	#define outFirstBeaconLight2 5            	//First Beacon light 2 output pin
	#define outFirstBeaconLight3 6           	//First Beacon light 3 output pin
	#define outFirstBeaconLight4 7           	//First Beacon light 4 output pin
#endif
#if (numberOfBeacons >= 2) 
	#define outSecondBeaconLight1 8           	//Second Beacon light 1 output pin
	#define outSecondBeaconLight2 9           	//Second Beacon light 2 output pin
	#define outSecondBeaconLight3 10          	//Second Beacon light 3 output pin
	#define outSecondBeaconLight4 11          	//Second Beacon light 4 output pin
#endif
#if (numberOfBeacons >= 3) 
	#define outThirdBeaconLight1 12            	//Third Beacon light 1 output pin
	#define outThirdBeaconLight2 13            	//Third Beacon light 2 output pin
	#define outThirdBeaconLight3 14           	//Third Beacon light 3 output pin
	#define outThirdBeaconLight4 15           	//Third Beacon light 4 output pin
#endif
#if (numberOfBeacons >= 4) 
	#define outFourthBeaconLight1 16           	//Fourth Beacon light 1 output pin
	#define outFourthBeaconLight2 17           	//Fourth Beacon light 2 output pin
	#define outFourthBeaconLight3 18          	//Fourth Beacon light 3 output pin
	#define outFourthBeaconLight4 19          	//Fourth Beacon light 4 output pin
#endif

//Free IOs 18, 19
/************************************
 * Definition and Initialisation 
 * Global Vars, Classes and Functions
 ************************************/
bool pulseStatus = false;
unsigned int RecivedRegisterAdress = 0;
#define maxRegisterAdress 10
unsigned int RecivedData[maxRegisterAdress] = { 0 };
unsigned int RecivedCRC = 0;
unsigned int answerToMaster = 0;
unsigned long statusPreviousMillis = 0;
#define singleBeaconSampleTime beaconSampleTime/4

#define beaconSampleTime2 beaconSampleTime+beaconTimeVariation
#define singleBeaconSampleTime2 beaconSampleTime2/4

#define beaconSampleTime3 beaconSampleTime-beaconTimeVariation
#define singleBeaconSampleTime3 beaconSampleTime3/4

#define beaconSampleTime4 beaconSampleTime2+beaconTimeVariation
#define singleBeaconSampleTime4 beaconSampleTime4/4
//Functions
bool controllerStatus(bool);
void beaconLight(const unsigned int, const unsigned int, const unsigned int, const unsigned int, const unsigned int);
void beaconLightOff(const unsigned int, const unsigned int, const unsigned int, const unsigned int);
void receiveEvent(int);
bool checkCRC(unsigned int, unsigned int, unsigned int);

void setup() {
  // put your setup code here, to run once:
	#if (wireCom == true)
	Wire.begin(beaconAdress);                 	// join I2C bus (address optional for master)
	Wire.onReceive(receiveEvent); 				// register event
	Wire.onRequest(requestEvent); 				// register event
	#endif
	#if (debugLevel >=2)
	Serial.begin(9600);  // start serial for output
	#endif
	

	#if (numberOfBeacons >= 1) 
	SoftPWMBegin();                           	//Init Soft PWM Lib
	SoftPWMSet(outFirstBeaconLight1, 0);     	//Create and set pin to 0
	SoftPWMSetFadeTime(outFirstBeaconLight1, singleBeaconSampleTime, singleBeaconSampleTime);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFirstBeaconLight2, 0);     	//Create and set pin to 0
	SoftPWMSetFadeTime(outFirstBeaconLight2, singleBeaconSampleTime, singleBeaconSampleTime);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFirstBeaconLight3, 0);     	//Create and set pin to 0
	SoftPWMSetFadeTime(outFirstBeaconLight3, singleBeaconSampleTime, singleBeaconSampleTime);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFirstBeaconLight4, 0);     	//Create and set pin to 0
	SoftPWMSetFadeTime(outFirstBeaconLight4, singleBeaconSampleTime, singleBeaconSampleTime);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	#endif
	#if (numberOfBeacons >= 2) 
	SoftPWMSet(outSecondBeaconLight1, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outSecondBeaconLight1, singleBeaconSampleTime2, singleBeaconSampleTime2);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outSecondBeaconLight2, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outSecondBeaconLight2, singleBeaconSampleTime2, singleBeaconSampleTime2);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outSecondBeaconLight3, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outSecondBeaconLight3, singleBeaconSampleTime2, singleBeaconSampleTime2);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outSecondBeaconLight4, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outSecondBeaconLight4, singleBeaconSampleTime2, singleBeaconSampleTime2);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	#endif
	#if (numberOfBeacons >= 3) 
	SoftPWMSet(outThirdBeaconLight1, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outThirdBeaconLight1, singleBeaconSampleTime3, singleBeaconSampleTime3);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outThirdBeaconLight2, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outThirdBeaconLight2, singleBeaconSampleTime3, singleBeaconSampleTime3);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outThirdBeaconLight3, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outThirdBeaconLight3, singleBeaconSampleTime3, singleBeaconSampleTime3);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outThirdBeaconLight4, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outThirdBeaconLight4, singleBeaconSampleTime3, singleBeaconSampleTime3);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	#endif
	#if (numberOfBeacons >= 4)   
	SoftPWMSet(outFourthBeaconLight1, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outFourthBeaconLight1, singleBeaconSampleTime4, singleBeaconSampleTime4);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFourthBeaconLight2, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outFourthBeaconLight2, singleBeaconSampleTime4, singleBeaconSampleTime4);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFourthBeaconLight3, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outFourthBeaconLight3, singleBeaconSampleTime4, singleBeaconSampleTime4);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	SoftPWMSet(outFourthBeaconLight4, 0);     //Create and set pin to 0
	SoftPWMSetFadeTime(outFourthBeaconLight4, singleBeaconSampleTime4, singleBeaconSampleTime4);       //Set fade time for pin 1000 ms fade-up time, and 1000 ms fade-down time
	#endif
	
}

void loop() {                             		// put your main code here, to run repeatedly:
	#if (debugLevel >=1)
	bool errorFlag = false;                 	// local var for error status
	#endif
	if(RecivedData[1]) {
		#if (numberOfBeacons >= 1) 
		beaconLight(outFirstBeaconLight1, outFirstBeaconLight2, outFirstBeaconLight3, outFirstBeaconLight4, beaconSampleTime);
		#endif
		#if (numberOfBeacons >= 2) 
		beaconLight(outSecondBeaconLight1, outSecondBeaconLight2, outSecondBeaconLight3, outSecondBeaconLight4, singleBeaconSampleTime2);
		#endif
		#if (numberOfBeacons >= 3) 
		beaconLight(outThirdBeaconLight1, outThirdBeaconLight2, outThirdBeaconLight3, outThirdBeaconLight4, singleBeaconSampleTime3);
		#endif
		#if (numberOfBeacons >= 4) 
		beaconLight(outFourthBeaconLight1, outFourthBeaconLight2, outFourthBeaconLight3, outFourthBeaconLight4, singleBeaconSampleTime4);
		#endif
	} else {
		#if (numberOfBeacons >= 1) 
		beaconLightOff(outFirstBeaconLight1, outFirstBeaconLight2, outFirstBeaconLight3, outFirstBeaconLight4);
		#endif
		#if (numberOfBeacons >= 2) 
		beaconLightOff(outSecondBeaconLight1, outSecondBeaconLight2, outSecondBeaconLight3, outSecondBeaconLight4);
		#endif
		#if (numberOfBeacons >= 3) 
		beaconLightOff(outThirdBeaconLight1, outThirdBeaconLight2, outThirdBeaconLight3, outThirdBeaconLight4);
		#endif
		#if (numberOfBeacons >= 4) 
		beaconLightOff(outFourthBeaconLight1, outFourthBeaconLight2, outFourthBeaconLight3, outFourthBeaconLight4);
		#endif
	}

	
	// Example For later Communication with other Module
	// TODO: Setup Communication
	#if (wireCom == true)
	//wireComunication();
	#endif
	#if (debugLevel >=1)
	controllerStatus(errorFlag);			//function to signal actual status with status led
	#endif
}



void beaconLight(const unsigned int pin1, const unsigned int pin2, const unsigned int pin3, const unsigned int pin4, const unsigned int sampleTime) {
	unsigned long currentMillis = millis();
	const unsigned int singleSampleTime = sampleTime/4;
	if(currentMillis%sampleTime >= singleSampleTime*3){ //ON/OFF Interval at half of Time.
		SoftPWMSet(pin3, 0);
		SoftPWMSet(pin4, 255);
	} else if (currentMillis%sampleTime >= singleSampleTime*2) {
		SoftPWMSet(pin2, 0);
		SoftPWMSet(pin3, 255);
	} else if (currentMillis%sampleTime >= singleSampleTime) {
		SoftPWMSet(pin1, 0);
		SoftPWMSet(pin2, 255);
	} else if (currentMillis%sampleTime < singleSampleTime) {
		SoftPWMSet(pin4, 0);
		SoftPWMSet(pin1, 255);
	}
}
void beaconLightOff(const unsigned int pin1, const unsigned int pin2, const unsigned int pin3, const unsigned int pin4) {
	SoftPWMSet(pin1, 0);
	SoftPWMSet(pin3, 0);
	SoftPWMSet(pin2, 0);
	SoftPWMSet(pin4, 0);
	
}
#if (debugLevel >=1)
bool controllerStatus(bool errorFlag) {
	if(errorFlag) {
		return true;
	} else {
		unsigned long currentMillis = millis();
	if (currentMillis - statusPreviousMillis >= 1000) { //Zeitverzoegerte Abfrage
		statusPreviousMillis = currentMillis;
		pulseStatus = !pulseStatus;
	} else if (currentMillis < statusPreviousMillis) {  //Reset
		statusPreviousMillis = currentMillis; 
	}
		return pulseStatus;                 	//Flash if everything is OK
	}
}
#endif

#if (wireCom == true)
void receiveEvent(int howMany) {
	unsigned int tempRecivedData = 0;
	if(howMany == 3){
		while (1 <= Wire.available()) { // loop through all 
			RecivedRegisterAdress = Wire.read(); // receive byte as a character
			tempRecivedData = Wire.read(); // receive byte as a character
			RecivedCRC = Wire.read(); // receive byte as a character
			#if (debugLevel >=3)
			Serial.println("Recived Data:");         // print the character
			Serial.println(RecivedRegisterAdress);   // print the character
			Serial.println(tempRecivedData);         // print the character
			Serial.println(RecivedCRC);         	 // print the character
			#endif
		}
		
		if((checkCRC(RecivedRegisterAdress, tempRecivedData, RecivedCRC)) && (RecivedRegisterAdress < maxRegisterAdress)) { //Prüfe CRC und größe der adresse
			RecivedData[RecivedRegisterAdress] = tempRecivedData;		//Wenn alles in Ordung, dann schreibe
			answerToMaster = 0x10; //Status Code Everything is fine
			#if (debugLevel >=3)
			Serial.println("Error Code Everything is fine");         // print the character
			#endif
		} else {
			answerToMaster = 0x11; //Error Code CRC Check failed
			#if (debugLevel >=3)
			Serial.println("Error Code CRC Check failed");         // print the character
			#endif
		}
	} else {
		//Error to much information
		while (1 <= Wire.available()) { // loop through all 
			unsigned int trashData = Wire.read(); // receive data an forget it
		}
		answerToMaster = 0x12;     //Error Code to much information
		#if (debugLevel >=3)
		Serial.println("Error Code to much information");         // print the character
		#endif
	}
	
}

bool checkCRC(unsigned int RecivedRegisterAdress, unsigned int tempRecivedData, unsigned int RecivedCRC){
	if(RecivedCRC){
		return true;
	} else {
		return false;
	}
	
}

void requestEvent() {
	#if (debugLevel >=3)
	Serial.println("Requenst from Master");         // print the character
	#endif
	Wire.write(answerToMaster);
}
#endif
 
Ein voller Akku löst das Problem auch nicht :(
Laut meiner Recherche gab es beim S20 einmal ein Speicherproblem bei langer Standzeit.
Gut möglich, dass das mein Problem ist.
Ich hab mal mit Servonaut Kontakt aufgenommen.
Dann folgt der endgültige Realtest erst wenn das Problem geklärt ist.
 
So mein Fahrregler ist auf dem Rückweg von Servonaut :D
Er wurde kostenfrei neu programmiert. Weil er zu einer Charge gehört, die falsch programmiert wurde. Was bei längerer Standzeit zum Ausfall führt.

Dann kann's bald weiter gehen! :D
Derweil hab ich mir viele Gedanken gemacht, wie ich die Elektronik aufbaue.
Die Elektronik wird relativ einfach sein, also eigentlich lediglich Schaltausgänge haben. Vorwiderstände kommen dann separat.
So passt es dann später auch individuell in jedes Modell.
Ich überlege ob ich noch einen zusätzlichen Servokanal auswerten soll. Weil später soll eines der Module, auch einen Antrieb für eine Kippermulde übernehmen ohne zusätzliche Kabel zum Auflieger.
Das muss ich aber testen, wie der Arduino das mitmacht.
3 Interrupt Routinen sind jedenfalls sehr zeitkritisch.
Bin Mal gespannt wie gut das funktioniert.
Wobei ich sogar die Routine für den Lenkservo auslassen könnte, wenn der Blinker nicht aktiv ist.

Das Software PWM will ich eventuell auch bei einigen anderen Lampen benutzen. Entweder um die Helligkeit anzupassen oder um ein "Fading"-Effekt hinzu bekommen.

Bezüglich der Kommunikation muss ich gestehen reizt es mich doch ein wenig, vielleicht auf RS485 umzuschwenken.
Das liegt wahrscheinlich daran, weil ich beruflich diesen Bus sehr lieb gewonnen habe.
Es wäre im Grunde ein zusätzlicher IC und von der Software ist es fast genau das selbe mit sogar ein paar Vorteilen, wie ich finde. Aber der Bus wäre von Grundauf so robust, dass ich mir nie Sorgen machen müsste.
Und ich kenne mich ja selbst. Wer weiß was verrückte Ideen ich mit all dem noch haben werde ;)
Auf der anderen Seite, ist es natürlich ratsamt das Modell bestmöglichst zu endstören.
 
Hallo Marina,

ich habe auch schon bei Schalteingängen mit der "pulseIn" Funktion gearbeitet, das ging auch ohne Probleme.
Du kannst natürlich auch auf den STM32 (Bluepill) aufsetzen, der lässt sich auch mit der Arduino IDE programmieren. Von der Größe her ist die Breite fast identisch, die Länge ca. 1,5 fach verglichen mit einem pro Mini.
 
Hallo Bert,
Ja na klar das geht auch mit "pulseIn", allerdings ist dabei die Gefahr, je nach Umfang des Programms, etwas zu verpassen oder falsch zu deuten, deutlich höher. Bei normalen Servo Impulsen ist das auch eher unkritisch.
Beim Multiswitch PPM Signal ist es allerdings wichtig wirklich alle Impulse sicher mit zu bekommen. Verpasst man nur einen Telegramm, dann stimmt die Reihenfolge nicht mehr.
Der Punkt bei mehreren Eingangssignalen ist, das die Gefahr steigt.
Mit Interrupt Routinen lässt sich das Problem ganz einfach umgehen, weil man diese Eingangsimpulse, damit Priorisiert.
Bei Flankenveränderung wird automatisch der Interrupt ausgelöst und das Zyklische Programm kurz unterbrochen.
Wichtig dabei ist, dass diese Routine so schnell wie möglich beendet wird.

Letztendlich sollte allerdings auch das Zyklische Programm noch schnell genug arbeiten, um das verarbeiten zu können.

Gleichzeitig muss der Hauptcontroller mit allen anderen Teilnehmern kommunizieren und bestenfalls noch eine Software PWM zustande bringen.
Beispielsweise wenn der Arduino mit anderen Aufgaben zu sehr beschäftigt ist, dann funktioniert eine Software PWM nicht zufriedenstellend. Das bedeutet das LEDs flackern, weil sie die erforderliche Frequenz nicht erreichen.
Das konnte ich im ersten Test auch schon simulieren, wenn ich zyklisch Kommuniziere. Letztendlich muss ich Erreignisgesteuert kommunizieren und dabei sicherstellen, dass erforderliche Telegramme auch ankommen.

Das wird sicher auch Problemlos gehen mit dem Arduino Micro.
Der ist schon wirklich sehr schnell.
Ich denke ein STM32 wäre übertrieben, aber sicher Problemlos einfach.
Es ist allerdings sicher nicht verkehrt, sich im voraus über zeitkritische Dinge Gedanken zu machen.
Und ich betrachte Dinge gerne Mal etwas zu kritisch, als man es eigentlich sollte ;)
Letztlich entscheidet die Effizienz des Codes, ob alles einwandfrei funktioniert.
 
Gleichzeitig muss der Hauptcontroller mit allen anderen Teilnehmern kommunizieren und bestenfalls noch eine Software PWM zustande bringen.
Beispielsweise wenn der Arduino mit anderen Aufgaben zu sehr beschäftigt ist, dann funktioniert eine Software PWM nicht zufriedenstellend. Das bedeutet das LEDs flackern, weil sie die erforderliche Frequenz nicht erreichen.

Kann man nicht die Berechnung der Software-PWM vom Slave-Arduino machen lassen? Der Master-Arduino sendet dann also nur ein Signal an den Slave, das er mit den Berechnungen anfangen oder aufhören soll.
 
Hallo Stephan,
teilweise Versuche ich das ganze ja schon modular zu machen.
Mal schauen. Ich werde heute Mal mehrere Empfänger Signale auswerten und schauen, wie die raus kommen.
 
So ich hab mal 4 Empfänger Impulse per Interrupt analysiert.
Die Signale kommen versetzt zueinander in einem Abstand von ein paar hundert Microsekunden herein.
Dem Controller bleiben damit, denke ich, zwischendrin genug Zeit um andere Dinge verarbeiten zu können.
Eine Funktion wie pulseIn() würde allerdings aufgrund dessen, dass sie versetzt sind, dazu führen das einzelne Impulse verpasst würden.
Für reine Servo Signale wäre das unkritisch, aber für das Multiswitch Signal ist es wichtig, dass alle Impulse erkannt werden, da sonst die Reihenfolge durcheinander kommt.

Denn pulseIn() wartet die Zeit ab von steigender bis fallender Flanke. Alles was innerhalb dieser Zeit geschieht bekommt man nicht mit.
Anders beim Interrupt. Hier wird lediglich die eine Flanke erkannt, welche man sich nur zeitlich abspeichern muss. Das heißt der Controller kann sofort weiter arbeiten.

Damit bin ich beruhigt und kann so weiter arbeiten.
 
Hallo Marina,

ich vermute du wirst dann die "Pin Change Interrupts" benutzen?
Das währe dann interessant die genaue Konfiguration der Register zu sehen. Ich habe mir das damals nicht angetan, bei mir hat "pulseIn" funktioniert. War ja auch nur ein einfache Schalteingang der noch über ein Array geglättet wurde.
 
Hallo Bert,

Nein ich nutze die bereits von haus aus definierten Interrupt Pins (0, 1, 2, 3, 7)
https://www.arduino.cc/reference/de/language/functions/external-interrupts/attachinterrupt/

Wenn es nur ein Kanal ist und das Programm nicht riesig ist, ist pulseIn auch voll in Ordnung. Erst wenn's mehr wird oder so kritische Sachen wie Multiswitch PPM dabei sind, ist es nicht zu empfehlen.

Es ist von daher nicht notwendig mehr zu definieren.

Ach und gute Idee mit dem Filter! Vielleicht brauche ich das an mancher stelle auch.
 
So hab mal den ersten Entwurf, wie meine Platine aussehen könnte.
Die Belegung ist noch nicht final.
Hab jetzt mal ein MAX485 für RS485 Kommunikation eingeplant, obwohl ich mich noch nicht entschieden hab, ob ich ihn nutzen soll.

Vorab habe ich zwei Multiswitch Eingänge vorgesehen für eventuell weitere Funktionen auf anderen Modulen.
Als Endstufen nutze ich ganz einfach Darlington Arrays, welche Masse geschaltet sind.
Die Schaltausgänge von Servonaut sind Massegeschaltet und gehen einmal auf Eingänge und lassen sich so auch direkt weiter verwenden.

2020-06-01 22_47_33-Window.jpg
 
Was etwas blöd bei der Kommunikation ist, ist die Blinkfunktion.
Ich muss diese ja Zeitgleich übertragen, damit am Auflieger der Blinker möglichst synchron Blinkt.
Gleichzeitig sollte die Kommunikation unabhängig von den Verknüpften Teilnehmern weiterhin reibungslos funktionieren.
Die Überlegung wäre zu prüfen wer gerade am Bus hängt, allerdings muss ich dabei auf eine Antwort warten.
Wenn genau dann der Blinker aktiv ist, führt das unweigerlich zu einer Verzögerung.
Gerade ein Auflieger kann mal da sein oder nicht.

Am besten wäre es, dass das sofort erkannt wird.

Prinzipiell kann es mir ja auch egal sein, ob die Teilnehmer antworten. Also könnte ich ja auch eine Art Broadcast machen.
Das heißt das ich einfach alle Daten auf dem Bus sende und die entsprechenden Teilnehmer schauen selbst, ob sie das gebrauchen können und antworten nicht.
Das versende ich bei Datenänderung oder nach einer bestimmten Zeit. Letztlich wird der Bus so am wenigsten belastet.
Heißt die Teilnehmer können sich auf das wesentliche konzentrieren.

Das wäre zumindest mal ein Anfang. Später würde ich das gerne so ausweiten, das sich die Teilnehmer anmelden.
Wobei ich mich selbst noch frage wozu ich das machen sollte. Es bring mir kaum bis gar keinen nutzen.
Das würde mir nur was bringen, wenn ich irgendwelche Funktionen hätte, wo ich wirklich eine Antwort brauche.
Von daher sollte ich es direkt so programmieren, dass die Teinehmer unterscheiden können ob es ein Broadcast ist oder nicht.
 
Hallo Marina,

schick doch einfach nur das Startsignal für den Blinker und lass ihn dann bis zu einem Stop oder x-mal blinken.
Start uns Stopsignal könnten 2-3 mal gesendet werden um sicher zu gehen das das Signal empfangen wurde. Die paar ms Zeitversatz wird man sicher nicht sehen
 

Servonaut
Zurück
Oben Unten