//-------------Lichtanlage; Programm für den Bulli T2 und andere RC Fahrzeuge
//
// Werte Ausgelegt für Multiplex Flex und Arduino Pro Mini At-Mega 328 (5V, 16 MHz)
// Funktionen:
// -----------
// * Empfängereingang für Kanal 1 Lenkung, Zur Blinklichtabschaltungsüberwachung.
// * Empfängereingang für Kanal 2 Gas, für Bremslicht und Rückfahrscheinwerfer Betätigung
// * Empfängereingang für Kanal 4 Beleuchtungen, Zum Betätigen von Standlicht, Fahrlicht, Blinklicht, Warnblinklicht,
// Rundumlicht und Arbeitsscheinwerfern.
// * Blinkicht rechts - links mit Fahrhebel Kanal 4 nach rechts und links ein- und ausschaltbar. Tippfunktion unter 1 Sek. Dauer.
// * Blinklicht Seite bei eingeschaltetem Blinklicht wechselbar.Tippfunktion unter 1 Sek. Dauer.
// * Blinklicht nur durch Blinkerhebel oder Lenkungsrückstellung (wie beim original PKW) ausschaltbar.
// * Warnblinkanlage schaltet keine Blinkereinstellung ab. Der Blinkerstatus wird beim Einschalten
// der Warnblinkanlage gespeichert, und nach dem Ausschalten wieder hergestellt.
// * Warnblinkanlage mit Fahrhebel Kanal 4 mehr als 1,0 Sekunden nach links halten jeder Zeit einschaltbar.
// * Warnblinkanlage ausschalten durch erneutes 1,0 Sekunden langes Betätigen des Fahrhebels Kanal 4 nach links.
// * Standlicht als Kombination in einer LED mit dem Fahrlicht oder als eigene LED mit dem Rücklicht anschließbar.
// * Stand- und Rücklicht mit Fahrhebel Kanal 4 mehr als 1,0 Sekunden nach rechts halten jeder Zeit einschaltbar.
// * Fahr- und Rücklicht mit Fahrhebel Kanal 4 mehr als 2,0 Sekunden nach rechts halten jeder Zeit einschaltbar.
// * Fahrlicht ausschalten durch erneutes 1,0 oder 2,0 Sekunden langes Betätigen des Fahrhebels Kanal 4 nach rechts. Standlicht wird eingeschaltet.
// * Stand- und Rücklicht ausschalten durch erneutes 1,0 Sekunden langes Betätigen des Fahrhebels Kanal 4 nach rechts.
// * Realistischer Rückfahrscheinwerfer. Der Rückfahrscheinwerfer geht an sobald der Gas Hebel (Kanal 2) auf Rückwärtsfahrt gezogen wird.
// * Der Rückfahrscheinwerfer geht erst dann wieder aus, wenn der Gashebel in Stellung Vorwärtsfahrt bewegt wird,
// oder mehr als 7 Sekunden in Neutralstellung steht.
// * Bremslicht sowohl als separate LED für das Bremslicht als auch mit einer LED in Kombination mit dem Rücklicht anschließbar.
// * Alle Bremslichtfunktionen funktionieren sowohl bei Vor- als auch bei Rückwärtsfahrt.
// Das Bremslicht wird eingeschaltet wenn innerhalb einer festgelegten kurzen Zeit ein bestimmter Wert an Gas schnell zurück genommen wird.
// (Ruckartiges Gas weg nehmen)
// Langsames Gas weg nehmen betätigt dagegen kein Bremslicht.
// Zittern mit dem Gashebel in einer Fahrstellung oder kurze Impulsschwankungen die zu Bremslichtfunktionen führen werden unterdrückt.
// Führt ruckartiges Gas weg nehmen zu einer Bremslichtfunktion bleibt das Bremslicht mindestens 200 Millisekunden an,
// um zu einem sichtbaren Effekt zu führen.
// Erreicht der Gashebel die Neutralstellung wird immer das Bremslicht eingeschaltet. Es sei denn, man nimmt extrem langsam das Gas weg
// (Ausrollfunktion). Wenn der Gashebel 5 Sekunden in Neutralstellung steht, wird das Bremslicht wieder abgeschaltet.
// Wird Der Gasknüppel aus der Neutralstellung in eine Fahrtstellung gebracht wird das Bremslicht sofort wieder ausgeschaltet.
// * Arbeitsscheinwerfer durch mit Fahrhebel Kanal 4 mehr als 3 Sekunden nach rechts halten jeder Zeit einschaltbar.
// * Arbeitsscheinwerfer durch mit Fahrhebel Kanal 4 mehr als 3 Sekunden nach rechts halten jeder Zeit ausschaltbar.
// * Rundumlicht oder andere Funktion mit Fahrhebel Kanal 4 mehr als 2 Sekunden nach links halten jeder Zeit einschaltbar.
// * Rundumlicht oder andere Funktion ausschalten durch erneutes 2 Sekunden langes Betätigen des Fahrhebels Kanal 4 nach links.
// * Automatisches Einschalten von Rundumlicht und Arbeitsscheinwerfer durch andere Modellfunktionen. Schalteingang -5 Volt.
//---------------------------------------------------------------------------------------------------------------------------------
// Betriebs- und Anschlusshinweise
//---------------------------------------------------------------------------------------------------------------------------------
// * Die Lichtplatine wird mit 5 Volt Versorgungsspannung betrieben und der Minuspol muss mit dem Minuspol des Akkus verbunden sein!
// * der maximale Ausgangsstrom je Ausgang beträgt 40 mA !!!!
// * Scheinwerfer-LED werden in Reihe geschaltet und müssen mit passenden Vorwiderständen Zur Akkuspannung versehen werden.
// * Standlicht-LED vorne werden in Reihe geschaltet und müssen mit passenden Vorwiderständen Zur Akkuspannung versehen werden.
// * Alle Licht-LED brauchen den passenden Vorwiderstand für 20 mA (volle Helligkeit)
// Die Helligkeit von Stand- und Rücklicht werden über PWM-Signal gesteuert.
// * Die Blinklicht-LED können durch höhere Widerstandswerte in der Helligkeit angepasst werden.
// * Die Blinklicht-LED sollten vordere und hintere in Reihe geschaltet werden. So ergibt sich je Blinkerseite ein Strom von 20 mA.
// Und so ist es möglich auch noch einen Anhänger mit Blinklichtstrom zu versorgen.
// * Die kombinierten Rück- und Bremslichter werden ebenfalls in Reihe geschaltet.
// * Separate Rücklichter (in Reihe geschaltet) lassen sich mit dem Standlichtausgang zusammenschalten.
// Allerdings steht dann kein Aausgang mehr für Anhängerrücklicht zur Verfügung.
// Soll ein Anhänger angeschlossen weden, ist es sinnvoll sowohl Anhänger als auch Zugfahrzeug mit kombiniertem Rück- und Bremslicht zu versehen.
//---------------------------------------------------------------------------------------------------------------------------------
// Anschluss Belegungen
//---------------------------------------------------------------------------------------------------------------------------------
// * Pin 2 Eingang wo das Empfängersignal eingelesen wird! Für RC-Kanal 2 Interrupt (Gas)
// * Pin 3 Eingang wo das Empfängersignal eingelesen wird! Für RC-Kanal 4 Interrupt (Licht)
// * Pin 4 Ausgang für Rückfahrscheinwerfer (max.40 mA)
// * Pin 5 Ausgang für Bremslicht und Rücklicht mit PWM (max.40 mA)
// * Pin 6 Ausgang für Fahrlicht (max.40 mA)
// * Pin 7 Ausgang für Rückfahrwarner (Pieper) (max.40 mA)
// * Pin 8 Eingang Lenkkanal-Impulse (pulseIn)
// * Pin 9 Ausgang für Licht (max.40 mA)
// * Pin 10 Ausgang Blinker links (max.40 mA)
// * Pin 11 Ausgang Blinker rechts (max.40 mA)
// * Pin 12 Ausgang Rundumkennleuchte bei Bedarf oder andere Funktion (max.40 mA)
// * Pin 13 Ausgang für Arbeitsscheinwerfer (max.40 mA) und Arduino-interne LED
//---------------------------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------------------------
// Variablen für den Interrupt bei Gasknüppelbetätigung
//---------------------------------------------------------------------------------------------------------------------------------
//---------------------------- Die letzten 8 Werte werden gespeichert um einen Mittelwert zu bilden
volatile uint16_t EmpfaengerKanal2Wert[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500};
volatile uint16_t EmpfaengerKanal2WertSum = 12000; // Die Summe der letzten 8 Werte
volatile uint8_t EmpfaengerKanal2WertIndex = 0; // Der Index des naechsten auszutauschenden Wwets
volatile uint32_t LetzterEmpfaengerWert = micros(); // Letzter Zeitpunkt des Signalwechsels
volatile uint16_t AktuellerEmpfaengerWert = 1500; // Der aktuell als letztes ermittelte Wert
volatile uint8_t LetzterInterruptStatus = PIND; // Interruptstatus des PortD
//------------------------------------------------------------------------------------------------------------------------------------
volatile int RcInValue; // Eingelesener Wert der immer aus dem RAM kommt (w.g. volatile)
volatile int ReceivedLightValues[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // Array mit 8 Werten für die gemessenen Werte
volatile int Summe = 12000; // Summe aus dem Array 8x1500, als Anfangswert
volatile int Mittelwert_K4 = 1500; // Mittelwert aus der Summe für RC-Kanal 4
volatile int Zeiger = 0; // Zeiger für das Array, fängt mit 0 an
volatile uint32_t LastLightChange = micros();
//
// Die Interrrupt Routine wird bei jedem Signalwechsel zwischen HIGH und LOW aufgerufen
// Die Routine beruecksichtigt die HIGH Level und errechnet aus den letzten 8 HIGH Level Werten einen Mittelwert
// Dies glättet mögliche Ausreißer und beseitigt kleinere Schwankungen.
//
//-------------- Pinbelegung - Constante Variablen Deklaration ----------------------------------------
//
const byte pw = 2; // das ist Interrupt 0 aber Pin 2 wo das Empfängersignal eingelesen wird! Für RC-Kanal 2 (Gas)
const byte PIN_RC = 3; // das ist Interrupt 1 aber Pin 3 wo das Empfängersignal eingelesen wird! Für RC-Kanal 4 (Licht)
const byte rfsch = 4; // Pin für Rückfahrscheinwerfer
const byte brakelight = 5; // Pin für Bremslicht und Rücklicht mit PWM
const byte headlight = 6; // Pin für Fahrlicht
const byte light = 9; // Pin für Licht
const byte lenk_in = 8; // Eingang Lenkkanal-Impulse
const byte piep = 7; // Ausgang für Rückfahrwarner
const byte bl = 10; // Pin Blinker links
const byte br = 11; // Pin Blinker rechts
const byte rkl = 12; // Pin RKL bei Bedarf oder andere Funktion
const byte al = 13; // interne LED und Ausgang für Arbeitsscheinwerfer
//
//------------- Einstellbare Werte - Constante Variablen Deklaration ---------------------------------------
const byte light_pwm = 20; // PWM-Wert für Standlicht (hier einstellbar)
const byte Aus = 0; // Zustand Aus auf 0 setzen
const byte gastoleranz = 10; // Toleranz für die Knüppelbewegung, bis Bremslichtvorgang eingeleitet wird. (milliseconds)(hier einstellbar)
const byte brakecounter_max = 3; // Maximaler Inhalt des Fehlerzählers. (X mal)(hier einstellbar)
const long brakelighttime = 5000; // Zeit wie lange das Bremslicht nach Fahrzeugstillstand noch leuchtet. (milliseconds)(hier einstellbar)
const long brakelighttime_min = 200; // Zeit wie lange das Bremslicht bei Betätigung mindestens leuchtet. (milliseconds)(hier einstellbar)
const long rfsch_ontime = 700; // Zeit wie lange der Rückfahrscheinwerfer nach Fahrzeugstillstand noch leuchtet. (milliseconds)(hier einstellbar)
const long Zeit_1 = 1000; // Überwachte kurze Zeit für Knüppeleinschlag in Millisekunden (hier einstellbar)
const long Zeit_2 = 2000; // Überwachte lange Zeit für Knüppeleinschlag in Millisekunden (hier einstellbar)
const long Zeit_3 = 3000; // Überwachte lange Zeit für Knüppeleinschlag in Millisekunden (hier einstellbar)
const long retourbeginn = 1600; // Knüppelbewegungsweg Kanal 2 ab wann Rückfahrscheinwerfer eingeschaltet wird. (hier einstellbar)
//
//-------------- Byte Variablen deklaration -----------------------------------
byte vb = 75; // Variable für gemapte Impulse Wert = Mittelstellung Blinker
byte vw = 75; // Variable für gemapte Impulse Wert = Mittelstellung Warnblinker
byte re_li = 0; // Flag Blinker rechts(Wert 01)_links(Wert 10)Warnblinker(Wert 11)
byte ledState = LOW; // Blinker Startstatus auf aus setzen
byte bron = 0; // Blinker rechts ein (Wert 1 bei an - 0 bei aus)
byte brof = 0; // Blinker rechts aus (Wert 1 bei an - 0 bei aus)
byte brofok = 0; // Blinker rechts aus (Wert 1 bestätigt - 0 bei unbestätigt)
byte blon = 0; // Blinker links ein (Wert 1 bei an - 0 bei aus)
byte blof = 0; // Blinker links aus (Wert 1 bei an - 0 bei aus)
byte blofok = 0; // Blinker links aus (Wert 1 bestätigt - 0 bei unbestätigt)
byte wbon = 0; // Warnblinker ein
byte rklon = 0; // RKL ein (RundumKennLeuchte)
byte rklof = 0; // RKL aus (RundumKennLeuchte)
byte alon = 0; // Arbeitscheinwerfer ein
byte alof = 0; // Arbeitscheinwerfer aus
byte headlight_on = 0; // Scheinwerfer ein
byte headlight_of = 0; // Scheinwerfer aus
byte light_on = 0; // Standlicht / Rücklicht ein
byte light_of = 0; // Standlicht / Rücklicht aus
byte reliSave = 00; // Speicher für Blinklicht Status
byte schalterRechts = 0; // Flag für Blinkerhebelstellung nach rechts
byte schalterLinks = 0; // Flag für Blinkerhebelstellung nach links
byte sentido = 0; // betätigte Richtung für linken Kreuzknüppel. 1=rechts; 2=links; 3=vorne; 4=hinten
byte rfsch_on = 0; // Rückfahrscheinwerfer (Wert 1 bei an - 0 bei aus)
byte vwf = 0; // Flag für Vorwärtsfahrt
byte brakelight_on = 0; // Flag steht auf "1" wenn Bremslicht leuchtet.
//
//-------------- int Variablen deklaration ----------------------------------------------------------------------------------
int akt_richtung = 0; // Flag für aktuelle Knüppelrichtung: 0 Stand; 1 = Vorwärts; 2 = Rückwärts
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Der Wert von "akt_richtung" bezieht sich nicht auf die Fahrtrichtung, //
// sondern die Richtung der Knüppelbewegung. //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int mem_duration = 0; // Speicher für Emfängerwert Gas
int brakecounter = 0; // Zähler zur Überwachung der Bremsimpulse
int brakelightdaueraus = 0; // Flag ob Bremslicht nach mehr als 5 Sec. Stillstand aus bleiben soll . "1" = ja.
int RKLE = HIGH; // Flag RKL-Eingangszustand
//
//-----------------long Variablen deklaration -------------------------------------------------------------------------------
long time = 0;
//---------------- unsigned long Variablen Dejklaration ---------------------------------------------------------------------
unsigned long aktTime = 0; // reset Speicher für aktuelle Zeit
unsigned long countMillis = 0; // reset Zeitzähler
unsigned long int interval = 700; // Zeit für Langeshalten des Steuerküppels nach rechts oder links (hier einstellbar)
unsigned long int blinterval = 600; // Blinkintervall (hier einstellbar)
unsigned long currentMillis = 0; // aktuell gültige Zeit
unsigned long currentbrakeMillis = 0; // aktuell gültige Zeit
unsigned long currentrfschMillis = 0; // aktuell gültige Zeit
unsigned long previousbrakeMillis = 0; // will store last time
unsigned long previousrfschMillis = 0; // will store last time
unsigned long previousMillis = 0; // zuletzt gespeicherte Zeit
unsigned long lenk; // Lenkeinschlagauswertung vom Empfänger
unsigned long dw; // zur Zeit nicht benutzt Pulse in Kanal 4 Futaba Warnlicht - RKL
unsigned long timeStart = 0; // Zeit bei Beginn einer Knüppelbewegung
unsigned long timeStop = 0; // Zeit bei Ende einer Knüppelbewegung
unsigned long timeBegin = 0; // Zeitbeginn in der Zeitkontrolle
unsigned long duration; // Variabele für den vom Interrupt eingelesenen Impuls des Empfängers
//
//
void setup()
{
PCICR |= (1 << PCIE2); // Interrupt Port D aktivieren
PCMSK2 |= (1 << PCINT18); // Interrupts fuer Pins 2 aktivieren
sei();
attachInterrupt( 1, LightPositionInterrupt, CHANGE);
//---------------------------------------------------------------------------------------------------------------
pinMode(pw, INPUT); // Pin 2 Input für Interrupt RC-Empfängersignal Kanal 2 (Gas)
digitalWrite(pw, HIGH); // hier wird der interne Pull-up Widerstand an Pin 2 eingeschaltet
pinMode(PIN_RC, INPUT); // Pin 3 Input für Interrupt RC-Empfängersignal Kanal 4 (Licht)
digitalWrite(PIN_RC, HIGH); // hier wird der interne Pull-up Widerstand an Pin 3 eingeschaltet
pinMode(rfsch, OUTPUT); // Pin 4 Output für Rückfahrscheinwerfer
pinMode(brakelight, OUTPUT); // Pin 5 Output für Bremslicht
pinMode(headlight, OUTPUT); // Pin 6 Output für Fahrlicht
pinMode(light, OUTPUT); // Pin 9 Output für Standlicht
pinMode(lenk_in, INPUT); // Pin 8 zur Zeit unbenutzt
digitalWrite(lenk_in, HIGH); // hier wird der interne Pull-up Widerstand an Pin 8 eingeschaltet
pinMode(piep, OUTPUT); // Pin 7 Ausgang für Rückfahrwarner (Pieper) max. 40 mA!
digitalWrite(piep, HIGH); // hier wird der interne Pull-up Widerstand an Pin 7 eingeschaltet
pinMode(bl, OUTPUT); // Pin 10 Output für Blinklicht links
pinMode(br, OUTPUT); // Pin 11 Output für Blinklicht rechts
pinMode(rkl, OUTPUT); // Pin 12 Output für Rundumkennleuchten
pinMode (al, OUTPUT); // Pin 13 Output für interne LED und Arbeitsscheinwerfer
//---------------------------------------------------------------------------------------------------------------
// Serial.begin(57600); // Einschaltung des seriellen Monitors Zur Programmkontrolle
delay(1500); // Wartezeit auf Empfänger Initialisierung
digitalWrite(light, HIGH); // Standlicht im Setup einschalten
digitalWrite(headlight, HIGH); // Scheinwerfer im Setup einschalten
digitalWrite(al, HIGH); // interne LED ausschalten (aktiv HIGH)
digitalWrite(rkl, HIGH); // Rundumkennleuchte im Setup einschalten
digitalWrite(br, HIGH); // Blinklicht rechts im Setup einschalten
digitalWrite(bl, HIGH); // Blinklicht links im Setup einschalten
digitalWrite(rfsch, HIGH); // Rückfahrscheinwerfer im Setup einschalten
digitalWrite(brakelight, HIGH); // Bremsleuchten im Setup einschalten
digitalWrite(piep, HIGH);
delay(1000); // Eine Sekunde Warteseit im Setup zur Lampenkontrolle
digitalWrite(light, LOW); // Standlicht nach dem Setup ausschalten
digitalWrite(headlight, LOW); // Scheinwerfer nach dem Setup ausschalten
digitalWrite(br, LOW); // Blinklicht rechts nach dem Setup ausschalten
digitalWrite(bl, LOW); // Blinklicht links nach dem Setup ausschalten
digitalWrite(rfsch, LOW); // Rückfahrscheinwerfer nach dem Setup ausschalten
digitalWrite(brakelight, LOW); // Bremsleuchten nach dem Setup ausschalten
digitalWrite(rkl, LOW); // Rundumkennleuchte nach dem Setup ausschalten
digitalWrite(piep, LOW);
}
//---------------------------------------------------------------------------------------------------------------
//---------------------------------------------------------------------------------------------------------------
// Interrupt
//---------------------------------------------------------------------------------------------------------------
ISR(PCINT2_vect)
{
uint8_t PinStatus = PIND; // Aktuellen Stetus der Interrupts lesen
uint8_t PinSignalWechsel = PinStatus ^ LetzterInterruptStatus; // Mit vorherigem Wert verknüpfen
// // Das Ergebnis ist eine Bitliste der ausgelösten Interrupts
if (PinSignalWechsel & (1 << PCINT18)) // Ist das Bit für Pin 2 gesetzt?
Interuppt_Kanal2(); // Ja -> Interrupt auswerten
LetzterInterruptStatus = PinStatus; // Alte Bitmaske merken
}
//---------------------------------------------------------------------------------------------------------------
// Interrupt Ende
//---------------------------------------------------------------------------------------------------------------
void loop() // Programmschleife
{
//---------------------------------------------------------------------------------------------------------------
rfschtest(); // Prüfen ob Rückfahrscheinwerfer eingeschaltet istund wenn ja, dann Pieperintervall einschalten
//---------------------------------------------------------------------------------------------------------------
getlenkung(); // Knüppelstellung für Lenkung (Blinker aus) auslesen
//---------------------------------------------------------------------------------------------------------------
Blinkcontrol(); // Programmteil für die Feststellung ob Blinker abgeschaltet werden darf
//---------------------------------------------------------------------------------------------------------------
blinken(blinterval, re_li); // Im Flag re_li festgelegte Blinker Blinken lasen falls erforderlich
//---------------------------------------------------------------------------------------------------------------
lampen_schalten(); // Lampen schalten mit Übergabe von Lampentyp
//---------------------------------------------------------------------------------------------------------------
loop2(); // Programmteil zur Brems- und Rückfahrlichtsteuerung
//---------------------------------------------------------------------------------------------------------------
} // Ende der gesamten Programmschleife
//---------------------------------------------------------------------------------------------------------------
//////////////////////////////////////////////////////////////////////////////////////////////////
// Programmteil für die Feststellung ob Blinker abgeschaltet werden darf //
// Die Variabel "vw" enthällt die gemappte Signalauswertung für Kanal 1 - Lenkung //
//////////////////////////////////////////////////////////////////////////////////////////////////
void Blinkcontrol()
{
if (lenk != 0) // Fehlerkorektur für Laufzeitfehler. Bei Wert"0" Routine nicht ausführen.
{
if (blon == 1 || bron == 1) // Abfrage 1 - Ist Blinker links oder rechts an? Wenn nein Weiter bei Ende Abfrage 1
{ // // wenn ja
if (vw < 35 || vw > 115) // Abfrage 2 - Weg der Lenkbewegung feststellen
{ // // wenn zwischen 35 und 115 dann ist weit genug eingeschlagen
// // wenn nicht weiter bei Ende Abfrage 2
blof = 1; // Flag setzen das Blinker links ausgemacht werden kann
brof = 1; // Flag setzen das Blinker rechts ausgemacht werden kann
// bron = 0; // ??
} // Ende - Abfrage 2
} // Ende - Abfrage 1
if (blof == 1 || brof == 1) // Abfrage 3 - Wenn Blinker aus gemacht werden kann blof = 1 oder brof = 1
{ // // wenn nicht weiter bei Ende Abfrage 3
if (vw > 60 && vw < 90) // Abfrage 4 - Ist weit genug zuzrück gelenkt? Wenn nicht weiter bei Ende Abfrage 4
{
if (wbon == 0) // Abfrage 5 - Ist Warnblinker ausgeschaltet? Wenn nicht weiter bei Ende Abfrage 5
{
re_li = 00; // Flag für beide Blinker aus setzen
blof = 0; // Flag für Blinker links ausschalten erlaubt wieder auf 0 setzen
brof = 0; // Flag für Blinker rechts ausschalten erlaubt wieder auf 0 setzen
} // Ende - Abfrage 5
} // Ende - Abfrage 4
} // Ende - Abfrage 3
} // Ende Fehlerekorrektur Blinkerabschaltung
} // Ende der Routine
// ---------------------------------------------------------------------------------
// -------------------- Kanal für Gas; Vor- Rückwärts; Bremse ----------------------
void Interuppt_Kanal2()
{
uint32_t nMicros = micros(); // Aktuellen Zeitstempel merken
uint16_t nDifference = (uint16_t)(nMicros - LetzterEmpfaengerWert); // Die Differenz zum letzten Aufruf errechnen
if ( (nDifference > 900 ) && ( nDifference < 2100)) // Zeiten zwischen 900 und 2100 Mikrosekunden sind das HIGH Signal
{
// -------------- Wert in der 4er Liste austauschen und Mittelwert errechnen. Dies erfolgt indem der alte Wert von der Summe subtrahiert wird
EmpfaengerKanal2WertSum -= EmpfaengerKanal2Wert[EmpfaengerKanal2WertIndex]; // Der neue Wert gemerkt wird
EmpfaengerKanal2Wert[EmpfaengerKanal2WertIndex] = nDifference; // Den neuen Wert auf die Summe addieren
EmpfaengerKanal2WertSum += nDifference; // Den Index auf die naechste Position schieben
EmpfaengerKanal2WertIndex = ( ( EmpfaengerKanal2WertIndex + 1 ) & 0x07 ); //Index erhoehen und ggf. von 8 auf 0 springen
// -------------- Den aktuellen Mittelwert errechnen indem die Summe durch 8 geteilt wird
AktuellerEmpfaengerWert = ( EmpfaengerKanal2WertSum >> 3 ); //durch 8 teilen
}
LetzterEmpfaengerWert = nMicros; // Zeitstempel fuer das naechste mal merken
}
// ---------------------------------------------------------------------------------
// -------------------- Kanal für Beleuchtungen ------------------------------------
void LightPositionInterrupt()
{
uint32_t nMicros = micros();
uint16_t nDifference = (uint16_t)(nMicros - LastLightChange);
if ( (nDifference > 900 ) && ( nDifference < 2100)) // Zeiten zwischen 900 und 2100 Mikrosekunden sind das HIGH Signal
{
// -------------- Wert in der 4er Liste austauschen und Mittelwert errechnen. Dies erfolgt indem der alte Wert von der Summe subtrahiert wird
Summe -= ReceivedLightValues[Zeiger]; // Der neue Wert gemerkt wird
ReceivedLightValues[Zeiger] = nDifference; // Den neuen Wert auf die Summe addieren
Summe += nDifference; // Den Index auf die naechste Position schieben
Zeiger = ( ( Zeiger + 1 ) & 0x07 ); // Index erhoehen und ggf. von 8 auf 0 springen
// -------------- Den aktuellen Mittelwert errechnen indem die Summe durch 8 geteilt wird
Mittelwert_K4 = ( Summe >> 3 ); // durch 8 teilen
}
LastLightChange = nMicros; // Zeitstempel fuer das naechste mal merken
//
//---------------------------------------------------------------------------------------------------------------
if (Mittelwert_K4 < 1200) // Wenn Kanal 4 - Knüppel nach rechts betätigt
{
sentido = 1; // Richtung rechts
if (schalterRechts == 0) // wenn Schalter-Flag rechts = "aus"
{
timeStart = millis(); // aktuell gültige Zeit
timeBegin = 0; // Startzeit auf 0 setzen
}
zeitkontrolle(sentido); // gehe zu Unterroutine Zeitkontrolle
}
else if (schalterRechts != 0) // sonst wenn Schalter rechts nicht ausgeschaltet ist
{
Schalter_Rechts(); // gehe zu Unterroutine Schalter_Rechts()
}
//---------------------------------------------------------------------------------------------------------------
if (Mittelwert_K4 > 1800) // Wenn Kanal 4 - Knüppel nach links betätigt
{
sentido = 2; // Richtung links
if (schalterLinks == 0) // wenn Schalter-Flag links = "aus"
{
timeStart = millis(); // aktuell gültige Zeit in timeStart speichern
timeBegin = 0; // Startzeit auf 0 setzen
}
zeitkontrolle(sentido); // gehe zu Unterroutine Zeitkontrolle
}
else if (schalterLinks != 0) // sonst wenn Schalter links nicht ausgeschaltet ist
{
Schalter_Links(); // gehe zu Unterroutine Schalter_Links()
}
}
void Licht_aus(int Li)
{
//digitalWrite (Li, HIGH);
switch (Li)
{
case light:
digitalWrite (headlight, LOW); // Pin 6; Scheinwerfer ausschalten
digitalWrite (light, LOW); // Pin 9; Standlichtausgang ausschalten
digitalWrite (brakelight, LOW); // Pin 5; Bremslicht ausschalten
break;
/*if (light_of == 1)
{
analogWrite (brakelight, 255); // Pin 5; Bremslicht ausschalten.
brakelight_on = 0;
}
else if (light_of == 0)
{
analogWrite (brakelight, light_pwm); // Pin 5; Bremslicht ausschalten und PWM auf Rücklichtwert setzen.
brakelight_on = 0;
}*/
case headlight:
analogWrite (headlight, light_pwm); // Pin 6; Scheinwerfer ausschalten und PWM auf Standlichtwert setzen
analogWrite (light, light_pwm); // Pin 9; Standlichtausgang einschalten
analogWrite (brakelight, light_pwm); // Bremslicht ausschalten und PWM auf Rücklichtwert setzen.
light_of = 1; // Flag für Licht ausschaltbar wieder auf 1 setzen
break;
//
case rkl:
digitalWrite (rkl, LOW);
rklof = 0;
rklon = 0;
break;
//
case al:
digitalWrite (al, LOW);
break;
//
default:
// do nothing;
break;
}
//Li = 0;
}
void Licht_ein(int Li)
{
switch (Li) // Schalte Licht ein
{
case headlight: // falls Wert = 6
analogWrite (headlight, 255); // schalte Pin 6 auf LOW = "ein"
analogWrite (light, light_pwm);
analogWrite (brakelight, light_pwm);
headlight_of = 1;
break;
//
case light: // falls Wert = 9
analogWrite (brakelight, light_pwm);
analogWrite (light, light_pwm);
analogWrite (headlight, light_pwm);
brakelight_on = 0;
light_of = 1;
break;
//
case al: // falls Wert = 13
digitalWrite (al, HIGH);
alof = 1;
break;
//
case rkl: // falls Wert = 12
digitalWrite (rkl, HIGH);
rklof = 1;
break;
//
default:
// do nothing;
break;
}
}
void blinken(int takt, int reli) // übergibt Taktintervall für Blinklicht und welcher Blinker blinken soll.
// // reli steht für rechts oder links
// // reli = 00 = keiner - beide Blinker aus
// // reli = 01 = rechts
// // reli = 10 = links
// // reli = 11 = beide - Warnblinklicht
//---------------------------------------------------------------------------------------------------------------
{ // // Beginn der Routine "void blinken"
currentMillis = millis(); // aktuelle Zeit in Millisekunden speichern
//---------------------------------------------------------------------------------------------------------------
if (reli == 00) // wenn kein Blinklicht an sein soll
{ // // nachfolgende Funktion 1 ausführen
ledState = LOW; // LED Status auf "aus" setzen
digitalWrite(br, ledState); // setzt die LED Blinker-rechts mit dem Status der Variable "ledState" ("aus")
digitalWrite(bl, ledState); // setzt die LED Blinker-links mit dem Status der Variable "ledState" ("aus")
}// // Ende der Funktion 1
//---------------------------------------------------------------------------------------------------------------
else if (currentMillis - previousMillis > takt) // an sonsten wenn die Aktuelle Zeit minus der vorher gespeicherten Zeit größer alls der Takt ist
{ // // Funktion 2 ausführen
previousMillis = currentMillis; // sichert letzte Zeit update LED Status
switch (ledState) // Wechselt LED Zustand ein / aus und umgekehrt (Funktion Blinken)
{
case LOW: // wenn der LED Status = "aus" ist....
ledState = HIGH; // wechseln zu LED Status "ein"
break;
//---------------------------------------------------------------------------------------------------------------
case HIGH: // sonst
ledState = LOW; // wechseln zu LED Status "aus"
break;
//----------------------------------------------------------------------------------------------------------
default:
// do nothing;
break;
}// // Ende der Funktion
}
//---------------------------------------------------------------------------------------------------------------
switch (reli) // schalte Blinklichter
{
case 01: // falls das rechte Blinklicht an sein soll, nachfolgende Funktionen ausführen
digitalWrite(br, ledState); // schaltet die LED "Blinker rechts" mit dem Status der Variable "ledState"
digitalWrite(bl, LOW); // schaltet die LED "Blinker links" "aus"
break; // Ende der Funktion
//---------------------------------------------------------------------------------------------------------------
case 10: // falls das linke Blinklicht an sein soll, nachfolgende Funktionen ausführen
digitalWrite(bl, ledState); // schaltet die LED "Blinker links" mit dem "NOT" Status der Variable "ledState"
digitalWrite(br, LOW); // schaltet die LED "Blinker rechts" "aus"
break; // Ende der Funktion
//---------------------------------------------------------------------------------------------------------------
case 11: // falls beide Blinklichter an sein sollen (Warnblinker), nachfolgende Funktionen ausführen
digitalWrite(br, ledState); // schaltet die LED "Blinker rechts" mit dem Status der Variable "ledState"
digitalWrite(bl, ledState); // schaltet die LED "Blinker links" mit dem Status der Variable "ledState"
break; // Ende der Funktion
//-----------------------------------------------------------------------------------------------------------------
default:
// do nothing;
break;
}// // Ende der Funktion 2
}// // Ende der Routine "void blinken()"
void bremslicht()
{
brakecounter ++; // Bremszähler zählt wie oft die Routine aufgerufen wurde.
if (brakecounter == brakecounter_max) // Wenn das 2. mal dann
{
analogWrite (brakelight, 255); // Bremslicht einschalten (PWM - 0 = voll an, 255 = aus; wegen aktiv LOW)
brakelight_on = 1;
brakecounter = 0; // Bremszähler wieder auf "0" seten - löschen.
delay(brakelighttime_min); // ?? Pause damit bei Microbremsung das Bremslicht z.B. 100 ms leuchtet und nicht nur aufblitzt.
}
}
//---------------- Der Bremszähler verhindert das bei jeder kleinen Wertschwankung vom Empfänger, oder z.B. unruhiger Knüppelhaltung,
//---------------- das Bremslicht aufblitzt.
void getlenkung()
{
lenk = pulseIn(lenk_in, HIGH, 20000); // Kanal 1 938 - 1480 - 2027
vw = map(lenk, 900, 2100, 0, 150);
delay(20);
}
void lampen_schalten()
{
if (rklon == 1 && rklof == 0)
{
rklon = 0;
Licht_ein(rkl); // Rundumkennleuchte einschalten
}
//----------------------------------------------------------------------------------------------------
if (rklon == 1 && rklof == 1)
{
rklon = 0;
rklof = 0;
Licht_aus(rkl); // Rundumkennleuchte ausschalten
}
//----------------------------------------------------------------------------------------------------
if (alon == 1 && alof == 0)
{
alon = 0;
Licht_ein(al); // Arbeitsleuchte einschalten
}
//----------------------------------------------------------------------------------------------------
if (alon == 1 && alof == 1)
{
alon = 0;
alof = 0;
Licht_aus(al); // Arbeitsleuchte ausschalten
}
//----------------------------------------------------------------------------------------------------
if (headlight_on == 1 && headlight_of == 0)
{
headlight_on = 0;
Licht_ein(headlight); // Scheinwerfer einschalten
light_on = 0;
}
//----------------------------------------------------------------------------------------------------
if (headlight_on == 1 && headlight_of == 1)
{
headlight_on = 0;
headlight_of = 0;
Licht_aus(headlight); // Scheinwerfer ausschalten
}
//----------------------------------------------------------------------------------------------------
if (light_on == 1 && light_of == 0)
{
light_on = 0;
Licht_ein(light); // Licht einschalten
}
//----------------------------------------------------------------------------------------------------
if (light_on == 1 && light_of == 1)
{
light_on = 0;
light_of = 0;
Licht_aus(light); // Licht ausschalten
}
}
void loop2()
{
//--------------------------------------------------------------------------------------------------------
//------------ Hier kann nun mit dem Wert von AktuellerEmpfaengerWert vom Interrupt gearbeitet werden ----
//--------------------------------------------------------------------------------------------------------
duration = AktuellerEmpfaengerWert; // Hier wird die aktuelle Steuerknüppelstellung vom Interrupt übernommen.
//-----------------------------------------------------------------------------
//------ Keine Gasknüppelbewegung
//-----------------------------------------------------------------------------
if (duration > 1400 && duration < 1550) // Knüppel befindet sich in Neutralstellung.
{
vwf = 0; // Flag für Vorwärtsfahrt wird auf "0" gesetzt
mem_duration = 0; // Speicher für Knüppelstellung wird auf "0" gesetzt - gelöscht.
akt_richtung = 0; // Flag für aktuelle Knüppelbewegungsrichtung wird auf "0" gesetzt.
currentbrakeMillis = millis(); // aktuell gültige Zeit für Bremslicht Zeitablauf beginn.
currentrfschMillis = millis(); // aktuell gültige Zeit für Rückfahrlicht Zeitablauf beginn.
}
//-----------------------------------------------------------------------------
//------ Rückwärts Gasknüppelbewegung
//-----------------------------------------------------------------------------
if (duration >= retourbeginn) // Knüpel auf Rückwärtsfahrstellung.
{
if (rfsch_on == 0) // Wenn Rückfahrflag auf "aus" steht.
{
digitalWrite(rfsch, HIGH); // Rückfahrscheinwerfer einschalten.
rfsch_on = 1; // Flag für Rückfahrscheinwerfer auf "ein" setzen.
}
if (duration >= mem_duration) // Wenn der Wert für die aktuelle Küppelstellung gleich oder größer als der gespeicherte ist.
{
akt_richtung = 2; // Das Flag für die aktuelle Knüppelbewegungsrichtung wird auf Richtung rückwärts (2) gesetzt.
}
if (duration < mem_duration - gastoleranz) // Wenn der Wert für die aktuelle Knüppelstellung kleiner als der gespeicherte - gastoleranz (50) ist.
{
akt_richtung = -2; // Das Flag für die aktuelle Knüppelbewegungsrichtung wird auf Richtung vorwärts im Rückwärtsfahrbereich(-2) gesetzt.
}
mem_duration = duration; // Aktuelle Knüppelstellung speichern.
//aktmillis = millis(); // Aktuellen Millisekunden Wert speichern.
}
//-----------------------------------------------------------------------------
//------ Vorwärts Gasknüppelbewegung
//-----------------------------------------------------------------------------
if (duration <= 1400) // Knüppel in Vorwärtsfahrstellung.
{
if (duration <= mem_duration) // Wenn der Wert für die aktuelle Küppelstellung gleich oder kleiner als der gespeicherte ist.
{
akt_richtung = 1; // Das Flag für die aktuelle Knüppelbewegungsrichtung wird auf Richtung vorwärts (1) gesetzt.
}
if (duration > mem_duration + gastoleranz) // Wenn der Wert für die aktuelle Knüppelstellung größer als der gespeicherte + gastoleranz (50) ist.
{
akt_richtung = -1; // Das Flag für die aktuelle Knüppelbewegungsrichtung wird auf Richtung rückwärts im Vorwärtsfahrbereich(-1) gesetzt.
}
if (rfsch_on == 1) // Wenn Rückfahrflag auf "ein" steht.
{
digitalWrite(rfsch, LOW); // Rückfahrscheinwerfer ausschalten.
rfsch_on = 0; // Flag für Rückfahrscheinwerfer auf "aus" setzen.
}
if (vwf == 0) // Wenn Flag Vorwärtsfahrt = noch auf "0" (Fahrzeug steht)
{
vwf = 1; // Flag Vorwärtsfahrt auf "1" setzen (Vorwärtsfahrt).
}
mem_duration = duration; // Aktuelle Knüppelstellung speichern.
//aktmillis = millis(); // Aktuellen Millisekunden Wert speichern.
}
//---------------------------------------------------------------------------------
//---------Kontrolle ob Bremslicht ein oder aus geschaltet wird -------------------
//---------------------------------------------------------------------------------
if (akt_richtung == -1 || akt_richtung == -2) // Knüppelbewegung gegen die Fahrtrichtung erfordert Bremslichtbehandlung.
{
bremslicht(); // Bremslichtroutine wird aufgerufen.
//delay(brakelighttime_min); // Pause damit bei Microbremsung das Bremslicht z.B. 100 ms leuchtet und nicht nur aufblitzt.
}
//-----------------------------------------------------------------------------------
if (akt_richtung == 0) // Knüppel hat Neutralstellung erreicht und erfordert Bremslichtbehandlung.
{
if (brakelight_on == 1)
{
if (brakelightdaueraus == 0) // Wenn das Flag für "Fahrzeug steht länger als 5 Sec." auf "0" steht.
{ // // Also weniger als 5 Sec. Standzeit.
bremslicht(); // Bremslichtroutine wird aufgerufen.
}
if (currentbrakeMillis - previousbrakeMillis >= brakelighttime)
{
previousbrakeMillis = currentbrakeMillis; // speichert die letzte Zeit bei Bremslichtbeginn.
if (light_of == 0)
{
analogWrite (brakelight, 0); // Bremslicht ausschalten.
brakelight_on = 0;
}
else if (light_of == 1)
{
analogWrite (brakelight, light_pwm); // Bremslicht ausschalten und PWM auf Rücklichtwert setzen.
brakelight_on = 0;
}
brakelightdaueraus = 1; // Das Flag für Bremslicht dauerhaft ausbleiben wird auf "1" gesetzt. Das Fahrzeug steht länger als 5 Sec.
}
}
if (rfsch_on == 1) // Wenn Rückfahrlichtflag auf "ein" steht.
{
if (currentrfschMillis - previousrfschMillis >= rfsch_ontime)
{
previousrfschMillis = currentrfschMillis; // speichert die letzte Zeit bei Rückfahrlichtlichtbeginn.
digitalWrite(rfsch, LOW); // Rückfahrscheinwerfer ausschalten.
rfsch_on = 0; // Flag für Rückfahrscheinwerfer auf "aus" setzen.
}
}
}
//----------------------------------------------------------------------------------------------
if (akt_richtung == 1 || akt_richtung == 2) // Knüppelbewegung in eine Fahrtrichtung bei leuchtendem Bremslicht erfordert Bremslichtbehandlung.
{
brakelightdaueraus = 0; // Das Flag für Bremslicht dauerhaft ausbleiben wird auf "0" gesetzt.
if (light_of == 0)
{
analogWrite (brakelight, 0); // Bremslicht ausschalten.
brakelight_on = 0;
}
else if (light_of == 1)
{
analogWrite (brakelight, light_pwm); // Bremslicht ausschalten und PWM auf Rücklichtwert setzen.
brakelight_on = 0;
}
brakelightdaueraus = 1; // Das Flag für Bremslicht dauerhaft ausbleiben wird auf "1" gesetzt. Das Fahrzeug steht länger als 5 Sec.
}
}
//-----------------------------------------------------------------------------------
//-------------------- Loop2 Ende
//--------------------------------------------------------------------------------
void rfschtest()
{
if (rfsch_on == 1)
{
digitalWrite(piep, HIGH);
delay (500);
digitalWrite(piep, LOW);
delay (500);
}
}
//--------------- Schalter nach links auswerten---------------------------------------------------------
void Schalter_Links()
{
if (time < Zeit_1)
{
blon = 1;
if (re_li != 11)
{
if (re_li == 10)
{
re_li = 00;
}
else
{
re_li = 10;
}
}
time_delete();
schalterLinks = 0;
}
if (time > Zeit_1 && time < Zeit_2)
{
if (wbon == 0)
{
wbon = 1;
if (re_li == 01 || re_li == 10)
{
reliSave = re_li;
}
re_li = 11;
}
else
{
wbon = 0;
re_li = reliSave;
reliSave = 00;
}
time_delete();
schalterLinks = 0;
}
if (time > Zeit_2) // && time < Zeit_3)
{
rklon = 1;
time_delete();
schalterLinks = 0;
}
}
//--------------- Schalter nach rechts auswerten---------------------------------------------------------
void Schalter_Rechts()
{
if (time < Zeit_1)
{
bron = 1;
if (re_li != 11)
{
if (re_li == 01)
{
re_li = 00;
}
else
{
re_li = 01;
}
}
time_delete();
schalterRechts = 0;
}
if (time > Zeit_1 && time < Zeit_2)
{
light_on = 1;
time_delete();
schalterRechts = 0;
}
if (time > Zeit_2 && time < Zeit_3 )
{
headlight_on = 1;
time_delete();
schalterRechts = 0;
}
if (time > Zeit_3 )
{
alon = 1;
time_delete();
schalterRechts = 0;
}
}
void time_delete()
{
time = 0;
timeBegin = 0;
aktTime = 0;
timeStart = 0;
}
void zeitkontrolle(int direction)
{
if (timeBegin == 0)
{
timeBegin = timeStart;
switch (direction)
{
case 1:
schalterRechts = 1;
break;
case 2:
schalterLinks = 1;
break;
default:
// do nothing;
break;
}
}
aktTime = millis(); // aktuell gültige Zeit
time = aktTime - timeBegin; // festgestellte Zeit = Aktuelle Zeit minus Anfangszeit
}