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

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

Arduino Lichtmodul mit Blinker, Bremslicht und Rückfahrwarner

Bording

Well-known member
Supermoderator
VIP Unterstützt modelltruck.net 2024
Registriert
08.08.2007
Beiträge
1.949
Hallo,

ich braucht für mein "neues" Projekt noch eine Lichtsteuerung. Eigentlich war die erst später im Jahr vorgesehen.

- Basis Arduino Nano
- zwei Servosignale werden eingelesen: Fahrtenregler und ein Schaltkanal
- der Fahrtenregler steuert das Bremslicht, den Rückfahrwarner und den Rückfahrscheinwerfer
- Der Schaltkanal steuert: als Tastfunktion die Blinker/Warnblinker
- als Schaltfunktion z.B. Fahrlicht und Fernlicht

Schalten tut der Arduino +5V, da muss man noch eine Treiberstufe dranhängen wenn man mehrere LEDs ansteuern will.

Code:
// Pin 2: Schaltmodul mit Bremslicht und Rückfahrscheinwerfer und Rückfahrwarner
// Pin 3: Schaltmodul mit Blinker/Warnblinker und zwei unabhängigen Lichtkanälen
// für Arduino Nano

const byte PIN_RC = 2; // das ist INT 0 aber Pin 2 wo das Empfängersignal Rückfahrwarmer & Bremslicht eingelesen wird
// alles was im Interrupt läuft muss als volatile deklariert werden
//volatile int RcValue;  // Eingelesener Wert direkt aus dem RAM w.g. volatile)
volatile int ReceivedSpeedValues[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 =1500; // Mittelwert aus der Summe 
volatile int Zeiger =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange =0;
volatile long nMicros =0;
volatile long nDifference =0;

const byte PIN_RC3 = 3; // das ist INT 1 aber Pin 3 wo das Empfängersignal Blinker eingelesen wird
volatile int ReceivedSpeedValues3[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // Array mit 8 Werten für die gemessenen Werte
volatile int Summe3 = 12000; // Summe aus dem Array 8x1500, als Anfangswert
volatile int Mittelwert3 =1500; // Mittelwert aus der Summe 
volatile int Zeiger3 =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange3 =0;
volatile long nMicros3 =0;
volatile long nDifference3 =0;


// Für Rückfahrwarner und Bremslicht
const byte LED = 4;           // pin 4 - Rückfahr LED weiß
const byte LEDrt = 5;         // pin 5 - Bremslicht rot
const byte speakerPin = 6;    // pin 6  (PWM) - Lautsprecher

boolean Null = 0;             // Nullstellung wird erkannt
boolean vorher_Null = 0;      // Nullstellung vorher
int frequency  = 1300;        // 1300Hz für den Pieper
int duration = 400;           // Dauer des Tons
unsigned long zeit = 0;       // Systemzeit
unsigned long zeit1_alt =0;   // alte Systemzeit 1 Rücklicht
unsigned long zeit2_alt =0;   // alte Systemzeit 2 Bremslicht
bool RVS = false;             // Status Rückwärts

// Für den Blinker und Fahrlicht
const byte Blink_re=7;        // pin 7 - Blinker rechts
const byte Blink_li=8;        // pin 8 - Blinker links
const byte Licht_re=9;        // pin 9 - Licht rechts
const byte Licht_li=10;       // pin 10 - Links links

unsigned long Dauer_re =0;    // Dauer wie lange Knüppel rechts war
unsigned long Pos_zeit_re =0; // Positionszeit rechts
unsigned long Dauer_li =0;    // Dauer wie lange Knüppel links war
unsigned long Pos_zeit_li =0; // Positionszeit links
unsigned long Takt =0;        // Hilfszeit für Blinktakt

bool Umschaltsperre_re = false;  // Knüppelposition wird abgefragt
bool Umschaltsperre_li = false;  // Knüppelposition wird abgefragt
bool Blink_re_an = false;        // Blinkfunktion rechts ein
bool Blink_li_an = false;        // Blinkfunktion links ein
bool Blink_re_Status = false;    // Blink LED rechts AN/AUS
bool Blink_li_Status = false;    // Blink LED rechts AN/AUS
byte i = 0;                      // Zähler für die Blinktakte
bool WarnBlink = false;          // Warnblinker
bool Licht_re_an = false;
bool Licht_li_an = false;
bool Licht_re_Sperre = false;     //Einschaltsperre Dauerlicht
bool Licht_li_Sperre = false;     //Einschaltsperre Dauerlicht

void setup() 
{ 
pinMode (LED, OUTPUT);       // Rückfahrlicht
pinMode (LEDrt, OUTPUT);     // Bremslicht LED
pinMode (Blink_re, OUTPUT);  // Blinker rechts
pinMode (Blink_li, OUTPUT);  // Blinker links
pinMode (Licht_re, OUTPUT);  // Licht rechts
pinMode (Licht_li, OUTPUT);  // Licht links

pinMode(PIN_RC, INPUT);      // Eingang für Empfängersignal an Pin 2   
pinMode(PIN_RC3, INPUT);     // Eingang für Empfängersignal an Pin 3  

attachInterrupt( 0, SpeedPositionInterrupt, CHANGE); // 0=Interrupt 0,also Pin2 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 2 sich ändert
attachInterrupt( 1, SpeedPositionInterrupt3, CHANGE); // 1=Interrupt 1,also Pin3 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 3 sich ändert

Serial.begin(9600); // nur für debugging und Test
} 


void SpeedPositionInterrupt() //Interrupt fragt Pin 2 ab
{
	nMicros = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
	nDifference  = (nMicros - LastSpeedChange); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

	if ( (nDifference > 900 ) && ( nDifference < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
	{
		Summe -= ReceivedSpeedValues[Zeiger]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
		ReceivedSpeedValues[Zeiger] = nDifference; // Array mit 8 Werten für die gemessenen Wert 
		Summe	+= nDifference; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
		Zeiger	 = ( ( Zeiger + 1 ) & 0x07 );	//	Index erhoehen und ggf. von 8 auf 0 springen
		Mittelwert = ( Summe >> 3 );	//der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
	}
	LastSpeedChange	= nMicros;
}

void SpeedPositionInterrupt3() //Interrupt fragt Pin 3 ab
{
  nMicros3 = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
  nDifference3  = (nMicros3 - LastSpeedChange3); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

  if ( (nDifference3 > 900 ) && ( nDifference3 < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
  {
    Summe3 -= ReceivedSpeedValues3[Zeiger3]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
    ReceivedSpeedValues3[Zeiger3] = nDifference3; // Array mit 8 Werten für die gemessenen Wert 
    Summe3 += nDifference3; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
    Zeiger3   = ( ( Zeiger3 + 1 ) & 0x07 ); //  Index erhoehen und ggf. von 8 auf 0 springen
    Mittelwert3 = ( Summe3 >> 3 );  //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
  }
  LastSpeedChange3 = nMicros3;

}

void loop() 
{ 
zeit = millis ();    // aktuelle Systemzeit in zeit1 schreiben

// Rückfahrlicht + Pieper

if (Mittelwert < 1450) {                         // Fahrzeug fährt rückwärts
  digitalWrite (LED,HIGH);                       // Rückfahrscheinwerfer ein
  RVS = true;                                    // Status Rückwärts
  }

if (RVS == true && (zeit - zeit1_alt >=800)) {   // Status Rückwärts UND Zeitdifferenz ist größer 800 ms
  tone(speakerPin, frequency, duration);         // 400 ms Ton ausgeben
  zeit1_alt = zeit;                              // aktuelle Zeit in Zeit1_alt schreiben -> hierdurch wird der Intervall gemacht.
  }
   

if (Mittelwert >1451) {                          // Fahrzeug ist in Neutral oder fährt vorwärts
  digitalWrite (LED,LOW);                        // Rückfahrscheinwerfer aus
  RVS = false;                                   // Status Rückwärts
 }

 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 //
 // Bremslicht
 
if ((Mittelwert >1450) &&(Mittelwert <1550)) {     // war 1450 und 1550 Abfrage Nullstellung 
    Null = true;
    } 
    
if (vorher_Null == false && Null == true)
    {                                              //vorher kein Null -> jetzt Null-> Bremslicht an
      digitalWrite (LEDrt,HIGH);                   //LED Bremslicht ein    
      zeit2_alt = millis ();                       //Zeit für Timer setzen
    }
    
if ((zeit - zeit2_alt >= 3000) || Null == false) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, dann Bremslicht aus
    digitalWrite (LEDrt,LOW);                       //LED Bremslicht aus  
    }

vorher_Null = Null;                                // alten Null Wert speichern
Null = false;                                      // aktuellen Nullwert zurück setzen


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker RECHTS für 8x blinken 420 ms / 420 ms + Licht
      
if ((Mittelwert3 >= 1800) && (Umschaltsperre_re == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_re = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_re = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_re == true){                           // Umschaltsperre ausschalten wenn der Knüppel in Null ist
    Dauer_re = (millis () - Pos_zeit_re);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_re <= 800) && (Mittelwert3 <= 1650)) {   //Verweildauer kleiner 800 UND Knüppel wieder in Null -> Blinker ein
          Blink_re_an = true;                             //Blinker rechts an
         }
      if ((Dauer_re >= 1001)&& (Licht_re_Sperre == false)) { //Verweildauer größer 1001 -> Licht ein
         Licht_re_an = true;
         Dauer_re = 0;                                       //Verweildauer löschen
         }
     if ((Dauer_re >= 1001)&& (Licht_re_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_re_an = false;
         Dauer_re = 0;                                       //Verweildauer löschen
         }  
       }

if (Mittelwert3 <= 1650){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_re = false;  
          }

if ((Mittelwert3 <= 1650) && (Licht_re_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_re_Sperre = true;  
          }
          
if ((Mittelwert3 <= 1650) && (Licht_re_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_re_Sperre = false;  
          }
 
if ((Blink_re_an == true) && (Blink_li_an == false)&& (WarnBlink == false)) {     //Blinken ein
   
    if (millis () - Takt > 420){                           //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_re_an = false;                                 //Blinker rechts aus
      Blink_re_Status = false;                             //Ausgangsstatus Blinker rechts auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
      
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker LINKS für 8x blinken 420 ms / 420 ms + Licht

if ((Mittelwert3 <= 1150) && (Umschaltsperre_li == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_li = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_li = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_li == true){                           
    Dauer_li = (millis () - Pos_zeit_li);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_li <= 800) && (Mittelwert3 >= 1350)) {   //Verweildauer kleiner 800 UND Knüppel wieder in der Mitte -> Blinker ein
          Blink_li_an = true;                             //Blinker links an                         
         }
      if ((Dauer_li >= 1001)&& (Licht_li_Sperre == false)) {  //Verweildauer größer 1011 -> Licht ein
         Licht_li_an = true;
         Dauer_li = 0;                                      //Verweildauer löschen
         }
     if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_li_an = false;
         Dauer_li = 0;                                      //Verweildauer löschen
         }  
   }

if (Mittelwert3 >= 1350){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_li = false;  
          }

if ((Mittelwert3 >= 1350) && (Licht_li_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_li_Sperre = true;  
          }
          
if ((Mittelwert3 >= 1350) && (Licht_li_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_li_Sperre = false;  
          }
          
if ((Blink_li_an == true) && (Blink_re_an == false)&& (WarnBlink == false)) {     // Blinken ein
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_li_Status = !Blink_li_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_li_an = false;                                 //Blinker links aus
      Blink_li_Status = false;                               //Ausgangsstatus Blinker links auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
    
 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 //  Warnblinker Logik
   
 if ((Blink_li_an == true) && (Blink_re_an == true) && (WarnBlink == false)) {  // Warnblinker ein wenn der andere Blinker schon blinkt
      WarnBlink = true;                                     //Warnblinker gesetzt
      Blink_li_an = false;                                  //Blinker links aus
      Blink_re_an = false;                                  //Blinker rechts aus
      Blink_li_Status = false;                              //LED erst mal aus wegen synchronisation
      Blink_re_Status = false;                              //LED erst mal aus wegen synchronisation
      i = 0;                                                //Zähler zurücksetzen     
      }
      
 if (WarnBlink == true) {
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      Blink_li_Status = !Blink_li_Status;                      
      }
      }

if ((WarnBlink == true) && (Blink_re_Status == false) && (Blink_li_Status == false) && ((Blink_li_an == true) || (Blink_re_an == true))) {    
                                                         // wird nur abgeschaltet wenn LED aus (Pause)
      WarnBlink = false;
      Blink_li_an = false;                                //Blinker links aus
      Blink_re_an = false;                                //Blinker rechts aus
      Blink_li_Status = false;                            //LED aus
      Blink_re_Status = false;                            //LED aus
    }
    
    digitalWrite (Blink_li,Blink_li_Status); // Blinker links ein/aus
    digitalWrite (Blink_re,Blink_re_Status); // Blinker rechts ein/aus
     
    digitalWrite (Licht_li,Licht_li_an); // Licht links ein/aus
    digitalWrite (Licht_re,Licht_re_an); // Licht rechts ein/aus

    
/*//   Serial.print ("Mittelwert ");
//Serial.println(Mittelwert);          // Anzeige des Mittelwertes 

Serial.print ("Knüppelzeit li ");
Serial.println(Dauer_li);          // Anzeige des Mittelwertes

Serial.print ("Knüppelzeit re ");
Serial.println(Dauer_re);          // Anzeige des Mittelwertes
  
Serial.print ("Rechts ");
Serial.println(Rechts);          // Anzeige des Mittelwertes
Serial.print ("Rechts an ");
Serial.println(Rechts_an);          // Anzeige des Mittelwertes
Serial.print ("Takt ");
Serial.println(Takt);          // Anzeige des Mittelwertes
/*/
}

Der Code ist schon was für Fortgeschrittene, aber sonst komplett kommentiert (ich such sonst selber zu lange rum ;))
 
Moin Bert,
das Programm schaut wirklich sehr gut aus. Das könnte das sein was ich gesucht habe. Ich werd mal schauen ob ich das hinbekomme.
Danke mal im voraus fürs einstellen. :ok:thx
 
Moin Bert,

ich habe den Quelltext mal überflogen und habe ein paar Tipps:

1. Den Array für die Mittelwertberechnung solltest du auf 4 Werte reduzieren. Bei 8 Werten brauchst du sonst mind. 160ms bis der tatsächliche Wert erreicht ist. Solange du die Werte nur ausliest ist das kein so großes Problem, aber sobald zu mit diesen Werten später mal einen Servo ansteuern möchtest bekommst du ein spürbares delay.

2. Ich empfehle dir eine Nullstelleneinmessung. Nach den Setzen der Interrupts durch attachInterrrupt() machst du per delay() eine Pause von z. B. 500ms. Danach nimmst du den aktuellen Mittelwert des Speed bzw. Schalters als Nullstellung. Nun berechnest du dir mit -50 und +50 von diesen Werten die Grenzwerte des Totpunkts. So bist du flexibel und egal wie der Sender programmiert ist, der Totpunkt ist am Knüppel immer gleich.

3. Bei der automatischen Aktivierung der Blinker hast du einen festen Schwellenwert. Dies kann, wenn der Knüppel sich an dieser Position einen ständigen Wechsel zwischen "An" und "Aus" bedeuten, dein Blinker "zuckt". Dies kann man durch überlappende Bereiche und aktive Bereiche lösen. Beispiel: Der Bereich für "Blinker aus" ist 1300 - 1700. Der Bereich für Blinker links ist 1000 - 1350, der für rechts ist 1650 - 2000. Du siehst eine Überschneidung der Bereiche um 50. Am Anfang setzt die den aktiven Bereich auf "Blinker aus". Im loop() prüfst du ob du noch im aktuellen Bereich bist. Wenn ja, passiert nichts. Hast du den Bereich verlassen suchst du nach einem anderen Bereich der nun gültig ist. Der neue Bereich wird als "aktiv" definiert. Aufgrund der Überlappung bist du bei diesem Bereich nun 50 ms vom Rand weg, es kommt nicht zum andauernden Springen zwischen zwei Bereichen. Die Überlappung kann auch z. B. nur 20 sein. Das hängt davon ab wie groß die Schwankung des Servowerts bei absoluter Ruhe am Kanal ist. Wenn der gemessene Wert immer nur um 4 Punkts nach oben und unten schwant, dann reicht z. B. eine Überlappung von 10-20.

4. Die LEDs: Ich würde sie nicht per 5V direkt schalten. Schalte statt dessen einen Transistor auf Masse. So kannst du auch mehrere LEDs schalten ohne die sehr niedrige mA Zahl des Arduino Pins zu überschreiten.

5. Strom sparen: Setze mal am Anfang und am Ende der loop einen micros() Aufruf und berechne die Differenz (bei deaktivierten Debug Ausgaben). So siehst du die Laufzeit eines Loop Durchgangs. Nun kannst du die Differenz zu 20 Millisekunden berechnen und dies am Ende mit delay() verbraten. So sparst du CPU Last und somit Strom. Der Chip wird auch nicht warm. Bedenke, ein Servosignal dauert 20 Millisekunden, d. h. in dieser Zeit tut sich nichts an den Werten. Es macht also keinen Sinn den loop() z. B. 20 mal zu durchlaufen. Die Zeiten zum Schalten der LEDs für Blinker oder Pieper an/aus können sicherlich auch "nur" alle 20 Millisekunden aktualisiert werden, das fällt nicht ins Gewicht.

So... Das waren erst einmal meine ersten Bemerkungen. Wenn ich Zeit habe schaue ich mir mal deinen loop() genauer an.
 
Hallo Bert,

interessantes Projekt. :ok - Respekt!
"Nachbauen" und den (fertigen) Code auf einen Arduino hochladen kann ich inzwischen auch schon ganz gut; einen eigenen, umfangreicheren Code erstellen krieg' ich jedoch noch nicht richtig hin. :heilig
 
Hallo zusammen,

danke erst einaml für Eure Kommentare.

#Peter

das mit dem 8er Array ist mir bewusst. Ich habe bei meinem "Kettenregler" extra ein 32er Array für eine sanfte Beschleunigung/Verzögerung eingebaut.

die Nulleinmessung ist noch ein guter Punkt den ich mir mal genauer ansehen werde. Hast du da einen Code den du mal posten könntest?

die Schwellwerte mit dem Blinker fünktionieren dank der "glättung" durch das 8er Array ganz gut

ich werde die LED nicht direkt anschließen. Im allgemeinen nutze ich einen PNP Transistor zum Masse schalten und auf der + Seite manchmal eine Konstantstromquelle.

an den Delay habe ich so noch nicht gedacht. Werde mal sehen wie die Looptime ist.
 
Hallo lieber Bert,
hab gerade mal die Schaltung aufgebaut und ausprobiert.
Für mich, der ich ja ein absoluter Anfänger bin, funktioniert sie SUPER. :ok:ok:ok
 
Hallo,

anbei ein Bremslichtmodul für an Atiny 85

Code:
// Schaltmodul über RCKanal mit Bremslicht und Rückfahrscheinwerfer und Rückfahrwarner
// für Attiny 85-20 mit 8 MHz 

const byte PIN_RC = 1; // PB1 ist an pin 6 -  wo das Empfängersignal eingelesen wird!!!!
volatile int RcValue;  // Eingelesener Wert direkt aus dem RAM w.g. volatile)
volatile int ReceivedSpeedValues[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 =1500; // Mittelwert aus der Summe 
volatile int Zeiger =0; // Zeiger für das Array, fängt mit 0 an

int timer_loop = 0; //Schleife bis LED aus
boolean Null = 0; // Nullstellung wird erkannt
boolean vorher_Null = 0; // Nullstellung vorher

const byte LED=3; // PB3  ist an pin 2 - Rückfahr LED weiß
const byte LEDrt=4; // PB4 ist an pin3 - Bremslicht rot
const byte speakerPin = 0;    // PB0 ist an pin 5  (PWM) - Lautsprecher
int frequency  = 1300; // 1300Hz 
int duration = 400;   // Dauer des Tons
int ton_loop = 0;  // Intervallzeit für den Ton


void setup() 
{ 
pinMode (LED, OUTPUT); // Rückfahrlicht
pinMode (LEDrt, OUTPUT); // Bremslicht LED
pinMode(PIN_RC, INPUT);  // Eingang für Empfängersignal an Pin 2   
//digitalWrite(PIN_RC, HIGH);
} 

void loop() 
{ 
Summe = Summe - ReceivedSpeedValues[Zeiger]; // substrahiere letzte Messung aus dem Array  
   RcValue = pulseIn(PIN_RC, HIGH, 100000); // Aktuellen RC-Wert vom Empfänger einlesen, HIGH = Flanke, 100000 = Timeout
   ReceivedSpeedValues[Zeiger] = RcValue; // eingelesener Wert neu in das Array
   Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe   
   Zeiger = Zeiger + 1; // zur naechsten Position im Array  
   
if (Zeiger >=7) {
   Zeiger = 0; }// wieder zum Anfang des Arrays                        

Mittelwert = (Summe >>3); // Mittelwert aus dem Array wird durch 8 geteilt     
delay(50);  // Zeitbasis für die Loop-Timer 
 
if (Mittelwert < 1450) { //war 1450
  digitalWrite (LED,HIGH); // Rückfahrscheinwerfer ein
  ton_loop = ton_loop + 1; // als Ersatz für den Pausetimer gibt es dises Schleife
    if (ton_loop <=1) { // am Anfang Ton einschalten
    tone(speakerPin, frequency, duration); // 400 ms Ton ausgeben
    }
    if (ton_loop == 15) { // Intervallzeit für den Ton 15*10ms = 200 ms
    ton_loop = 0;} // wenn Intervall voll, Loop wieder zurück setzen
}
if (Mittelwert >1451) { // war 1451
  digitalWrite (LED,LOW); // Rückfahrscheinwerfer aus
  ton_loop = 0; // Ton_loop aus
 }
if ((Mittelwert >1450) &&(Mittelwert <1550)) {// war 1450 und 1550 Abfrage Nullstellung 
  Null = true;
} 
    if (vorher_Null == false && Null == true)
    { //vorher kein Null -> jetzt Null-> Bremslicht an
      digitalWrite (LEDrt,HIGH);
      timer_loop = 0; // timer auf 0 setzen
    }
    if (timer_loop == 200 || Null == false) { // wenn timer = 2000 -> 10s oder wieder FWD bzw RVS, dann Bremslicht aus
    digitalWrite (LEDrt,LOW);
    }
vorher_Null = Null; // alten Null Wert speichern
Null = false; // aktuellen Nullwert zurück setzen
timer_loop = timer_loop +1; // Timer um 1 hochzählen
}
 
Hallo Bert,

danke für dieses Modul. :trucker Ich wollte es für meinen GAZ anpassen. Dazu wollte ich die Fkt. Licht rechts erweitern und zwar dass bei eingeschaltetem Licht, das Bremslicht mit halber Helligkeit leuchtet, die Frontlichter mit halber Helligkeit und ein zusätzlicher Ausgang LED für die Begrenzungsleuchten. Ich habe das mit dem Befehl analogWrite gelöst. Als Frontlicht habe ich die LED vom Licht links definiert. Als Begrenzungsleuchten die LED rechts, Rücklicht ist LEDrt. Es funktioniert aber nur wenn ich den Knüppel rechts halte. :sauer Lasse ich ihn wieder los (Mittelstellung) leuchtet nur die LED rechts. Was mache ich falsch? Hier der von mir bearbeitete Code:
PHP:
// Pin 2: Schaltmodul mit Bremslicht und Rückfahrscheinwerfer und Rückfahrwarner
// Pin 3: Schaltmodul mit Blinker/Warnblinker und zwei unabhängigen Lichtkanälen
// für Arduino Nano

const byte PIN_RC = 2; // das ist INT 0 aber Pin 2 wo das Empfängersignal Rückfahrwarmer & Bremslicht eingelesen wird
// alles was im Interrupt läuft muss als volatile deklariert werden
//volatile int RcValue;  // Eingelesener Wert direkt aus dem RAM w.g. volatile)
volatile int ReceivedSpeedValues[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 =1500; // Mittelwert aus der Summe 
volatile int Zeiger =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange =0;
volatile long nMicros =0;
volatile long nDifference =0;

const byte PIN_RC3 = 3; // das ist INT 1 aber Pin 3 wo das Empfängersignal Blinker eingelesen wird
volatile int ReceivedSpeedValues3[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // Array mit 8 Werten für die gemessenen Werte
volatile int Summe3 = 12000; // Summe aus dem Array 8x1500, als Anfangswert
volatile int Mittelwert3 =1500; // Mittelwert aus der Summe 
volatile int Zeiger3 =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange3 =0;
volatile long nMicros3 =0;
volatile long nDifference3 =0;

//Lichtstärke Rücklichter
const byte PWM_Half_Heck = 50;
//Lichtstärke Standlicht
const byte PWM_Half_Front = 50;
//PWM Definition für halbe und volle Leistung
const byte PWM_Full = 255;

// Für Rückfahrwarner und Bremslicht
const byte LED = 4;           // pin 4 - Rückfahr LED weiß
const byte LEDrt = 5;         // pin 5 - Bremslicht rot PWM
const byte speakerPin = 6;    // pin 6  (PWM) - Lautsprecher

boolean Null = 0;             // Nullstellung wird erkannt
boolean vorher_Null = 0;      // Nullstellung vorher
int frequency  = 1300;        // 1300Hz für den Pieper
int duration = 400;           // Dauer des Tons
unsigned long zeit = 0;       // Systemzeit
unsigned long zeit1_alt =0;   // alte Systemzeit 1 Rücklicht
unsigned long zeit2_alt =0;   // alte Systemzeit 2 Bremslicht
bool RVS = false;             // Status Rückwärts

// Für den Blinker und Fahrlicht
const byte Blink_re=7;        // pin 7 - Blinker rechts
const byte Blink_li=8;        // pin 8 - Blinker links
const byte Licht_beg=9;        // pin 9 - Begrenzungslichter
const byte Licht_front=10;       // pin 10 - Frontlichter PWM
const byte Licht_re=9;
const byte Licht_li=10;

unsigned long Dauer_re =0;    // Dauer wie lange Knüppel rechts war
unsigned long Pos_zeit_re =0; // Positionszeit rechts
unsigned long Dauer_li =0;    // Dauer wie lange Knüppel links war
unsigned long Pos_zeit_li =0; // Positionszeit links
unsigned long Takt =0;        // Hilfszeit für Blinktakt

bool Umschaltsperre_re = false;  // Knüppelposition wird abgefragt
bool Umschaltsperre_li = false;  // Knüppelposition wird abgefragt
bool Blink_re_an = false;        // Blinkfunktion rechts ein
bool Blink_li_an = false;        // Blinkfunktion links ein
bool Blink_re_Status = false;    // Blink LED rechts AN/AUS
bool Blink_li_Status = false;    // Blink LED rechts AN/AUS
byte i = 0;                      // Zähler für die Blinktakte
bool WarnBlink = false;          // Warnblinker
bool Licht_re_an = false;
bool Licht_li_an = false;
bool Licht_re_Sperre = false;     //Einschaltsperre Dauerlicht
bool Licht_li_Sperre = false;     //Einschaltsperre Dauerlicht

void setup() 
{ 
pinMode (LED, OUTPUT);       // Rückfahrlicht
pinMode (LEDrt, OUTPUT);     // Bremslicht LED
pinMode (Blink_re, OUTPUT);  // Blinker rechts
pinMode (Blink_li, OUTPUT);  // Blinker links
pinMode (Licht_front, OUTPUT);  // Frontlichter
pinMode (Licht_beg, OUTPUT);  // Begrenzungslichter

pinMode(PIN_RC, INPUT);      // Eingang für Empfängersignal an Pin 2   
pinMode(PIN_RC3, INPUT);     // Eingang für Empfängersignal an Pin 3  

attachInterrupt( 0, SpeedPositionInterrupt, CHANGE); // 0=Interrupt 0,also Pin2 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 2 sich ändert
attachInterrupt( 1, SpeedPositionInterrupt3, CHANGE); // 1=Interrupt 1,also Pin3 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 3 sich ändert

Serial.begin(9600); // nur für debugging und Test
} 


void SpeedPositionInterrupt() //Interrupt fragt Pin 2 ab
{
	nMicros = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
	nDifference  = (nMicros - LastSpeedChange); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

	if ( (nDifference > 900 ) && ( nDifference < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
	{
		Summe -= ReceivedSpeedValues[Zeiger]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
		ReceivedSpeedValues[Zeiger] = nDifference; // Array mit 8 Werten für die gemessenen Wert 
		Summe	+= nDifference; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
		Zeiger	 = ( ( Zeiger + 1 ) & 0x07 );	//	Index erhoehen und ggf. von 8 auf 0 springen
		Mittelwert = ( Summe >> 3 );	//der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
	}
	LastSpeedChange	= nMicros;
}

void SpeedPositionInterrupt3() //Interrupt fragt Pin 3 ab
{
  nMicros3 = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
  nDifference3  = (nMicros3 - LastSpeedChange3); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

  if ( (nDifference3 > 900 ) && ( nDifference3 < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
  {
    Summe3 -= ReceivedSpeedValues3[Zeiger3]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
    ReceivedSpeedValues3[Zeiger3] = nDifference3; // Array mit 8 Werten für die gemessenen Wert 
    Summe3 += nDifference3; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
    Zeiger3   = ( ( Zeiger3 + 1 ) & 0x07 ); //  Index erhoehen und ggf. von 8 auf 0 springen
    Mittelwert3 = ( Summe3 >> 3 );  //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
  }
  LastSpeedChange3 = nMicros3;

}

void loop() 
{ 
zeit = millis ();    // aktuelle Systemzeit in zeit1 schreiben

// Rückfahrlicht + Pieper

if (Mittelwert < 1450) {                         // Fahrzeug fährt rückwärts
  digitalWrite (LED,HIGH);                       // Rückfahrscheinwerfer ein
  RVS = true;                                    // Status Rückwärts
  }

if (RVS == true && (zeit - zeit1_alt >=800)) {   // Status Rückwärts UND Zeitdifferenz ist größer 800 ms
  tone(speakerPin, frequency, duration);         // 400 ms Ton ausgeben
  zeit1_alt = zeit;                              // aktuelle Zeit in Zeit1_alt schreiben -> hierdurch wird der Intervall gemacht.
  }
   

if (Mittelwert >1451) {                          // Fahrzeug ist in Neutral oder fährt vorwärts
  digitalWrite (LED,LOW);                        // Rückfahrscheinwerfer aus
  RVS = false;                                   // Status Rückwärts
 }

 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 //
 // Bremslicht
 
if ((Mittelwert >1450) &&(Mittelwert <1550)) {     // war 1450 und 1550 Abfrage Nullstellung 
    Null = true;
    } 
    
if (vorher_Null == false && Null == true)
    {                                              //vorher kein Null -> jetzt Null-> Bremslicht an
      digitalWrite (LEDrt,HIGH);                   //LED Bremslicht ein    
      zeit2_alt = millis ();                       //Zeit für Timer setzen
    }
    
if ((zeit - zeit2_alt >= 3000) || Null == false) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, dann Bremslicht aus
    digitalWrite (LEDrt,LOW);                       //LED Bremslicht aus  
    }

vorher_Null = Null;                                // alten Null Wert speichern
Null = false;                                      // aktuellen Nullwert zurück setzen


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker RECHTS für 8x blinken 420 ms / 420 ms + Licht
      
if ((Mittelwert3 >= 1800) && (Umschaltsperre_re == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_re = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_re = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_re == true){                           // Umschaltsperre ausschalten wenn der Knüppel in Null ist
    Dauer_re = (millis () - Pos_zeit_re);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_re <= 800) && (Mittelwert3 <= 1650)) {   //Verweildauer kleiner 800 UND Knüppel wieder in Null -> Blinker ein
          Blink_re_an = true;                             //Blinker rechts an
         }
      if ((Dauer_re >= 1001)&& (Licht_re_Sperre == false)) { //Verweildauer größer 1001 -> Licht ein
         Licht_re_an = true ;
         Dauer_re = 0;                                       //Verweildauer löschen
         }
     if ((Dauer_re >= 1001)&& (Licht_re_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_re_an = false;
         Dauer_re = 0;                                       //Verweildauer löschen
         }  
       }

if (Mittelwert3 <= 1650){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_re = false;  
          }

if ((Mittelwert3 <= 1650) && (Licht_re_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_re_Sperre = true;  
          }
          
if ((Mittelwert3 <= 1650) && (Licht_re_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_re_Sperre = false;  
          }
 
if ((Blink_re_an == true) && (Blink_li_an == false)&& (WarnBlink == false)) {     //Blinken ein
   
    if (millis () - Takt > 420){                           //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_re_an = false;                                 //Blinker rechts aus
      Blink_re_Status = false;                             //Ausgangsstatus Blinker rechts auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
      
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker LINKS für 8x blinken 420 ms / 420 ms + Licht

if ((Mittelwert3 <= 1150) && (Umschaltsperre_li == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_li = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_li = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_li == true){                           
    Dauer_li = (millis () - Pos_zeit_li);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_li <= 800) && (Mittelwert3 >= 1350)) {   //Verweildauer kleiner 800 UND Knüppel wieder in der Mitte -> Blinker ein
          Blink_li_an = true;                             //Blinker links an                         
         }
      if ((Dauer_li >= 1001)&& (Licht_li_Sperre == false)) {  //Verweildauer größer 1011 -> Licht ein
         Licht_li_an = true;
         analogWrite (Licht_front,PWM_Half_Front);
         analogWrite (LEDrt,PWM_Half_Heck);
         digitalWrite (Licht_beg,HIGH);
         Dauer_li = 0;                                      //Verweildauer löschen
         }
     if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_li_an = false;
         Dauer_li = 0;                                      //Verweildauer löschen
         }  
   }

if (Mittelwert3 >= 1350){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_li = false;  
          }

if ((Mittelwert3 >= 1350) && (Licht_li_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_li_Sperre = true;  
          }
          
if ((Mittelwert3 >= 1350) && (Licht_li_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_li_Sperre = false;  
          }
          
if ((Blink_li_an == true) && (Blink_re_an == false)&& (WarnBlink == false)) {     // Blinken ein
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_li_Status = !Blink_li_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_li_an = false;                                 //Blinker links aus
      Blink_li_Status = false;                               //Ausgangsstatus Blinker links auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
    
 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 //  Warnblinker Logik
   
 if ((Blink_li_an == true) && (Blink_re_an == true) && (WarnBlink == false)) {  // Warnblinker ein wenn der andere Blinker schon blinkt
      WarnBlink = true;                                     //Warnblinker gesetzt
      Blink_li_an = false;                                  //Blinker links aus
      Blink_re_an = false;                                  //Blinker rechts aus
      Blink_li_Status = false;                              //LED erst mal aus wegen synchronisation
      Blink_re_Status = false;                              //LED erst mal aus wegen synchronisation
      i = 0;                                                //Zähler zurücksetzen     
      }
      
 if (WarnBlink == true) {
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      Blink_li_Status = !Blink_li_Status;                      
      }
      }

if ((WarnBlink == true) && (Blink_re_Status == false) && (Blink_li_Status == false) && ((Blink_li_an == true) || (Blink_re_an == true))) {    
                                                         // wird nur abgeschaltet wenn LED aus (Pause)
      WarnBlink = false;
      Blink_li_an = false;                                //Blinker links aus
      Blink_re_an = false;                                //Blinker rechts aus
      Blink_li_Status = false;                            //LED aus
      Blink_re_Status = false;                            //LED aus
    }
    
    digitalWrite (Blink_li,Blink_li_Status); // Blinker links ein/aus
    digitalWrite (Blink_re,Blink_re_Status); // Blinker rechts ein/aus
     
    digitalWrite (Licht_li,Licht_li_an); // Licht links ein/aus
    digitalWrite (Licht_re,Licht_re_an); // Licht rechts ein/aus

    
/*//   Serial.print ("Mittelwert ");
//Serial.println(Mittelwert);          // Anzeige des Mittelwertes 

Serial.print ("Knüppelzeit li ");
Serial.println(Dauer_li);          // Anzeige des Mittelwertes

Serial.print ("Knüppelzeit re ");
Serial.println(Dauer_re);          // Anzeige des Mittelwertes
  
Serial.print ("Rechts ");
Serial.println(Rechts);          // Anzeige des Mittelwertes
Serial.print ("Rechts an ");
Serial.println(Rechts_an);          // Anzeige des Mittelwertes
Serial.print ("Takt ");
Serial.println(Takt);          // Anzeige des Mittelwertes
/*/
}

Viele Grüße Carsten
 
Hallo Carsten,

du hast in der Deklaration der Konstanten Pin 9 und 10 zwei mal definiert

Code:
// Für den Blinker und Fahrlicht
const byte Blink_re=7;        // pin 7 - Blinker rechts
const byte Blink_li=8;        // pin 8 - Blinker links
const byte Licht_beg=9;        // pin 9 - Begrenzungslichter
const byte Licht_front=10;       // pin 10 - Frontlichter PWM
const byte Licht_re=9;
const byte Licht_li=10;

das wird ja nur einmal bearbeitet bei booten.

Hier gibt es auch noch mal einen Konflikt:

Code:
   if ((Dauer_li >= 1001)&& (Licht_li_Sperre == false)) {  //Verweildauer größer 1011 -> Licht ein
         Licht_li_an = true;
         analogWrite (Licht_front,PWM_Half_Front);
         analogWrite (LEDrt,PWM_Half_Heck);
         digitalWrite (Licht_beg,HIGH);
         Dauer_li = 0;                                      //Verweildauer löschen
         }
     if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_li_an = false;
         Dauer_li = 0;                                      //Verweildauer löschen
         }

Generell ist es einfacher zu debuggen wenn man den geänderten Code markiert bzw. den originalen Code als Kommentar drin lässt.
 
Hallo Bert,
danke, das Du über den Code drüber geschaut hast.:thx Ich bin Laie auf dem Gebiet der Programmierung. Alles was ich bisher weiß habe ich aus dem Internet und Büchern. Deshalb habe ich versucht mit meinen gefährlich Halbwissen etwas zu ändern. Mit Deinen Hinweisen habe ich alle von mir vorgenommenen Änderungen verworfen und noch mal aus einem anderen Blickwinkel darübergeschaut. Jetzt funktioniert es fast wie ich es wollte, mit einem kleinen Schönheitsfehler,:sauer das Licht links lässt sich nicht mehr ausschalten dafür geht es aber bei kurzer Bewegung des Knüppels nach rechts (bspw. Blinker rechts schalten) aus. Die zusätzlich an Pin 11 angeschlossene LED verlischt bei Rückwärtsfahrt.
Meine Änderungen/Ergänzungen habe ich der besseren Auffindbarkeit halber rot geschrieben:
Code:
// Pin 2: Schaltmodul mit Bremslicht und Rückfahrscheinwerfer und Rückfahrwarner
// Pin 3: Schaltmodul mit Blinker/Warnblinker und zwei unabhängigen Lichtkanälen
// für Arduino Nano

const byte PIN_RC = 2; // das ist INT 0 aber Pin 2 wo das Empfängersignal Rückfahrwarmer & Bremslicht eingelesen wird
// alles was im Interrupt läuft muss als volatile deklariert werden
//volatile int RcValue;  // Eingelesener Wert direkt aus dem RAM w.g. volatile)
volatile int ReceivedSpeedValues[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 =1500; // Mittelwert aus der Summe 
volatile int Zeiger =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange =0;
volatile long nMicros =0;
volatile long nDifference =0;

const byte PIN_RC3 = 3; // das ist INT 1 aber Pin 3 wo das Empfängersignal Blinker eingelesen wird
volatile int ReceivedSpeedValues3[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // Array mit 8 Werten für die gemessenen Werte
volatile int Summe3 = 12000; // Summe aus dem Array 8x1500, als Anfangswert
volatile int Mittelwert3 =1500; // Mittelwert aus der Summe 
volatile int Zeiger3 =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange3 =0;
volatile long nMicros3 =0;
volatile long nDifference3 =0;

[COLOR=#b22222]//Lichtstärke Rücklichter
const byte PWM_Half_Heck = 50;
//Lichtstärke Standlicht
const byte PWM_Half_Front = 50;
//PWM Definition für volle Leistung
const byte PWM_Full = 255;
//PWM Definition für aus
const byte PWM_aus = 0;
[/COLOR]
// Für Rückfahrwarner und Bremslicht
const byte LED = 4;           // pin 4 - Rückfahr LED weiß
const byte LEDrt = 5;         // pin 5 - Bremslicht rot
const byte speakerPin = 6;    // pin 6  (PWM) - Lautsprecher

boolean Null = 0;             // Nullstellung wird erkannt
boolean vorher_Null = 0;      // Nullstellung vorher
int frequency  = 1300;        // 1300Hz für den Pieper
int duration = 400;           // Dauer des Tons
unsigned long zeit = 0;       // Systemzeit
unsigned long zeit1_alt =0;   // alte Systemzeit 1 Rücklicht
unsigned long zeit2_alt =0;   // alte Systemzeit 2 Bremslicht
bool RVS = false;             // Status Rückwärts

// Für den Blinker und Fahrlicht
const byte Blink_re=7;        // pin 7 - Blinker rechts
const byte Blink_li=8;        // pin 8 - Blinker links
const byte Licht_re=9;        // pin 9 - Licht rechts
const byte Licht_li=10;       // pin 10 - Links links
[COLOR=#b22222]const byte Stand=11;           // pin 11 - Standlicht[/COLOR]

unsigned long Dauer_re =0;    // Dauer wie lange Knüppel rechts war
unsigned long Pos_zeit_re =0; // Positionszeit rechts
unsigned long Dauer_li =0;    // Dauer wie lange Knüppel links war
unsigned long Pos_zeit_li =0; // Positionszeit links
unsigned long Takt =0;        // Hilfszeit für Blinktakt

bool Umschaltsperre_re = false;  // Knüppelposition wird abgefragt
bool Umschaltsperre_li = false;  // Knüppelposition wird abgefragt
bool Blink_re_an = false;        // Blinkfunktion rechts ein
bool Blink_li_an = false;        // Blinkfunktion links ein
bool Blink_re_Status = false;    // Blink LED rechts AN/AUS
bool Blink_li_Status = false;    // Blink LED rechts AN/AUS
byte i = 0;                      // Zähler für die Blinktakte
bool WarnBlink = false;          // Warnblinker
bool Licht_re_an = false;
bool Licht_li_an = false;
bool Licht_re_Sperre = false;     //Einschaltsperre Dauerlicht
bool Licht_li_Sperre = false;     //Einschaltsperre Dauerlicht

void setup() 
{ 
pinMode (LED, OUTPUT);       // Rückfahrlicht
pinMode (LEDrt, OUTPUT);     // Bremslicht LED
pinMode (Blink_re, OUTPUT);  // Blinker rechts
pinMode (Blink_li, OUTPUT);  // Blinker links
pinMode (Licht_re, OUTPUT);  // Licht rechts
pinMode (Licht_li, OUTPUT);  // Licht links
[COLOR=#b22222]pinMode (Stand, OUTPUT);[/COLOR]
pinMode(PIN_RC, INPUT);      // Eingang für Empfängersignal an Pin 2   
pinMode(PIN_RC3, INPUT);     // Eingang für Empfängersignal an Pin 3  

attachInterrupt( 0, SpeedPositionInterrupt, CHANGE); // 0=Interrupt 0,also Pin2 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 2 sich ändert
attachInterrupt( 1, SpeedPositionInterrupt3, CHANGE); // 1=Interrupt 1,also Pin3 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 3 sich ändert

Serial.begin(9600); // nur für debugging und Test
} 


void SpeedPositionInterrupt() //Interrupt fragt Pin 2 ab
{
    nMicros = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
    nDifference  = (nMicros - LastSpeedChange); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

    if ( (nDifference > 900 ) && ( nDifference < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
    {
        Summe -= ReceivedSpeedValues[Zeiger]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
        ReceivedSpeedValues[Zeiger] = nDifference; // Array mit 8 Werten für die gemessenen Wert 
        Summe    += nDifference; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
        Zeiger     = ( ( Zeiger + 1 ) & 0x07 );    //    Index erhoehen und ggf. von 8 auf 0 springen
        Mittelwert = ( Summe >> 3 );    //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
    }
    LastSpeedChange    = nMicros;
}

void SpeedPositionInterrupt3() //Interrupt fragt Pin 3 ab
{
  nMicros3 = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
  nDifference3  = (nMicros3 - LastSpeedChange3); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

  if ( (nDifference3 > 900 ) && ( nDifference3 < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
  {
    Summe3 -= ReceivedSpeedValues3[Zeiger3]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
    ReceivedSpeedValues3[Zeiger3] = nDifference3; // Array mit 8 Werten für die gemessenen Wert 
    Summe3 += nDifference3; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
    Zeiger3   = ( ( Zeiger3 + 1 ) & 0x07 ); //  Index erhoehen und ggf. von 8 auf 0 springen
    Mittelwert3 = ( Summe3 >> 3 );  //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
  }
  LastSpeedChange3 = nMicros3;

}

void loop() 
{ 
zeit = millis ();    // aktuelle Systemzeit in zeit1 schreiben

// Rückfahrlicht + Pieper

if (Mittelwert < 1450) {                         // Fahrzeug fährt rückwärts
  digitalWrite (LED,HIGH);                       // Rückfahrscheinwerfer ein
  RVS = true;                                    // Status Rückwärts
  }

if (RVS == true && (zeit - zeit1_alt >=800)) {   // Status Rückwärts UND Zeitdifferenz ist größer 800 ms
  tone(speakerPin, frequency, duration);         // 400 ms Ton ausgeben
  zeit1_alt = zeit;                              // aktuelle Zeit in Zeit1_alt schreiben -> hierdurch wird der Intervall gemacht.
  }
   

if (Mittelwert >1451) {                          // Fahrzeug ist in Neutral oder fährt vorwärts
  digitalWrite (LED,LOW);                        // Rückfahrscheinwerfer aus
  RVS = false;                                   // Status Rückwärts
 }

 //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
 //
 // Bremslicht
 
if ((Mittelwert >1450) &&(Mittelwert <1550)) {     // war 1450 und 1550 Abfrage Nullstellung 
    Null = true;
    } 
    
if (vorher_Null == false && Null == true)
    {                                              //vorher kein Null -> jetzt Null-> Bremslicht an
      digitalWrite (LEDrt,HIGH);                   //LED Bremslicht ein    
      zeit2_alt = millis ();                       //Zeit für Timer setzen
    }
    
if (((zeit - zeit2_alt >= 3000) || Null == false)[COLOR=#b22222]&&(Licht_re_an == true)[/COLOR]) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, [COLOR=#b22222]dann Bremslicht = Rücklicht[/COLOR]
    [COLOR=#b22222]analogWrite (LEDrt,PWM_Half_Heck);                       //LED Bremslicht = Rücklicht[/COLOR] 
    }

if (((zeit - zeit2_alt >= 3000) || Null == false)[COLOR=#b22222]&&(Licht_re_an == false[/COLOR])) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, dann Bremslicht aus
    digitalWrite (LEDrt,LOW);                       //LED Bremslicht = Rücklicht aus  
    }
vorher_Null = Null;                                // alten Null Wert speichern
Null = false;                                      // aktuellen Nullwert zurück setzen


//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker RECHTS für 8x blinken 420 ms / 420 ms + Licht
      
if ((Mittelwert3 >= 1800) && (Umschaltsperre_re == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_re = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_re = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_re == true){                           // Umschaltsperre ausschalten wenn der Knüppel in Null ist
    Dauer_re = (millis () - Pos_zeit_re);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_re <= 800) && (Mittelwert3 <= 1650)) {   //Verweildauer kleiner 800 UND Knüppel wieder in Null -> Blinker ein
          Blink_re_an = true;                             //Blinker rechts an
         }
      if ((Dauer_re >= 1001)&& (Licht_re_Sperre == false)) { //Verweildauer größer 1001 -> Licht ein
         Licht_re_an = true;
         Dauer_re = 0;                                       //Verweildauer löschen
         }
       [COLOR=#b22222]if (Licht_re_an == true){
          analogWrite (Licht_li,PWM_Half_Front);             //Standlicht an
          analogWrite (Stand,PWM_Half_Front);                //Standlicht an
          analogWrite (LEDrt,PWM_Half_Heck);                 //Rücklichter an[/COLOR]
         }
     
     if ((Dauer_re >= 1001)&& (Licht_re_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
         Licht_re_an = false;
         Dauer_re = 0;                                       //Verweildauer löschen
         }  
      [COLOR=#b22222]if (Licht_re_an == false){
          analogWrite (Licht_li,PWM_aus);              //Standlicht aus
          analogWrite (Stand,PWM_aus);                 //Standlicht aus
          analogWrite (LEDrt,PWM_aus);                 //Rücklichter aus[/COLOR]       
     }
       }

if (Mittelwert3 <= 1650){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_re = false;  
          }

if ((Mittelwert3 <= 1650) && (Licht_re_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_re_Sperre = true;  
          }
          
if ((Mittelwert3 <= 1650) && (Licht_re_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_re_Sperre = false;  
          }
 
if ((Blink_re_an == true) && (Blink_li_an == false)&& (WarnBlink == false)) {     //Blinken ein
   
    if (millis () - Takt > 420){                           //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_re_an = false;                                 //Blinker rechts aus
      Blink_re_Status = false;                             //Ausgangsstatus Blinker rechts auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
      
//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

// Ansteuerung Blinker LINKS für 8x blinken 420 ms / 420 ms + Licht

if ((Mittelwert3 <= 1150) && (Umschaltsperre_li == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
    Pos_zeit_li = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
    Umschaltsperre_li = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
    } 
    
if (Umschaltsperre_li == true){                           
    Dauer_li = (millis () - Pos_zeit_li);                 //hier wird die Verweildauer rechts ausgewertet

      if ((Dauer_li <= 800) && (Mittelwert3 >= 1350)) {   //Verweildauer kleiner 800 UND Knüppel wieder in der Mitte -> Blinker ein
          Blink_li_an = true;                             //Blinker links an                         
         }
      if ((Dauer_li >= 1001)&& (Licht_li_Sperre == false)[COLOR=#b22222]&&(Licht_re_an == true)[/COLOR]) {  //Verweildauer größer 1011 -> Licht ein
         Licht_li_an == true;
         [COLOR=#b22222]analogWrite (Licht_li, PWM_Full)[/COLOR];
         Dauer_li = 0;                                      //Verweildauer löschen
         }
    
     if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)[COLOR=#b22222]&&(Licht_re_an == true)[/COLOR]) {  //Verweildauer größer 1001 UND Licht war an und Begrenzungsleuchten an-> Standlicht
         Licht_li_an == false;
         [COLOR=#b22222]analogWrite (Licht_li,PWM_Half_Front)[/COLOR];
         Dauer_li = 0;                                      //Verweildauer löschen
         }  
     if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)[COLOR=#b22222]&&(Licht_re_an == false)[/COLOR]) {  //Verweildauer größer 1001 UND Licht war an und Begrenzungsleuchten aus-> Licht aus
         analogWrite (Licht_li,PWM_aus);
         Dauer_li = 0;                                      //Verweildauer löschen
         }  
   }

if (Mittelwert3 >= 1350){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
          Umschaltsperre_li = false;  
          }

if ((Mittelwert3 >= 1350) && (Licht_li_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
          Licht_li_Sperre = true;  
          }
          
if ((Mittelwert3 >= 1350) && (Licht_li_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
          Licht_li_Sperre = false;  
          }
          
if ((Blink_li_an == true) && (Blink_re_an == false)&& (WarnBlink == false)) {     // Blinken ein
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_li_Status = !Blink_li_Status;                  //Ausgangsstatus invertieren
      i++;                                                 //Zähler 1 erhöhen  
     }
  }
    if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
      Blink_li_an = false;                                 //Blinker links aus
      Blink_li_Status = false;                               //Ausgangsstatus Blinker links auf LOW
      i = 0;                                               //Zähler zurücksetzen
    }
    
 //xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
 //  Warnblinker Logik
   
 if ((Blink_li_an == true) && (Blink_re_an == true) && (WarnBlink == false)) {  // Warnblinker ein wenn der andere Blinker schon blinkt
      WarnBlink = true;                                     //Warnblinker gesetzt
      Blink_li_an = false;                                  //Blinker links aus
      Blink_re_an = false;                                  //Blinker rechts aus
      Blink_li_Status = false;                              //LED erst mal aus wegen synchronisation
      Blink_re_Status = false;                              //LED erst mal aus wegen synchronisation
      i = 0;                                                //Zähler zurücksetzen     
      }
      
 if (WarnBlink == true) {
      if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
      Takt = millis ();                                    //
      Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
      Blink_li_Status = !Blink_li_Status;                      
      }
      }

if ((WarnBlink == true) && (Blink_re_Status == false) && (Blink_li_Status == false) && ((Blink_li_an == true) || (Blink_re_an == true))) {    
                                                         // wird nur abgeschaltet wenn LED aus (Pause)
      WarnBlink = false;
      Blink_li_an = false;                                //Blinker links aus
      Blink_re_an = false;                                //Blinker rechts aus
      Blink_li_Status = false;                            //LED aus
      Blink_re_Status = false;                            //LED aus
    }
    
    digitalWrite (Blink_li,Blink_li_Status); // Blinker links ein/aus
    digitalWrite (Blink_re,Blink_re_Status); // Blinker rechts ein/aus
     
     [COLOR=#b22222]//digitalWrite (Licht_li,Licht_li_an); // Licht links ein/aus[/COLOR]
    digitalWrite (Licht_re,Licht_re_an); // Licht rechts ein/aus

    
/*//   Serial.print ("Mittelwert ");
//Serial.println(Mittelwert);          // Anzeige des Mittelwertes 

Serial.print ("Knüppelzeit li ");
Serial.println(Dauer_li);          // Anzeige des Mittelwertes

Serial.print ("Knüppelzeit re ");
Serial.println(Dauer_re);          // Anzeige des Mittelwertes
  
Serial.print ("Rechts ");
Serial.println(Rechts);          // Anzeige des Mittelwertes
Serial.print ("Rechts an ");
Serial.println(Rechts_an);          // Anzeige des Mittelwertes
Serial.print ("Takt ");
Serial.println(Takt);          // Anzeige des Mittelwertes
/*/
}

Kannst Du mir bitte sagen, was ich verändern muss um die Schönheitsfehler zu beseitigen?
:winkerViele Grüße Carsten
 
Hallo Carsten,

auf Anhieb kann ich da nichts erkennen. Wo liegt denn der Nullwert vom Knüppel?
Am Ende des Programms liegt der Debug Teil, dort kann man über den Seriel Monitor in der Arduino IDE sich variablen und Werte anzeigen lassen. Baudrate ist 9600. Der Debug Teil ist auskommentiert, da kann st du auch noch andere (neue) Variablen einfügen.
 
Moin Carsten,

das Problem liegt in der starren Definition der Schwellenwerte.

Ich empfehle 2 Änderungen:

1. Im Setup schaltest du die IRQs ein und baust dann ein delay() ein, z. B. 500ms. Dies sorgt dafür dass die Interrrupts ca. 25 mal durchlaufen werden und somit nach dem delay der aktuelle Mittelwert den tatsächlichen Nullpunkt darstellt. Diesen Wert speicherst du dir ein einer Variable z. B. "MeasuredCenterValue" ab.

2. Die Schellenwerte definierst du dann statt 1450 "(MeasuredCenterValue - 50)", einen Schwellenwert von 1850 ersetzt du durch "(MeasuredCenterValue + 350)". Dies sorgt dafür dass die Schwellenwerte sich dynamisch mit dem tatsächlichen Mittelpunkt verschieben.

Es gibt mit eine weitere Optimierung, welche allerdings eine Einmessung benötigt. Durch die Einmessung (maximale Ausschläge in beide Richtungen) bekommst du zum Mittelwert auch die Endwerte. So kannst du Schwellenwerte auf Basis der Differenz zwischen Mittel- und Endwert definieren.

Noch ein Tipp: Du berechnest den Mittelwert aus 8 Werten. Dies bringt eine gewisse Trägheit mit sich. Meine bisherigen Erfahrungen mit meinen Fahrplatinen haben gezeigt dass 4 Werte zum Glätten durchaus ausreichen.
 
Hallo Peter,

da hast du recht mit den starren Werten. Ich weis aber nicht ob Carsten da so mal schnell hin bekommt. Einfacher ist es da schon die den Servoweg und die Nullstellung an der Funke einzustellen.
Das mit den 8 Werten kann ich so nicht bestätigen, bei 8x25ms kommt man auf 200ms. So schnell reagiert da keiner am Knüppel (außer vielleicht ein Ninja ;) )
 
Moin Bert,

die Trägheit der acht Werte kommt zum Tragen wenn man z. B. den EKMFA odus von Beier nachbaut.
 
Moin, moin...

Ich habe das Programm mal auf einen eingemessenen Mittelpunkt umgebaut.

Code:
// Pin 2: Schaltmodul mit Bremslicht und Rückfahrscheinwerfer und Rückfahrwarner
// Pin 3: Schaltmodul mit Blinker/Warnblinker und zwei unabhängigen Lichtkanälen
// für Arduino Nano

const byte PIN_RC = 2; // das ist INT 0 aber Pin 2 wo das Empfängersignal Rückfahrwarmer & Bremslicht eingelesen wird
					   // alles was im Interrupt läuft muss als volatile deklariert werden
					   //volatile int RcValue;  // Eingelesener Wert direkt aus dem RAM w.g. volatile)
volatile int ReceivedSpeedValues[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 =1500; // Mittelwert aus der Summe 
volatile int Zeiger =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange =0;
volatile long nMicros =0;
volatile long nDifference =0;

const byte PIN_RC3 = 3; // das ist INT 1 aber Pin 3 wo das Empfängersignal Blinker eingelesen wird
volatile int ReceivedSpeedValues3[8] = {1500, 1500, 1500, 1500, 1500, 1500, 1500, 1500}; // Array mit 8 Werten für die gemessenen Werte
volatile int Summe3 = 12000; // Summe aus dem Array 8x1500, als Anfangswert
volatile int Mittelwert3 =1500; // Mittelwert aus der Summe 
volatile int Zeiger3 =0; // Zeiger für das Array, fängt mit 0 an
volatile long LastSpeedChange3 =0;
volatile long nMicros3 =0;
volatile long nDifference3 =0;

//Lichtstärke Rücklichter
const byte PWM_Half_Heck = 50;
//Lichtstärke Standlicht
const byte PWM_Half_Front = 50;
//PWM Definition für volle Leistung
const byte PWM_Full = 255;
//PWM Definition für aus
const byte PWM_aus = 0;

// Für Rückfahrwarner und Bremslicht
const byte LED = 4;           // pin 4 - Rückfahr LED weiß
const byte LEDrt = 5;         // pin 5 - Bremslicht rot
const byte speakerPin = 6;    // pin 6  (PWM) - Lautsprecher

boolean Null = 0;             // Nullstellung wird erkannt
boolean vorher_Null = 0;      // Nullstellung vorher
int frequency  = 1300;        // 1300Hz für den Pieper
int duration = 400;           // Dauer des Tons
unsigned long zeit = 0;       // Systemzeit
unsigned long zeit1_alt =0;   // alte Systemzeit 1 Rücklicht
unsigned long zeit2_alt =0;   // alte Systemzeit 2 Bremslicht
bool RVS = false;             // Status Rückwärts

							  // Für den Blinker und Fahrlicht
const byte Blink_re=7;        // pin 7 - Blinker rechts
const byte Blink_li=8;        // pin 8 - Blinker links
const byte Licht_re=9;        // pin 9 - Licht rechts
const byte Licht_li=10;       // pin 10 - Links links
const byte Stand=11;           // pin 11 - Standlicht

unsigned long Dauer_re =0;    // Dauer wie lange Knüppel rechts war
unsigned long Pos_zeit_re =0; // Positionszeit rechts
unsigned long Dauer_li =0;    // Dauer wie lange Knüppel links war
unsigned long Pos_zeit_li =0; // Positionszeit links
unsigned long Takt =0;        // Hilfszeit für Blinktakt

bool Umschaltsperre_re = false;  // Knüppelposition wird abgefragt
bool Umschaltsperre_li = false;  // Knüppelposition wird abgefragt
bool Blink_re_an = false;        // Blinkfunktion rechts ein
bool Blink_li_an = false;        // Blinkfunktion links ein
bool Blink_re_Status = false;    // Blink LED rechts AN/AUS
bool Blink_li_Status = false;    // Blink LED rechts AN/AUS
byte i = 0;                      // Zähler für die Blinktakte
bool WarnBlink = false;          // Warnblinker
bool Licht_re_an = false;
bool Licht_li_an = false;
bool Licht_re_Sperre = false;     //Einschaltsperre Dauerlicht
bool Licht_li_Sperre = false;     //Einschaltsperre Dauerlicht

//	Die gemessenen Mittelstellungen
int	MeasuredCenterPin2		= 1500;
int	MeasuredCenterPin3		= 1500;

void setup() 
{ 
	pinMode (LED, OUTPUT);       // Rückfahrlicht
	pinMode (LEDrt, OUTPUT);     // Bremslicht LED
	pinMode (Blink_re, OUTPUT);  // Blinker rechts
	pinMode (Blink_li, OUTPUT);  // Blinker links
	pinMode (Licht_re, OUTPUT);  // Licht rechts
	pinMode (Licht_li, OUTPUT);  // Licht links
	pinMode (Stand, OUTPUT);
	pinMode(PIN_RC, INPUT);      // Eingang für Empfängersignal an Pin 2   
	pinMode(PIN_RC3, INPUT);     // Eingang für Empfängersignal an Pin 3  

	attachInterrupt( 0, SpeedPositionInterrupt, CHANGE); // 0=Interrupt 0,also Pin2 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 2 sich ändert
	attachInterrupt( 1, SpeedPositionInterrupt3, CHANGE); // 1=Interrupt 1,also Pin3 / NAME der Interruptroutine / springe zum Interrupt wenn der Wert an Pin 3 sich ändert

	//	Den Interrupts Zeit geben aktuelle Werte zu sammeln
	delay(500);
	//	Die aktuellen Werte als gemessene Mittelstellungen verwenden
	MeasuredCenterPin2	= Mittelwert;
	MeasuredCenterPin3	= Mittelwert3;

	Serial.begin(9600); // nur für debugging und Test
} 


void SpeedPositionInterrupt() //Interrupt fragt Pin 2 ab
{
	nMicros = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
	nDifference  = (nMicros - LastSpeedChange); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

	if ( (nDifference > 900 ) && ( nDifference < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
	{
		Summe -= ReceivedSpeedValues[Zeiger]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
		ReceivedSpeedValues[Zeiger] = nDifference; // Array mit 8 Werten für die gemessenen Wert 
		Summe    += nDifference; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
		Zeiger     = ( ( Zeiger + 1 ) & 0x07 );    //    Index erhoehen und ggf. von 8 auf 0 springen
		Mittelwert = ( Summe >> 3 );    //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
	}
	LastSpeedChange    = nMicros;
}

void SpeedPositionInterrupt3() //Interrupt fragt Pin 3 ab
{
	nMicros3 = micros();  // die aktuelle Prozessorzeit wird in der variablen nMicros abgespeichert, dann geht der Zugriff schneller
	nDifference3  = (nMicros3 - LastSpeedChange3); // hier wird geprüft wie lange der letzte Pegelwechsel her ist

	if ( (nDifference3 > 900 ) && ( nDifference3 < 2100)) // liegt die Zeitdifferenz zwischen 0,9 und 2,1 ms, so ist es ein HIGH Pegal
	{
		Summe3 -= ReceivedSpeedValues3[Zeiger3]; // Summe = Summe - ReceivedSpeedValues[Zeiger];// substrahiere letzte Messung aus dem Array
		ReceivedSpeedValues3[Zeiger3] = nDifference3; // Array mit 8 Werten für die gemessenen Wert 
		Summe3 += nDifference3; //Summe = Summe + ReceivedSpeedValues[Zeiger]; // addiere Wert zur Summe  
		Zeiger3   = ( ( Zeiger3 + 1 ) & 0x07 ); //  Index erhoehen und ggf. von 8 auf 0 springen
		Mittelwert3 = ( Summe3 >> 3 );  //der Befehl >>3 ist bit shift left um drei bit, das ist wie durch 8 teilen
	}
	LastSpeedChange3 = nMicros3;

}

void loop() 
{ 
	zeit = millis ();    // aktuelle Systemzeit in zeit1 schreiben

						 // Rückfahrlicht + Pieper

	if (Mittelwert < (MeasuredCenterPin2 - 50)) {      // Fahrzeug fährt rückwärts
		digitalWrite (LED,HIGH);                       // Rückfahrscheinwerfer ein
		RVS = true;                                    // Status Rückwärts
	}

	if (RVS == true && (zeit - zeit1_alt >=800)) {   // Status Rückwärts UND Zeitdifferenz ist größer 800 ms
		tone(speakerPin, frequency, duration);         // 400 ms Ton ausgeben
		zeit1_alt = zeit;                              // aktuelle Zeit in Zeit1_alt schreiben -> hierdurch wird der Intervall gemacht.
	}


	if (Mittelwert >(MeasuredCenterPin2 - 49)) {                          // Fahrzeug ist in Neutral oder fährt vorwärts
		digitalWrite (LED,LOW);                        // Rückfahrscheinwerfer aus
		RVS = false;                                   // Status Rückwärts
	}

	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX
	//
	// Bremslicht

	if ((Mittelwert >(MeasuredCenterPin2 - 50)) &&(Mittelwert <(MeasuredCenterPin2 + 50))) {     // war 1450 und 1550 Abfrage Nullstellung 
		Null = true;
	} 

	if (vorher_Null == false && Null == true)
	{                                              //vorher kein Null -> jetzt Null-> Bremslicht an
		digitalWrite (LEDrt,HIGH);                   //LED Bremslicht ein    
		zeit2_alt = millis ();                       //Zeit für Timer setzen
	}

	if (((zeit - zeit2_alt >= 3000) || Null == false)&&(Licht_re_an == true)) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, dann Bremslicht = Rücklicht
		analogWrite (LEDrt,PWM_Half_Heck);                       //LED Bremslicht = Rücklicht 
	}

	if (((zeit - zeit2_alt >= 3000) || Null == false)&&(Licht_re_an == false)) {  // wenn timer = 3000 ODER wieder FWD bzw RVS, dann Bremslicht aus
		digitalWrite (LEDrt,LOW);                       //LED Bremslicht = Rücklicht aus  
	}
	vorher_Null = Null;                                // alten Null Wert speichern
	Null = false;                                      // aktuellen Nullwert zurück setzen


													   //XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

													   // Ansteuerung Blinker RECHTS für 8x blinken 420 ms / 420 ms + Licht

	if ((Mittelwert3 >= (MeasuredCenterPin3 + 300)) && (Umschaltsperre_re == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
		Pos_zeit_re = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
		Umschaltsperre_re = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
	} 

	if (Umschaltsperre_re == true){                           // Umschaltsperre ausschalten wenn der Knüppel in Null ist
		Dauer_re = (millis () - Pos_zeit_re);                 //hier wird die Verweildauer rechts ausgewertet

		if ((Dauer_re <= 800) && (Mittelwert3 <= (MeasuredCenterPin3 + 150))) {   //Verweildauer kleiner 800 UND Knüppel wieder in Null -> Blinker ein
			Blink_re_an = true;                             //Blinker rechts an
		}
		if ((Dauer_re >= 1001)&& (Licht_re_Sperre == false)) { //Verweildauer größer 1001 -> Licht ein
			Licht_re_an = true;
			Dauer_re = 0;                                       //Verweildauer löschen
		}
		if (Licht_re_an == true){
			analogWrite (Licht_li,PWM_Half_Front);             //Standlicht an
			analogWrite (Stand,PWM_Half_Front);                //Standlicht an
			analogWrite (LEDrt,PWM_Half_Heck);                 //Rücklichter an
		}

		if ((Dauer_re >= 1001)&& (Licht_re_Sperre == true)) {  //Verweildauer größer 1001 UND Licht war an -> Licht aus
			Licht_re_an = false;
			Dauer_re = 0;                                       //Verweildauer löschen
		}  
		if (Licht_re_an == false){
			analogWrite (Licht_li,PWM_aus);              //Standlicht aus
			analogWrite (Stand,PWM_aus);                 //Standlicht aus
			analogWrite (LEDrt,PWM_aus);                 //Rücklichter aus       
		}
	}

	if (Mittelwert3 <= (MeasuredCenterPin3 + 150)){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
		Umschaltsperre_re = false;  
	}

	if ((Mittelwert3 <= (MeasuredCenterPin3 + 150)) && (Licht_re_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
		Licht_re_Sperre = true;  
	}

	if ((Mittelwert3 <= 1650) && (Licht_re_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
		Licht_re_Sperre = false;  
	}

	if ((Blink_re_an == true) && (Blink_li_an == false)&& (WarnBlink == false)) {     //Blinken ein

		if (millis () - Takt > 420){                           //Blinktatkt 420 ms ein / aus
			Takt = millis ();                                    //
			Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
			i++;                                                 //Zähler 1 erhöhen  
		}
	}
	if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
		Blink_re_an = false;                                 //Blinker rechts aus
		Blink_re_Status = false;                             //Ausgangsstatus Blinker rechts auf LOW
		i = 0;                                               //Zähler zurücksetzen
	}

	//XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX

	// Ansteuerung Blinker LINKS für 8x blinken 420 ms / 420 ms + Licht

	if ((Mittelwert3 <= (MeasuredCenterPin3 - 350)) && (Umschaltsperre_li == false)) { // Knüppelposition erreicht und Umschaltsperre ist frei 
		Pos_zeit_li = millis ();        // aktueller Zeitwert wird geschrieben -> Auswertung der Verweildauer Knüppel 
		Umschaltsperre_li = true;       // Umschaltsperre einschalten, Knüppel muss erst mal wieder nach Null
	} 

	if (Umschaltsperre_li == true){                           
		Dauer_li = (millis () - Pos_zeit_li);                 //hier wird die Verweildauer rechts ausgewertet

		if ((Dauer_li <= 800) && (Mittelwert3 >= (MeasuredCenterPin3 - 150))) {   //Verweildauer kleiner 800 UND Knüppel wieder in der Mitte -> Blinker ein
			Blink_li_an = true;                             //Blinker links an                         
		}
		if ((Dauer_li >= 1001)&& (Licht_li_Sperre == false)&&(Licht_re_an == true)) {  //Verweildauer größer 1011 -> Licht ein
			Licht_li_an == true;
			analogWrite (Licht_li, PWM_Full);
			Dauer_li = 0;                                      //Verweildauer löschen
		}

		if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)&&(Licht_re_an == true)) {  //Verweildauer größer 1001 UND Licht war an und Begrenzungsleuchten an-> Standlicht
			Licht_li_an == false;
			analogWrite (Licht_li,PWM_Half_Front);
			Dauer_li = 0;                                      //Verweildauer löschen
		}  
		if ((Dauer_li >= 1001)&& (Licht_li_Sperre == true)&&(Licht_re_an == false)) {  //Verweildauer größer 1001 UND Licht war an und Begrenzungsleuchten aus-> Licht aus
			analogWrite (Licht_li,PWM_aus);
			Dauer_li = 0;                                      //Verweildauer löschen
		}  
	}

	if (Mittelwert3 >= (MeasuredCenterPin3 - 150)){                                 //Knüppel in der Mitte -> Umschaltsperre löschen
		Umschaltsperre_li = false;  
	}

	if ((Mittelwert3 >= (MeasuredCenterPin3 - 150)) && (Licht_li_an == true)) {     //Knüppel in der Mitte + Licht AN -> Lichtsperre einschalten
		Licht_li_Sperre = true;  
	}

	if ((Mittelwert3 >= (MeasuredCenterPin3 - 150)) && (Licht_li_an == false)) {     //Knüppel in der Mitte + Licht AUS -> Lichtsperre löschen
		Licht_li_Sperre = false;  
	}

	if ((Blink_li_an == true) && (Blink_re_an == false)&& (WarnBlink == false)) {     // Blinken ein
		if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
			Takt = millis ();                                    //
			Blink_li_Status = !Blink_li_Status;                  //Ausgangsstatus invertieren
			i++;                                                 //Zähler 1 erhöhen  
		}
	}
	if (i > 15) {                                          //der Blinker blinkt 8 mal, aber der Zähler zählt ja auch die Pause mit (8 Blink + 7 Pause = 15)
		Blink_li_an = false;                                 //Blinker links aus
		Blink_li_Status = false;                               //Ausgangsstatus Blinker links auf LOW
		i = 0;                                               //Zähler zurücksetzen
	}

	//xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
	//  Warnblinker Logik

	if ((Blink_li_an == true) && (Blink_re_an == true) && (WarnBlink == false)) {  // Warnblinker ein wenn der andere Blinker schon blinkt
		WarnBlink = true;                                     //Warnblinker gesetzt
		Blink_li_an = false;                                  //Blinker links aus
		Blink_re_an = false;                                  //Blinker rechts aus
		Blink_li_Status = false;                              //LED erst mal aus wegen synchronisation
		Blink_re_Status = false;                              //LED erst mal aus wegen synchronisation
		i = 0;                                                //Zähler zurücksetzen     
	}

	if (WarnBlink == true) {
		if (millis () - Takt > 420){                         //Blinktatkt 420 ms ein / aus
			Takt = millis ();                                    //
			Blink_re_Status = !Blink_re_Status;                  //Ausgangsstatus invertieren
			Blink_li_Status = !Blink_li_Status;                      
		}
	}

	if ((WarnBlink == true) && (Blink_re_Status == false) && (Blink_li_Status == false) && ((Blink_li_an == true) || (Blink_re_an == true))) {    
		// wird nur abgeschaltet wenn LED aus (Pause)
		WarnBlink = false;
		Blink_li_an = false;                                //Blinker links aus
		Blink_re_an = false;                                //Blinker rechts aus
		Blink_li_Status = false;                            //LED aus
		Blink_re_Status = false;                            //LED aus
	}

	digitalWrite (Blink_li,Blink_li_Status); // Blinker links ein/aus
	digitalWrite (Blink_re,Blink_re_Status); // Blinker rechts ein/aus

											 //digitalWrite (Licht_li,Licht_li_an); // Licht links ein/aus
	digitalWrite (Licht_re,Licht_re_an); // Licht rechts ein/aus


										 /*//   Serial.print ("Mittelwert ");
										 //Serial.println(Mittelwert);          // Anzeige des Mittelwertes 

										 Serial.print ("Knüppelzeit li ");
										 Serial.println(Dauer_li);          // Anzeige des Mittelwertes

										 Serial.print ("Knüppelzeit re ");
										 Serial.println(Dauer_re);          // Anzeige des Mittelwertes

										 Serial.print ("Rechts ");
										 Serial.println(Rechts);          // Anzeige des Mittelwertes
										 Serial.print ("Rechts an ");
										 Serial.println(Rechts_an);          // Anzeige des Mittelwertes
										 Serial.print ("Takt ");
										 Serial.println(Takt);          // Anzeige des Mittelwertes
										 /*/
	delay(20);
}
 

Servonaut
Zurück
Oben Unten