- Registriert
- 22.07.2007
- Beiträge
- 72
... oder das Frankenstein-Programm
Anbei mal ein Programmentwurf fuer einen Bruder Claas Xerion Umbau, welches auf diesem Thema aufbaut.
Ziel ist es mit einer herkoemmlichen 4-Kanal-Anlage soviele Funktionen wie moeglich in einem Bruder Claas Xerion zu bekommen.
Warum Frankenstein-Programm? Das Programm besteht aus vielen Teilen von Programmen, die hier schon einmal vorgestellt wurden. Die Formatierung ist (noch) nicht schoen und sauber, aber
es laeuft zufriedenstellen.
Verwendet wurden Auszuege aus Winnis Lichtsteuerung, Gismows Multiswitch, einem Programm zur Allradlenkung aus dem Rockcrawler-Froum, einigen Arduino-Beispielen usw.
Faktenheft:
- Fernsteuerung Futaba FC-16 mit Jeti Duplex 2,4GHz
- Blocher Xerion Fahrgestell mit servogesteuerten Heckheber
- FMB Geiger Frontheber
- 12V Bordspannung mit S22-Servonaut Fahrregler
- vollstaendige Lichtanlage
- automatische Nullpunktermittlung beim Einschalten
- Kontrolle Empfaengersignal beim Einschalten
- Auslesen aller 4 Kanaele mittels Interrupt
- Kanal 1 - Lenkung
- Kanal 2 - Gas
- Kanal 3 - Steuerung Front- und Heckheber
- Kanal 4 - Schalter fuer Licht, usw.
- verschiedene Lenkprogramme
- Ansteuerung Licht, Front- und Heckheber
- Steuerung:
rechter Steuerknueppel hoch/runter - Gas/Bremse
rechter Steuerknueppel links/rechts - Lenkfuntion
linker Steuerknueppel hoch/runter - Heben/Senken des Front- bzw. Heckhebers
linker Steuerknueppel links/rechts - kurze Tippbewegung - Blinker,
2x rechts - Warnblinker an/aus
3x rechts - Rundumleuchte an/aus
4x rechts - Lenkung normal
5x rechts - Allradlenkung
6x rechts - Hundegang
2x links - Abblendlicht an/aus
3x links - Fernlicht an/aus
4x links - Arbeitsscheinwerfer an/aus
5x links - Frontheber an
6x links - Heckheber an
Das Programm und die Beschreibung ist noch nicht vollstaendig und wird noch ueberarbeitet!
Link 1: https://forum.arduino.cc/index.php?topic=187864.0
Link 2: https://www.hackster.io/ashraf_minh...er2-library-simple-explain-servo-sweep-512fd9
Viel Spaß!
Anbei mal ein Programmentwurf fuer einen Bruder Claas Xerion Umbau, welches auf diesem Thema aufbaut.
Ziel ist es mit einer herkoemmlichen 4-Kanal-Anlage soviele Funktionen wie moeglich in einem Bruder Claas Xerion zu bekommen.
Warum Frankenstein-Programm? Das Programm besteht aus vielen Teilen von Programmen, die hier schon einmal vorgestellt wurden. Die Formatierung ist (noch) nicht schoen und sauber, aber
es laeuft zufriedenstellen.
Verwendet wurden Auszuege aus Winnis Lichtsteuerung, Gismows Multiswitch, einem Programm zur Allradlenkung aus dem Rockcrawler-Froum, einigen Arduino-Beispielen usw.
Faktenheft:
- Fernsteuerung Futaba FC-16 mit Jeti Duplex 2,4GHz
- Blocher Xerion Fahrgestell mit servogesteuerten Heckheber
- FMB Geiger Frontheber
- 12V Bordspannung mit S22-Servonaut Fahrregler
- vollstaendige Lichtanlage
- automatische Nullpunktermittlung beim Einschalten
- Kontrolle Empfaengersignal beim Einschalten
- Auslesen aller 4 Kanaele mittels Interrupt
- Kanal 1 - Lenkung
- Kanal 2 - Gas
- Kanal 3 - Steuerung Front- und Heckheber
- Kanal 4 - Schalter fuer Licht, usw.
- verschiedene Lenkprogramme
- Ansteuerung Licht, Front- und Heckheber
- Steuerung:
rechter Steuerknueppel hoch/runter - Gas/Bremse
rechter Steuerknueppel links/rechts - Lenkfuntion
linker Steuerknueppel hoch/runter - Heben/Senken des Front- bzw. Heckhebers
linker Steuerknueppel links/rechts - kurze Tippbewegung - Blinker,
2x rechts - Warnblinker an/aus
3x rechts - Rundumleuchte an/aus
4x rechts - Lenkung normal
5x rechts - Allradlenkung
6x rechts - Hundegang
2x links - Abblendlicht an/aus
3x links - Fernlicht an/aus
4x links - Arbeitsscheinwerfer an/aus
5x links - Frontheber an
6x links - Heckheber an
Das Programm und die Beschreibung ist noch nicht vollstaendig und wird noch ueberarbeitet!
Code:
/* Modul Projekt Claas Xerion komplett - Version 3 - Dezember 2019
- Faktenheft
- vollstaendige Lichtanlage
- automatische Nullpunktermittlung beim Einschalten
- Auslesen aller Servosignale mittels Interrupt
- Kanal 1 - Lenkung
- Kanal 2 - Gas
- Kanal 3 - Steuerung Front- und Heckheber
- Kanal 4 - Schalter fuer Licht, usw.
- verschiedene Lenkprogramme
- Ansteuerung Licht, Front- und Heckheber
Den Code kann und darf jeder fuer sich aendern, solange es eine private Nutzung ist. Der Code wurde nur zum Einsatz in privaten Modellfahrzeugen erstellt.
Jede andere Nutzung ist widerrechtlich. Gewerbliche Nutzung des Codes ist untersagt und wird rechtlich verfolgt.
Eine gewerbliche Nutzung ist nur gegen Lizenzgebuehr moeglich. Es wird keine Haftung fuer Folgeschaeden welche sich aus der Nutzung des Codes ergeben
koennten uebernommen.
Der Einsatz erfolgt auf eigene Gefahr und eigenes Risiko.
Mit der Nutzung diese Codes erklaert sich der Nutzer hiermit einverstanden.
* Pin 2 Eingang wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 2 Interrupt (Gas)
* Pin 3 Eingang wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 1 Interrupt (Lenkung)
* Pin 4 Ausgang fuer Rueckfahrscheinwerfer (max.40 mA)
* Pin 5 Ausgang fuer Bremslicht und Ruecklicht mit PWM (max.40 mA)
* Pin 6 Ausgang fuer Fahrlicht (max.40 mA)
* Pin 7 Eingang wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 4 Interrupt (Schalter)
* Pin 8 frei
* Pin 9 Ausgang fuer 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 fuer Arbeitsscheinwerfer (max.40 mA) und Arduino-interne LED
- Auslesen der vier Kanalwerte mittels der Interruptroutine <> Konflikt mit der Servo.h - Bibliothek (beide benutzen den Timer1 des Nanos
--> Verwendung der ServoTimer2-Bibliothek
Pin 14 (A0) Servo 1
Pin 15 (A1) Servo 2
Pin 16 (A2) Servo 3
Pin 17 (A3) Servo 4
Pin 18 (A4) Eingang wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 3 Interrupt (Funktion)
---------------------------------------------------------------------------------------------------------------------------------
laut hier koennen die analogen Pins auch fuer LEDs usw. genutzt werden : siehe Link 1
ServoTimer2 - Bibliothek --> siehe Link 2
*/
#include <ServoTimer2.h>
#define debug
#define pinServo1 14 // Pin 14 (Analog0) Ausgang, wo das Signal fuer Servo 1 ausgegeben wird
#define pinServo2 15 // Pin 15 (Analog1) Ausgang, wo das Signal fuer Servo 2 ausgegeben wird
#define pinServo3 16 // Pin 16 (Analog2) Ausgang, wo das Signal fuer Servo 3 ausgegeben wird
#define pinServo4 17 // Pin 17 (Analog3) Ausgang, wo das Signal fuer Servo 4 ausgegeben wird
//Variablen
//RC-bezogen
int cnt_CH_1 = 0; //Zaehler Channel 1 fuer Interruptroutine
int frqraw_CH_1 = 0; //Uebergabewert Channel 1 aus Interruptroutine
int cnt_CH_2 = 0; //Zaehler Channel 2 fuer Interruptroutine
int frqraw_CH_2 = 0; //Uebergabewert Channel 2 aus Interruptroutine
int cnt_CH_3 = 0; //Zaehler Channel 3 fuer Interruptroutine
int frqraw_CH_3 = 0; //Uebergabewert Channel 3 aus Interruptroutine
int cnt_CH_4 = 0; //Zaehler Channel 4 fuer Interruptroutine
int frqraw_CH_4 = 0; //Uebergabewert Channel 4 aus Interruptroutine
// Variablen fuer die Lenkung
volatile uint16_t Empfaenger_Kanal1_Wert[4] = {1500, 1500, 1500, 1500}; // Die letzten 4 Werte werden gespeichert um einen Mittelwert zu bilden
volatile uint16_t Empfaenger_Kanal1_Wert_Summe = 6000; // Die Summe der letzten 4 Werte
volatile uint8_t Empfaenger_Kanal1_Wert_Index = 0; // Der Index des naechsten auszutauschenden Werts
// Variablen fuer die Gasstellung
volatile uint16_t Empfaenger_Kanal2_Wert[4] = {1500, 1500, 1500, 1500}; // Die letzten 4 Werte werden gespeichert um einen Mittelwert zu bilden
volatile uint16_t Empfaenger_Kanal2_Wert_Summe = 6000; // Die Summe der letzten 4 Werte
volatile uint8_t Empfaenger_Kanal2_Wert_Index = 0; // Der Index des naechsten auszutauschenden Werts
// Variablen fuer die Funktionsstellungstellung
volatile uint16_t Empfaenger_Kanal3_Wert[4] = {1500, 1500, 1500, 1500}; // Die letzten 4 Werte werden gespeichert um einen Mittelwert zu bilden
volatile uint16_t Empfaenger_Kanal3_Wert_Summe = 6000; // Die Summe der letzten 4 Werte
volatile uint8_t Empfaenger_Kanal3_Wert_Index = 0; // Der Index des naechsten auszutauschenden Werts
// Variablen fuer die Schaltung
volatile uint16_t Empfaenger_Kanal4_Wert[4] = {1500, 1500, 1500, 1500}; // Die letzten 4 Werte werden gespeichert um einen Mittelwert zu bilden
volatile uint16_t Empfaenger_Kanal4_Wert_Summe = 6000; // Die Summe der letzten 4 Werte
volatile uint8_t Empfaenger_Kanal4_Wert_Index = 0; // Der Index des naechsten auszutauschenden Werts
volatile uint32_t LetzterSchaltungWechsel = micros();
//volatile uint32_t LastChannelMultiswitchChange = micros();
// Variablen und Defines fuer die Realisierung eines Multiswitch Kanals
#define MultiswitchStateUndefined 0
#define MultiswitchStateCenter 1
#define MultiswitchStateUp 2
#define MultiswitchStateDown 3
// Maximal- bzw. Minimalwert des Kanals. Zur Initialisierung werden diese mit festen Werten definiert,
// welche eine Standard Funke liefern koennen sollte. Bei Bedarf koennen diese auch angepasst werden.
uint16_t MeasuredMultiswitchUp = 1950;
uint16_t MeasuredMultiswitchDown = 1100;
// Der Nullpunkt des Multiswitch Kanals wird beim Start ermittelt. Der hier festgelegte Wert ist eigentlich nicht notwendig.
uint16_t ErmittelterNullpunktSchaltung = 1500;
// Das Programm geht davon aus dass eine Bewegung des Knueppels (Tasters, Schalters, what ever) ueber die Mitte des moeglichen Weges
// einen zaehlbaren Tippwert ergeben. Alle Bewegungen unterhalb dieser Mittelwerte werden nicht beruecksichtigt.
volatile uint16_t CalculatedMultiSwitchUpperStart = ((ErmittelterNullpunktSchaltung + MeasuredMultiswitchUp) >> 1);
volatile uint16_t CalculatedMultiSwitchLowerStart = ((ErmittelterNullpunktSchaltung + MeasuredMultiswitchDown) >> 1);
// Die Zaehler fuer die Tipps nach oben bzw. nach unten
volatile uint8_t MultiswitchUpCounter;
volatile uint8_t MultiswitchDownCounter;
// Der Zeitstempel wann das letzte Tippen gezaehlt wurde. Er wird im Programmablauf geprueft. Ist die letzte Tippaktion eine bestimmte Zeit her,
// werden die bis dahin gezaehlten Tipps ausgewertet und die entsprechende Funktion ausgefuehrt. Danach werden die Counter wieder auf 0 gesetzt.
volatile uint32_t MultiswitchLastCounterChange;
// Der Zustand waehrend der letzten Signalauswertung. Er wird gebraucht um ihn mit dem aktuellen Zustand zu vergleichen. Gibt es eine Aenderung
// muss reagiert werden.
volatile uint8_t MultiswitchLastState;
#define ProcessingMode_Startup 1 // Die Phase des Einmessens des Nullpunkts
#define ProcessingMode_Running 2 // Die eigentliche Programmausfuehrung
volatile uint8_t ProcessingMode = ProcessingMode_Startup;
#define NumberOfNeededValidSignals 10
volatile uint8_t StartupValidSignalCounter = 0;
volatile uint16_t AktuellerEmpfaengerWertLenkung = 1500; // Der aktuell als letztes ermittelte Wert
volatile uint16_t AktuellerEmpfaengerWertGas = 1500; // Der aktuell als letztes ermittelte Wert
volatile uint16_t AktuellerEmpfaengerWertFunktion = 1500; // Der aktuell als letztes ermittelte Wert
volatile uint16_t AktuellerEmpfaengerWertSchaltung = 1500; // Der aktuell als letztes ermittelte Wert
// Variablen fuer die gemessenen Mittelstellungen
int ErmittelterNullpunktLenkung = 1472;
int ErmittelterNullpunktGas = 1472;
int ErmittelterNullpunktFunktion = 1472;
// Variablen fuer Schaltung Lenkprogramm
byte Lenkprogramm = 1; // Standardwert (Anfang) Lenkprogramm 1
// Variablen fuer Berechnung der einzelnen Lenkprogramme
int WertInSchalter; // Wert des Eingangssignal Schaltung
int wertin; //Wert des Eingangssignale Lenkung
int wertaus1 = 1472; //Wert des Ausgangssignales Achse 1 (auf Mitte stellen)
int wertaus2 = 1472; //Wert des Ausgangssignales Achse 2 (auf Mitte stellen)
int mixer = 40; //Mixer in % von Servo 1 auf Servo 2
int mitte1 = 0; //Mittelstellung Servo 1 anpassen
int mitte2 = 0; //Mittelstellung Servo 2 anpassen
// Variablen fuer die Servos
ServoTimer2 s1, s2, s3, s4; //Servoobjekte definieren
//-------------- Pinbelegung - Constante Variablen Deklaration ----------------------------------------
//
const byte pw = 2; // das ist Interrupt 0 aber Pin 2 wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 2 (Gas)
const byte PIN_RC = 3; // das ist Interrupt 1 aber Pin 3 wo das Empfaengersignal eingelesen wird! Fuer RC-Kanal 4 (Licht)
const byte rfsch = 4; // Pin fuer Rueckfahrscheinwerfer
const byte brakelight = 5; // Pin fuer Bremslicht und Ruecklicht mit PWM
const byte AbBlendLicht = 6; // Pin fuer AbBlendLicht
const byte light = 9; // Pin fuer Licht
//const byte lenk_in = 8; // Eingang Lenkkanal-Impulse
//const byte RKL_in = 7; // Eingang fuer externe RKL-Einschaltung
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 = LED_BUILTIN; // interne LED und Ausgang fuer Arbeitsscheinwerfer
const byte deadzone = 90; // pulse lenght difference in µS between neutral and point to switch on
const byte hysteresis = 50; // pulse lenght hysteresis (between on and off)
//
//------------- Einstellbare Werte - Constante Variablen Deklaration ---------------------------------------
const byte light_pwm = 240; // PWM-Wert fuer Standlicht (hier einstellbar)
const byte Aus = 0; // Zustand Aus auf 0 setzen
const byte gastoleranz = 20; // Toleranz fuer die Knueppelbewegung, bis Bremslichtvorgang eingeleitet wird. (milliseconds)(hier einstellbar)
const byte brakecounter_max = 3; // Maximaler Inhalt des Fehlerzaehlers. (X mal)(hier einstellbar)
const long brakelighttime = 5000; // Zeit wie lange das Bremslicht nach Fahrzeugstillstand noch leuchtet. (milliseconds)(hier einstellbar)
const long brakelighttime_min = 500; // Zeit wie lange das Bremslicht bei Betaetigung mindestens leuchtet. (milliseconds)(hier einstellbar)
const long rfsch_ontime = 7000; // Zeit wie lange der Rueckfahrscheinwerfer nach Fahrzeugstillstand noch leuchtet. (milliseconds)(hier einstellbar)
const long retourbeginn = 1600; // Knueppelbewegungsweg Kanal 2 ab wann Rueckfahrscheinwerfer eingeschaltet wird. (hier einstellbar)
//
//-------------- Byte Variablen deklaration -----------------------------------
byte vb = 75; // Variable fuer gemapte Impulse Wert = Mittelstellung Blinker
byte vw = 75; // Variable fuer 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 LedStatusLenkprogramm = LOW;
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 bestaetigt - 0 bei unbestaetigt)
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 bestaetigt - 0 bei unbestaetigt)
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 AbBlendLicht_on = 0; // Scheinwerfer ein
byte AbBlendLicht_of = 0; // Scheinwerfer aus
byte light_on = 0; // Standlicht / Ruecklicht ein
byte light_of = 0; // Standlicht / Ruecklicht aus
byte reliSave = 00; // Speicher fuer Blinklicht Status
byte schalterRechts = 0; // Flag fuer Blinkerhebelstellung nach rechts
byte schalterLinks = 0; // Flag fuer Blinkerhebelstellung nach links
byte sentido = 0; // betaetigte Richtung fuer linken Kreuzknueppel. 1=rechts; 2=links; 3=vorne; 4=hinten
byte rfsch_on = 0; // Rueckfahrscheinwerfer (Wert 1 bei an - 0 bei aus)
byte vwf = 0; // Flag fuer Vorwaertsfahrt
byte brakelight_on = 0; // Flag steht auf "1" wenn Bremslicht leuchtet.
byte StatusFrontHeber = 0; // Flag fuer Frontheber
byte StatusHeckHeber = 0; // Flag fuer Heckheber
//
//-------------- int Variablen deklaration ----------------------------------------------------------------------------------
int akt_richtung = 0; // Flag fuer aktuelle Knueppelrichtung: 0 Stand; 1 = Vorwaerts; 2 = Rueckwaerts
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
// Der Wert von "akt_richtung" bezieht sich nicht auf die Fahrtrichtung, //
// sondern die Richtung der Knueppelbewegung. //
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
int mem_duration = 0; // Speicher fuer Emfaengerwert Gas
int brakecounter = 0; // Zaehler zur ueberwachung der Bremsimpulsezeitkontrolle
int brakelightdaueraus = 0; // Flag ob Bremslicht nach mehr als 5 Sec. Stillstand aus bleiben soll . "1" = ja.
int RKLE = HIGH; // Flag RKL-Eingangszustand
int WertEingangFrontHeber = 1500; // Wert des Eingangssignal Frontheber
int WertAusgangFrontHeber = 1500; // Wert des Ausgangssignal Frontheber
//
//-----------------long Variablen deklaration -------------------------------------------------------------------------------
long time = 0;
//---------------- unsigned long Variablen Deklaration ---------------------------------------------------------------------
unsigned long aktTime = 0; // reset Speicher fuer aktuelle Zeit
unsigned long countMillis = 0; // reset Zeitzaehler
unsigned long int interval = 700; // Zeit fuer Langeshalten des Steuerkueppels nach rechts oder links (hier einstellbar)
unsigned long int blinterval = 600; // Blinkintervall (hier einstellbar)
unsigned long currentMillis = 0; // aktuell gueltige Zeit
unsigned long StatusLenkprogrammMillis = 0;
unsigned long currentbrakeMillis = 0; // aktuell gueltige Zeit
unsigned long currentrfschMillis = 0; // aktuell gueltige 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 = 1; // Lenkeinschlagauswertung vom Empfaenger
unsigned long dw; // zur Zeit nicht benutzt Pulse in Kanal 4 Futaba Warnlicht - RKL
unsigned long timeStart = 0; // Zeit bei Beginn einer Knueppelbewegung
unsigned long timeStop = 0; // Zeit bei Ende einer Knueppelbewegung
unsigned long timeBegin = 0; // Zeitbeginn in der Zeitkontrolle
unsigned long duration; // Variabele fuer den vom Interrupt eingelesenen Impuls des Empfaengers
unsigned long intervalLED = 1000; // interval at which to blink (milliseconds)
unsigned long previousMillisLED = 0; // will store last time LED was updated
//
//
/*
*/
void setup() {
// Controller pins
DDRD = DDRD | 0b01110011; //Setzt D2,D3 und D7 als Eingang 0 und die restlichen als Ausgang 1
cli(); // Clear interrupts Interrupts ausschalten
// Register zuruecksetzen
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = 0;
OCR1A = 20; //Output Compare Register auf Vergleichswert setzen, war 20
TCCR1B |= (1 << CS11); //Prescale 8
// 16MHz/8=2MHz mit OCR1A=20 Interrupt alle 10µs
TCCR1B |= (1 << WGM12); //CTC-Mode einschalten
TIMSK1 |= (1 << OCIE1A); //Timer Compare Interrupt setzen
sei(); // Set Interrupts Interrupts
//---------------------------------------------------------------------------------------------------------------
// pinMode(pw, INPUT); // Pin 2 Input fuer Interrupt RC-Empfaengersignal Kanal 2 (Gas)
digitalWrite(pw, HIGH); // hier wird der interne Pull-up Widerstand an Pin 2 eingeschaltet
// pinMode(PIN_RC, INPUT); // Pin 3 Input fuer Interrupt RC-Empfaengersignal Kanal 4 (Licht)
digitalWrite(PIN_RC, HIGH); // hier wird der interne Pull-up Widerstand an Pin 3 eingeschaltet
pinMode(rfsch, OUTPUT); // Pin 4 Output fuer Rueckfahrscheinwerfer
pinMode(brakelight, OUTPUT); // Pin 5 Output fuer Bremslicht
pinMode(AbBlendLicht, OUTPUT); // Pin 6 Output fuer AbBlendLicht
pinMode(light, OUTPUT); // Pin 9 Output fuer 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(RKL_in, INPUT); // Pin 7 externer Einschalteingang fuer die Rundumkennleuchte
// digitalWrite(RKL_in, HIGH); // hier wird der interne Pull-up Widerstand an Pin 9 eingeschaltet
pinMode(bl, OUTPUT); // Pin 10 Output fuer Blinklicht links
pinMode(br, OUTPUT); // Pin 11 Output fuer Blinklicht rechts
// pinMode(rkl, OUTPUT); // Pin 12 Output fuer Rundumkennleuchten
pinMode (al, OUTPUT); // Pin 13 Output fuer interne LED und Arbeitsscheinwerfer
pinMode (A4, INPUT); // Pin A4 Input fuer Interrupt RC-Empfaengersignal Kanal 3 (Funktion)
digitalWrite(A4, HIGH); // hier wird der interne Pull-up Widerstand an Pin A4 eingeschaltet
//---------------------------------------------------------------------------------------------------------------
delay(1500); // Wartezeit auf Empfaenger Initialisierung
// digitalWrite(light, LOW); // Standlicht im Setup einschalten
digitalWrite(AbBlendLicht, HIGH); // Scheinwerfer im Setup einschalten
digitalWrite(al, LOW); // interne LED ausschalten (aktiv HIGH)
// digitalWrite(rkl, LOW); // Rundumkennleuchte im Setup einschalten
digitalWrite(br, LOW); // Blinklicht rechts im Setup einschalten
digitalWrite(bl, LOW); // Blinklicht links im Setup einschalten
digitalWrite(rfsch, HIGH); // Ruecfahrscheinwerfer im Setup einschalten
digitalWrite(brakelight, LOW); // Bremsleuchten im Setup einschalten
delay(1000); // Eine Sekunde Warteseit im Setup zur Lampenkontrolle
digitalWrite(light, HIGH); // Standlicht nach dem Setup ausschalten
digitalWrite(AbBlendLicht, LOW); // Scheinwerfer nach dem Setup ausschalten
digitalWrite(br, HIGH); // Blinklicht rechts nach dem Setup ausschalten
digitalWrite(bl, HIGH); // Blinklicht links nach dem Setup ausschalten
digitalWrite(rfsch, LOW); // Rueckfahrscheinwerfer nach dem Setup ausschalten
digitalWrite(brakelight, HIGH); // Bremsleuchten nach dem Setup ausschalten
// digitalWrite(rkl, HIGH); // Rundumkennleuchte nach dem Setup ausschalten
s1.attach(pinServo1); // Pin fuer Servo 1 definieren
s2.attach(pinServo2); // Pin fuer Servo 2 definieren
s3.attach(pinServo3); // Pin fuer Servo Frontheber definieren
// s4.attach(pinServo4); // Pin fuer Servo 4 definieren
s1.write(ErmittelterNullpunktLenkung); //Servoposition Servo 1 in Neutrallage
s2.write(ErmittelterNullpunktLenkung); //Servoposition Servo 2 in Neutrallage
s3.write(ErmittelterNullpunktFunktion); //Servoposition Servo 3 in Neutrallage
// pinMode(ledPin, OUTPUT); // Pin 13 als LED-Ausgang definieren
#ifdef debug
Serial.begin( 115200 );
Serial.println(F("Start..."));
#endif
}
ISR(TIMER1_COMPA_vect) //die Interruptroutine gibt ein Zehntel der Impulsbreite in µs zurueck
{
if (PIND & (1 << PD3)) //Channel 1 rechts horizontal, das ist PIN D3
{
cnt_CH_1++; //wenn Eingang High dann Zaehler inkrementieren
}
else if (cnt_CH_1) //wenn Eingang Low dann pruefen ob Zaehler gestartet
{
frqraw_CH_1 = cnt_CH_1 - 1; //wenn Zaehler gestartet, stoppen und Wert uebergeben
cnt_CH_1 = 0; //Zaehler zuruecksetzen
}
if (PIND & (1 << PD2)) //Channel 2 rechts vertikal, das ist PIN D2
{
cnt_CH_2++; //wenn Eingang High dann Zaehler inkrementieren
}
else if (cnt_CH_2) //Channel 2 rechts vertikal, das ist PIN D4
{
frqraw_CH_2 = cnt_CH_2 - 1; //wenn Zaehler gestartet, stoppen und Wert uebergeben
cnt_CH_2 = 0; //Zaehler zuruecksetzen
}
if (PINC & (1 << PC4)) //Channel 3 links vertikal, das ist PIN A4
{
cnt_CH_3++; //wenn Eingang High dann Zaehler inkrementieren
}
else if (cnt_CH_3) { //wenn Eingang Low dann pruefen ob Zaehler gestartet
frqraw_CH_3 = cnt_CH_3 - 1; //wenn Zaehler gestartet, stoppen und Wert uebergeben
cnt_CH_3 = 0; //Zaehler zuruecksetzen
}
if (PIND & (1 << PD7)) { //Channel 4 links horizontal , das ist PIN D7
cnt_CH_4++; //wenn Eingang High dann Zaehler inkrementieren
}
else if (cnt_CH_4) { //wenn Eingang Low dann pruefen ob Zaehler gestartet
frqraw_CH_4 = cnt_CH_4 - 1; //wenn Zaehler gestartet, stoppen und Wert uebergeben
cnt_CH_4 = 0; //Zaehler zuruecksetzen
}
}
/*
*/
void InterruptLenkung()
{
uint32_t nMicros = micros(); // Aktuellen Zeitstempel merken
uint16_t nDifference = (uint16_t)(frqraw_CH_1 * 10); // 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
Empfaenger_Kanal1_Wert_Summe -= Empfaenger_Kanal1_Wert[Empfaenger_Kanal1_Wert_Index];
// Der neue Wert gemerkt wird
Empfaenger_Kanal1_Wert[Empfaenger_Kanal1_Wert_Index] = nDifference;
// Den neuen Wert auf die Summe addieren
Empfaenger_Kanal1_Wert_Summe += nDifference;
// Den Index auf die naechste Position schieben
Empfaenger_Kanal1_Wert_Index = ( ( Empfaenger_Kanal1_Wert_Index + 1 ) & 0x03 ); // Index erhoehen und ggf. von 4 auf 0 springen
// Den aktuellen Mittelwert errechnen indem die Summe durch 4 geteilt wird
AktuellerEmpfaengerWertLenkung = ( Empfaenger_Kanal1_Wert_Summe >> 2 ); // durch 4 teilen
}
}
/*
*/
void InterruptGas()
{
uint32_t nMicros2 = micros(); // Aktuellen Zeitstempel merken
uint16_t nDifference2 = (uint16_t)(frqraw_CH_2 * 10); // Die Differenz zum letzten Aufruf errechnen
if ( (nDifference2 > 900) && ( nDifference2 < 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
Empfaenger_Kanal2_Wert_Summe -= Empfaenger_Kanal2_Wert[Empfaenger_Kanal2_Wert_Index];
// Der neue Wert gemerkt wird
Empfaenger_Kanal2_Wert[Empfaenger_Kanal2_Wert_Index] = nDifference2;
// Den neuen Wert auf die Summe addieren
Empfaenger_Kanal2_Wert_Summe += nDifference2;
// Den Index auf die naechste Position schieben
Empfaenger_Kanal2_Wert_Index = ( ( Empfaenger_Kanal2_Wert_Index + 1 ) & 0x03 ); // Index erhoehen und ggf. von 4 auf 0 springen
// Den aktuellen Mittelwert errechnen indem die Summe durch 4 geteilt wird
AktuellerEmpfaengerWertGas = ( Empfaenger_Kanal2_Wert_Summe >> 2 ); // durch 4 teilen
}
}
/*
*/
void InterruptFunktion()
{
uint32_t nMicros3 = micros(); // Aktuellen Zeitstempel merken
uint16_t nDifference3 = (uint16_t)(frqraw_CH_3 * 10); // Die Differenz zum letzten Aufruf errechnen
if ( (nDifference3 > 900) && ( nDifference3 < 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
Empfaenger_Kanal3_Wert_Summe -= Empfaenger_Kanal3_Wert[Empfaenger_Kanal3_Wert_Index];
// Der neue Wert gemerkt wird
Empfaenger_Kanal3_Wert[Empfaenger_Kanal3_Wert_Index] = nDifference3;
// Den neuen Wert auf die Summe addieren
Empfaenger_Kanal3_Wert_Summe += nDifference3;
// Den Index auf die naechste Position schieben
Empfaenger_Kanal3_Wert_Index = ( ( Empfaenger_Kanal3_Wert_Index + 1 ) & 0x03 ); // Index erhoehen und ggf. von 4 auf 0 springen
// Den aktuellen Mittelwert errechnen indem die Summe durch 4 geteilt wird
AktuellerEmpfaengerWertFunktion = ( Empfaenger_Kanal3_Wert_Summe >> 2 ); // durch 4 teilen
}
}
/*
*/
void InterruptSchalter()
{
uint32_t nMicros4 = micros(); // Aktuellen Zeitstempel merken
uint16_t nDifference4 = (uint16_t)(frqraw_CH_4 * 10); // Die Differenz zum letzten Aufruf errechnen
if ( (nDifference4 > 900) && ( nDifference4 < 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
Empfaenger_Kanal4_Wert_Summe -= Empfaenger_Kanal4_Wert[Empfaenger_Kanal4_Wert_Index];
// Der neue Wert gemerkt wird
Empfaenger_Kanal4_Wert[Empfaenger_Kanal4_Wert_Index] = nDifference4;
// Den neuen Wert auf die Summe addieren
Empfaenger_Kanal4_Wert_Summe += nDifference4;
// Den Index auf die naechste Position schieben
Empfaenger_Kanal4_Wert_Index = ( ( Empfaenger_Kanal4_Wert_Index + 1 ) & 0x03 ); // Index erhoehen und ggf. von 4 auf 0 springen
// Den aktuellen Mittelwert errechnen indem die Summe durch 4 geteilt wird
AktuellerEmpfaengerWertSchaltung = ( Empfaenger_Kanal4_Wert_Summe >> 2 ); // durch 4 teilen
if (ProcessingMode == ProcessingMode_Startup)
{
StartupValidSignalCounter++;
return;
// Da wir uns im Startup Modus befinden ist eine weitere Bearbeitung des Signals nicht notwendig
}
uint8_t NewMultiSwitchstate = MultiswitchStateCenter;
// Nun wird aus dem Servowert berechnet ob sich der Kanal in der Mitte, oben oder unten befindet
if (nDifference4 >= CalculatedMultiSwitchUpperStart)
NewMultiSwitchstate = MultiswitchStateUp; // Der Kanal ist oberhalb des oberen Schwellenwerts
else
{
if (nDifference4 <= CalculatedMultiSwitchLowerStart)
NewMultiSwitchstate = MultiswitchStateDown;// Der Kanal ist unterhalb des unteren Schwellenwerts
}
if ( MultiswitchLastState != NewMultiSwitchstate )
{
// Der Wert unterscheidet sich vom vorherigen, entweder ist der Kanal von der Mitte in einen der ausseren gewechselt,
// oder er ist in die Mitte zurueck gekehrt.
if (NewMultiSwitchstate == MultiswitchStateCenter)
{
// Der Kanal ist aus einem der aeusseren Bereiche in die Mitte zurueck gewechselt.
// Diesen Status bearbeiten
// Der aktuelle Status muss ggf. in die Multiswitch Informationen als Auswahl eingepflegt werden
switch (MultiswitchLastState)
{
case MultiswitchStateUp:
// Der Kanal ist aus dem oberen Bereich in die Mitte gewechselt.
// Der Zaehler fuer Tipps nach oben wird erhoeht und der fuer unten wird resettet
MultiswitchUpCounter++;
MultiswitchDownCounter = 0;
break;
case MultiswitchStateDown:
// Der Kanal ist aus dem unteren Bereich in die Mitte gewechselt.
// Der Zaehler fuer Tipps nach unten wird erhoeht und der fuer oben wird resettet
MultiswitchUpCounter = 0;
MultiswitchDownCounter++;
break;
}
// Zusaetzlich wird die Uhrzeit gemerkt wann dieser Wechsel statt gefunden hat.
MultiswitchLastCounterChange = millis();
}
// Den letzten Status merken.
MultiswitchLastState = NewMultiSwitchstate;
}
}
}
/*
*/
void CalculateMultiSwitchSignalAreas()
{
// Der Mittelwert zwischen der Mitte und unten bzw. oben wird durch Addition der Mitte mit dem oberen bzw. unteren Wert und das anschliessende
// Teilen durch 2 errechnet.
CalculatedMultiSwitchUpperStart = ((ErmittelterNullpunktSchaltung + MeasuredMultiswitchUp) >> 1);
CalculatedMultiSwitchLowerStart = ((ErmittelterNullpunktSchaltung + MeasuredMultiswitchDown) >> 1);
#ifdef debug
Serial.print(F("Lower: "));
Serial.println(CalculatedMultiSwitchLowerStart);
Serial.print(F("Upper: "));
Serial.println(CalculatedMultiSwitchUpperStart);
#endif
}
/*
*/
void InitializeMultiswitchVariables()
{
MultiswitchLastState = MultiswitchStateCenter;
MultiswitchLastCounterChange = 0;
MultiswitchUpCounter = 0;
MultiswitchDownCounter = 0;
// Nun berechnen wir noch die Bereiche fuer den Multiswitch
CalculateMultiSwitchSignalAreas();
}
/*
*/
void HandleMultiswitch() // Ermitteln und Auswerten der Steuerknueppeleingaben Schaltung
{
int nMultiswitchCommand = 0;
if (MultiswitchLastCounterChange > 0)
{
// Es liegt ein Zeitstempel eines Wechsel in die Mitte vor.
// Wenn die letzte Aenderung der Zaehlerstaende mehr als 750ms her ist, wird dies als das gewaehlte Kommando angesehen und gesetzt
if (MultiswitchLastCounterChange < (millis() - 750))
{
// Die Zaehler werden in einen Wert umgewandelt. Positive Werte sind Tipps nach oben, negative Werte sind Tipps nach unten
if (MultiswitchUpCounter > 0)
{
nMultiswitchCommand = (int)MultiswitchUpCounter;
MultiswitchUpCounter = 0;
}
else
{
if (MultiswitchDownCounter > 0)
{
nMultiswitchCommand = -((int)MultiswitchDownCounter);
MultiswitchDownCounter = 0;
}
}
// Der Zeitstempel wird wieder geloescht, denn der Zaehlerwert wurde ja umgewandelt.
MultiswitchLastCounterChange = 0;
}
}
// Auswertung des Multiswitch
if (nMultiswitchCommand > 0)
{
#ifdef debug
Serial.print(nMultiswitchCommand);
Serial.println("x nach rechts");
#endif
}
if (nMultiswitchCommand < 0)
{
#ifdef debug
Serial.print(-nMultiswitchCommand);
Serial.println("x nach links");
#endif
}
// Hier wird nun der errechnete Wert ausgewertet und die entsprechenden Funktionen ausgefuehrt.
switch (nMultiswitchCommand)
{
case 1: // 1x rechts
// Blinker rechts
{
blon = 1;
if (re_li != 11)
{
if (re_li == 10)
{
re_li = 00;
}
else
{
re_li = 10;
}
}
schalterLinks = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case 2: // 2x rechts
// Warnblinker an/aus
{
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;
}
schalterLinks = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case 3: // 3x rechts
// Rundumleuchte an/aus
{
rklon = 1;
//time_delete();
schalterLinks = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case 4: // 4x rechts
// normale Lenkung
{
Lenkprogramm = 1;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case 5: // 5x rechts
// Allradlenkung
{
Lenkprogramm = 2;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case 6: // 6x rechts
// Hundegang
{
Lenkprogramm = 3;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case -1: // 1x links
// hier die entsprechende Aktion ausfuehren
{
bron = 1;
if (re_li != 11)
{
if (re_li == 01)
{
re_li = 00;
}
else
{
re_li = 01;
}
}
//time_delete();
schalterRechts = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case -2: // 2x links
// Abblendlicht an/aus
{
light_on = 1;
//time_delete();
schalterRechts = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case -3: // 3x links
// Fernlicht an/aus
{
AbBlendLicht_on = 1;
//time_delete();
schalterRechts = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case -4: // 4x links
// Arbeitsscheinwerfer an/aus
{
alon = 1;
schalterRechts = 0;
StatusFrontHeber = 0;
StatusHeckHeber = 0;
}
break;
case -5: // 5x links
// Frontheber an
{
StatusFrontHeber = 1;
StatusHeckHeber = 0;
}
break;
case -6: // 6x links
// Heckheber an
{
StatusFrontHeber = 0;
StatusHeckHeber = 1;
}
break;
default:
// do nothing;
break;
}
}
/*
*/
void Blinkcontrol()
{
vw = map(AktuellerEmpfaengerWertLenkung, 900, 2100, 0, 150);
if (lenk != 0) // Fehlerkorektur fuer Laufzeitfehler. Bei Wert"0" Routine nicht ausfuehren.
{
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 zuzrueck 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 fuer beide Blinker aus setzen
blof = 0; // Flag fuer Blinker links ausschalten erlaubt wieder auf 0 setzen
brof = 0; // Flag fuer Blinker rechts ausschalten erlaubt wieder auf 0 setzen
} // Ende - Abfrage 5
} // Ende - Abfrage 4
} // Ende - Abfrage 3
} // Ende Fehlerekorrektur Blinkerabschaltung
} // Ende der Routine
/*
*/
void gas()
{
//--------------------------------------------------------------------------------------------------------
//------------ Hier kann nun mit dem Wert von AktuellerEmpfaengerWert vom Interrupt gearbeitet werden ----
//--------------------------------------------------------------------------------------------------------
duration = AktuellerEmpfaengerWertGas; // Hier wird die aktuelle Steuerknueppelstellung vom Interrupt uebernommen.
//-----------------------------------------------------------------------------
//------ Keine Gasknueppelbewegung
//-----------------------------------------------------------------------------
if (duration > (ErmittelterNullpunktGas - deadzone) && duration < (ErmittelterNullpunktGas + deadzone)) // Knueppel befindet sich in Neutralstellung.
{
vwf = 0; // Flag fuer Vorwaertsfahrt wird auf "0" gesetzt
mem_duration = 0; // Speicher fuer Knueppelstellung wird auf "0" gesetzt - geloescht.
akt_richtung = 0; // Flag fuer aktuelle Knueppelbewegungsrichtung wird auf "0" gesetzt.
currentbrakeMillis = millis(); // aktuell gueltige Zeit fuer Bremslicht Zeitablauf beginn.
currentrfschMillis = millis(); // aktuell gueltige Zeit fuer Rueckfahrlicht Zeitablauf beginn.
}
//-----------------------------------------------------------------------------
//------ Rueckwaerts Gasknueppelbewegung
//-----------------------------------------------------------------------------
if (duration >= retourbeginn) // Knuepel auf Rueckwaertsfahrstellung.
{
if (rfsch_on == 0) // Wenn Rueckfahrflag auf "aus" steht.
{
digitalWrite(rfsch, HIGH); // Rueckfahrscheinwerfer einschalten.
rfsch_on = 1; // Flag fuer Rueckfahrscheinwerfer auf "ein" setzen.
}
if (duration >= mem_duration) // Wenn der Wert fuer die aktuelle Kueppelstellung gleich oder groesser als der gespeicherte ist.
{
akt_richtung = 2; // Das Flag fuer die aktuelle Knueppelbewegungsrichtung wird auf Richtung rueckwaerts (2) gesetzt.
}
if (duration < mem_duration - gastoleranz) // Wenn der Wert fuer die aktuelle Knueppelstellung kleiner als der gespeicherte - gastoleranz (50) ist.
{
akt_richtung = -2; // Das Flag fuer die aktuelle Knueppelbewegungsrichtung wird auf Richtung vorwaerts im Rueckwaertsfahrbereich(-2) gesetzt.
}
mem_duration = duration; // Aktuelle Knueppelstellung speichern.
//aktmillis = millis(); // Aktuellen Millisekunden Wert speichern.
}
//-----------------------------------------------------------------------------
//------ Vorwaerts Gasknueppelbewegung
//-----------------------------------------------------------------------------
// if (duration <= 1400) // Knueppel in Vorwaertsfahrstellung.
if (duration <= (ErmittelterNullpunktGas - deadzone)) // Knueppel in Vorwaertsfahrstellung.
{
if (duration <= mem_duration) // Wenn der Wert fuer die aktuelle Kueppelstellung gleich oder kleiner als der gespeicherte ist.
{
akt_richtung = 1; // Das Flag fuer die aktuelle Knueppelbewegungsrichtung wird auf Richtung vorwaerts (1) gesetzt.
}
if (duration > mem_duration + gastoleranz) // Wenn der Wert fuer die aktuelle Knueppelstellung groesser als der gespeicherte + gastoleranz (50) ist.
{
akt_richtung = -1; // Das Flag fuer die aktuelle Knueppelbewegungsrichtung wird auf Richtung rueckwaerts im Vorwaertsfahrbereich(-1) gesetzt.
}
if (rfsch_on == 1) // Wenn Rueckfahrflag auf "ein" steht.
{
digitalWrite(rfsch, LOW); // Rueckfahrscheinwerfer ausschalten.
rfsch_on = 0; // Flag fuer Rueckfahrscheinwerfer auf "aus" setzen.
}
if (vwf == 0) // Wenn Flag Vorwaertsfahrt = noch auf "0" (Fahrzeug steht)
{
vwf = 1; // Flag Vorwaertsfahrt auf "1" setzen (Vorwaertsfahrt).
}
mem_duration = duration; // Aktuelle Knueppelstellung speichern.
//aktmillis = millis(); // Aktuellen Millisekunden Wert speichern.
}
//---------------------------------------------------------------------------------
//---------Kontrolle ob Bremslicht ein oder aus geschaltet wird -------------------
//---------------------------------------------------------------------------------
if (akt_richtung == -1 || akt_richtung == -2) // Knueppelbewegung 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) // Knueppel hat Neutralstellung erreicht und erfordert Bremslichtbehandlung.
{
if (brakelight_on == 1)
{
if (brakelightdaueraus == 0) // Wenn das Flag fuer "Fahrzeug steht laenger 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, 255); // Bremslicht ausschalten.
brakelight_on = 0;
}
else if (light_of == 1)
{
analogWrite (brakelight, light_pwm); // Bremslicht ausschalten und PWM auf Ruecklichtwert setzen.
brakelight_on = 0;
}
brakelightdaueraus = 1; // Das Flag fuer Bremslicht dauerhaft ausbleiben wird auf "1" gesetzt. Das Fahrzeug steht laenger als 5 Sec.
}
}
if (rfsch_on == 1) // Wenn Rueckfahrlichtflag auf "ein" steht.
{
if (currentrfschMillis - previousrfschMillis >= rfsch_ontime)
{
previousrfschMillis = currentrfschMillis; // speichert die letzte Zeit bei Rueckfahrlichtlichtbeginn.
digitalWrite(rfsch, LOW); // Rueckfahrscheinwerfer ausschalten.
rfsch_on = 0; // Flag fuer Rueckfahrscheinwerfer auf "aus" setzen.
}
}
}
//----------------------------------------------------------------------------------------------
if (akt_richtung == 1 || akt_richtung == 2) // Knueppelbewegung in eine Fahrtrichtung bei leuchtendem Bremslicht erfordert Bremslichtbehandlung.
{ //
brakelightdaueraus = 0; // Das Flag fuer Bremslicht dauerhaft ausbleiben wird auf "0" gesetzt.
if (light_of == 0)
{
analogWrite (brakelight, 255); // Bremslicht ausschalten.
brakelight_on = 0;
}
else if (light_of == 1)
{
analogWrite (brakelight, light_pwm); // Bremslicht ausschalten und PWM auf Ruecklichtwert setzen.
brakelight_on = 0;
}
brakelightdaueraus = 1; // Das Flag fuer Bremslicht dauerhaft ausbleiben wird auf "1" gesetzt. Das Fahrzeug steht laenger als 5 Sec.
}
}
void BlinkenStatusLenkprogramm()
{
// check to see if it's time to blink the LED; that is, if the difference
// between the current time and last time you blinked the LED is bigger than
// the interval at which you want to blink the LED.
unsigned long StatusLenkprogrammMillis = millis();
if (StatusLenkprogrammMillis - previousMillisLED >= interval)
{
// save the last time you blinked the LED
previousMillisLED = StatusLenkprogrammMillis;
// if the LED is off turn it on and vice-versa:
if (LedStatusLenkprogramm == LOW)
{
LedStatusLenkprogramm = HIGH;
}
else
{
LedStatusLenkprogramm = LOW;
}
// set the LED with the LedStatusLenkprogramm of the variable:
digitalWrite(al, LedStatusLenkprogramm);
}
}
/*
*/
void bremslicht()
{
brakecounter ++; // Bremszaehler zaehlt wie oft die Routine aufgerufen wurde.
if (brakecounter == brakecounter_max) // Wenn das 2. mal dann
{
analogWrite (brakelight, 0); // Bremslicht einschalten (PWM - 0 = voll an, 255 = aus; wegen aktiv LOW)
brakelight_on = 1;
// if (Initialisierung == 1 && AnzahlLegaleWerte < 10)
// {
// AnzahlLegaleWerte++;
// ErmittelterNullpunktLenkung = AktuellerEmpfaengerWertLenkung;
// ErmittelterNullpunktSchaltung = AktuellerEmpfaengerWertSchaltung;
// ErmittelterNullpunktGas = AktuellerEmpfaengerWertGas;
// ErmittelterNullpunktFunktion = AktuellerEmpfaengerWertFunktion;
// }
brakecounter = 0; // Bremszaehler wieder auf "0" seten - loeschen.
delay(brakelighttime_min); // ?? Pause damit bei Microbremsung das Bremslicht z.B. 100 ms leuchtet und nicht nur aufblitzt.
}
}
//---------------- Der Bremszaehler verhindert das bei jeder kleinen Wertschwankung vom Empfaenger, oder z.B. unruhiger Knueppelhaltung,
//---------------- das Bremslicht aufblitzt.
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 gueltige Zeit
time = aktTime - timeBegin; // festgestellte Zeit = Aktuelle Zeit minus Anfangszeit
}
void loop() {
if (ProcessingMode == ProcessingMode_Startup)
{
if (StartupValidSignalCounter >= NumberOfNeededValidSignals)
{
// Es wurde die benoetigte Anzahl valider Signale erreicht.
// Der bisher eingemessene Wert wird als der Nullpunkt des Kanals eingetragen
ErmittelterNullpunktLenkung = AktuellerEmpfaengerWertLenkung;
ErmittelterNullpunktSchaltung = AktuellerEmpfaengerWertSchaltung;
ErmittelterNullpunktGas = AktuellerEmpfaengerWertGas;
ErmittelterNullpunktFunktion = AktuellerEmpfaengerWertFunktion;
InitializeMultiswitchVariables();
// Umschalten auf den Standardmodus
ProcessingMode = ProcessingMode_Running;
#ifdef SERIAL_OUTPUT
Serial.print(F("Measuring done..."));
Serial.println(ErmittelterNullpunktSchaltung);
#endif
}
}
else
{
// Standardmodus
// Um ein Einmessen des Kanals zu vermeiden wird der aktuelle Wert des kanals getestet.
// Ist er groesser als der bekannte Grenzwert, wird dieser ausgeweitet und die Schwellenwerte
// fuer den Multiswitch erneut kalibriert
// Diese Kalibrierung kann aber auch weg gelassen und feste Werte definiert werden.
uint8_t Calibrate = 0;
if (AktuellerEmpfaengerWertSchaltung < MeasuredMultiswitchDown)
{
// Der Wert is groesser als der obere Grenzwert, also wird er als neuer oberster Grenzwert gesetzt und die Neuberechnung
// der Schwellenwerte angefordert
MeasuredMultiswitchDown = AktuellerEmpfaengerWertSchaltung;
Calibrate = 1;
}
if (AktuellerEmpfaengerWertSchaltung > MeasuredMultiswitchUp)
{
// Der Wert is kleiner als der untere Grenzwert, also wird er als neuer oberster Grenzwert gesetzt und die Neuberechnung
// der Schwellenwerte angefordert
MeasuredMultiswitchUp = AktuellerEmpfaengerWertSchaltung;
Calibrate = 1;
}
if (Calibrate) CalculateMultiSwitchSignalAreas();
// Das Signal des Multiswitch auswerten und ggf. eine Funktion ausfuehren.
HandleMultiswitch();
}
InterruptSchalter();
InterruptLenkung();
InterruptGas();
InterruptFunktion();
// getlenkung();
Blinkcontrol();
blinken(blinterval, re_li);
lampen_schalten();
gas();
FunktionHeber();
// // Initialisierung des Moduls und Warten auf 10 gueltige Signale
//
// if (Initialisierung == 1)
// {
// if (AnzahlLegaleWerte >= 10)
// {
// Initialisierung = 0;
// }
// else
// {
// // Es wird noch auf gueltige Daten gewartet....
// delay(20);
// return;
// }
// }
if (( ( AktuellerEmpfaengerWertLenkung >= ( ErmittelterNullpunktLenkung - deadzone ) ) && ( AktuellerEmpfaengerWertLenkung <= ( ErmittelterNullpunktLenkung + deadzone ) ) ))
{
// AktuellerEmpfaengerWertLenkung = 1472;
AktuellerEmpfaengerWertLenkung = ErmittelterNullpunktLenkung;
}
/* Ab hier werden die einzelnen Lenkprogramme beschrieben
*/
if (Lenkprogramm == 1) // Standard-Lenkung
{
digitalWrite(LED_BUILTIN, HIGH);
wertin = AktuellerEmpfaengerWertLenkung;
wertaus1 = wertin + mitte1; //Mittelstellung Servo1 korregieren
// wertaus2 = wertaus1 - 1472;
wertaus2 = wertaus1 - ErmittelterNullpunktLenkung;
wertaus2 = wertaus2 * mixer / 100; //Mixer fuer Servo2 einrechnen
// wertaus2 = wertaus2 + 1472;
wertaus2 = wertaus2 + ErmittelterNullpunktLenkung;
wertaus2 = wertaus2 + mitte2; //Mittelstellung Servo2 korregieren
wertaus1 = constrain(wertaus1, 1128, 1812); //Ausgabewert fuer Servo1 begrenzen als Schutz
wertaus2 = constrain(wertaus2, 1128, 1812); //Ausgabewert fuer Servo2 begrenzen als Schutz
}
if (Lenkprogramm == 2) // Allrad-Lenkung
{
intervalLED = 100; // Intervall der internen LED auf 100ms setzen
BlinkenStatusLenkprogramm(); // Aufruf der Funktion "blinken"
wertin = AktuellerEmpfaengerWertLenkung;
wertaus1 = wertin + mitte1; //Mittelstellung Servo1 korregieren
// wertaus2 = 1472 - wertaus1;
wertaus2 = ErmittelterNullpunktLenkung - wertaus1;
// wertaus2 = (wertaus2 + 1472);
wertaus2 = (wertaus2 + ErmittelterNullpunktLenkung);
wertaus2 = wertaus2 + mitte2; //Mittelstellung Servo2 korregieren
wertaus1 = constrain(wertaus1, 1128, 1812); //Ausgabewert fuer Servo1 begrenzen als Schutz
wertaus2 = constrain(wertaus2, 1128, 1812); //Ausgabewert fuer Servo2 begrenzen als Schutz
}
if (Lenkprogramm == 3) // Hundegang
{
intervalLED = 500; // Intervall der internen LED auf 500ms setzen
BlinkenStatusLenkprogramm(); // Aufruf der Funktion "blinken"
wertin = AktuellerEmpfaengerWertLenkung;
wertaus1 = wertin + mitte1; //Mittelstellung Servo1 korregieren
wertaus2 = wertaus1;
wertaus2 = wertaus2 + mitte2; //Mittelstellung Servo2 korregieren
wertaus1 = constrain(wertaus1, 1128, 1812); //Ausgabewert fuer Servo1 begrenzen als Schutz
wertaus2 = constrain(wertaus2, 1128, 1812); //Ausgabewert fuer Servo2 begrenzen als Schutz
}
s1.write(wertaus1); //Servo 1 stellen
s2.write(wertaus2); //Servo 2 stellen
s3.write(WertAusgangFrontHeber); //Servo Frontheber stellen
delay(20);
}
/*
*/
void Licht_aus(int Li)
{
//digitalWrite (Li, HIGH);
switch (Li)
{
case light:
digitalWrite (AbBlendLicht, LOW); // Pin 6; Scheinwerfer ausschalten
digitalWrite (light, HIGH); // Pin 9; Standlichtausgang ausschalten
digitalWrite (brakelight, HIGH); // 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 Ruecklichtwert setzen.
brakelight_on = 0;
}*/
case AbBlendLicht:
analogWrite (AbBlendLicht, 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 Ruecklichtwert setzen.
light_of = 1; // Flag fuer Licht ausschaltbar wieder auf 1 setzen
break;
//
case rkl:
digitalWrite (rkl, HIGH);
rklof = 0;
rklon = 0;
break;
//
case al:
digitalWrite (al, HIGH);
break;
//
default:
// do nothing;
break;
}
//Li = 0;
}
/*
*/
void Licht_ein(int Li)
{
switch (Li) // Schalte Licht ein
{
case AbBlendLicht: // falls Wert = 6
analogWrite (AbBlendLicht, 0); // schalte Pin 6 auf LOW = "ein"
// analogWrite (light, light_pwm);
analogWrite (brakelight, light_pwm);
AbBlendLicht_of = 1;
break;
//
case light: // falls Wert = 9
analogWrite (brakelight, light_pwm);
// analogWrite (light, light_pwm);
analogWrite (AbBlendLicht, light_pwm);
brakelight_on = 0;
light_of = 1;
break;
//
case al: // falls Wert = 13
digitalWrite (al, LOW);
alof = 1;
break;
//
case rkl: // falls Wert = 12
digitalWrite (rkl, LOW);
rklof = 1;
break;
//
default:
// do nothing;
break;
}
}
/*
*/
void blinken(int takt, int reli) // uebergibt Taktintervall fuer Blinklicht und welcher Blinker blinken soll.
// // reli steht fuer 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 ausfuehren
ledState = HIGH; // 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 groesser alls der Takt ist
{ // // Funktion 2 ausfuehren
previousMillis = currentMillis; // sichert letzte Zeit update LED Status
switch (ledState) // Wechselt LED Zustand ein / aus und umgekehrt (Funktion Blinken)
{
case HIGH: // wenn der LED Status = "aus" ist....
ledState = LOW; // wechseln zu LED Status "ein"
break;
//---------------------------------------------------------------------------------------------------------------
case LOW: // sonst
ledState = HIGH; // 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 ausfuehren
digitalWrite(br, ledState); // schaltet die LED "Blinker rechts" mit dem Status der Variable "ledState"
digitalWrite(bl, HIGH); // schaltet die LED "Blinker links" "aus"
break; // Ende der Funktion
//---------------------------------------------------------------------------------------------------------------
case 10: // falls das linke Blinklicht an sein soll, nachfolgende Funktionen ausfuehren
digitalWrite(bl, ledState); // schaltet die LED "Blinker links" mit dem "NOT" Status der Variable "ledState"
digitalWrite(br, HIGH); // schaltet die LED "Blinker rechts" "aus"
break; // Ende der Funktion
//---------------------------------------------------------------------------------------------------------------
case 11: // falls beide Blinklichter an sein sollen (Warnblinker), nachfolgende Funktionen ausfuehren
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 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 (AbBlendLicht_on == 1 && AbBlendLicht_of == 0)
{
AbBlendLicht_on = 0;
Licht_ein(AbBlendLicht); // Scheinwerfer einschalten
light_on = 0;
}
//----------------------------------------------------------------------------------------------------
if (AbBlendLicht_on == 1 && AbBlendLicht_of == 1)
{
AbBlendLicht_on = 0;
AbBlendLicht_of = 0;
Licht_aus(AbBlendLicht); // 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
}
}
/*
Beschreibung Funktion Front- und Heckheber
*/
void FunktionHeber()
{
if ((StatusFrontHeber == 1) && (StatusHeckHeber == 0)) // Servo fuer Frontheber aktiv
{
if ( AktuellerEmpfaengerWertFunktion >= ( ErmittelterNullpunktFunktion + deadzone ) )
{
WertEingangFrontHeber = WertEingangFrontHeber + 10;
if (WertEingangFrontHeber > 2100)
{
WertEingangFrontHeber = 2100;
}
}
if ( AktuellerEmpfaengerWertFunktion <= ( ErmittelterNullpunktFunktion - deadzone ) )
{
WertEingangFrontHeber = WertEingangFrontHeber - 10;
if (WertEingangFrontHeber < 544)
{
WertEingangFrontHeber = 544;
}
}
WertAusgangFrontHeber = WertEingangFrontHeber;
}
}
Link 1: https://forum.arduino.cc/index.php?topic=187864.0
Link 2: https://www.hackster.io/ashraf_minh...er2-library-simple-explain-servo-sweep-512fd9
Viel Spaß!