Blinker für RC-Auto

Schönen Abend zusammen,

ich habe vor, für ein RC-Fahrzeug einen Blinker zu bauen.
Dieser wird über drei Kanäle (Taster) gesteuert, diese sollen folgendes auslösen:

  1. Nach Links blinken
  2. Nach Rechts blinken
  3. Warnblinker
    Dann hab ich mir mal überlegt wie ich das am besten lösen kann, ein bisschen im Internet nach ähnlichen Themen gesucht und dann das mal soweit versucht zu programmieren.
const int LED_L = 8;
const int LED_R = 6;
const int schalter_L = 4; 
const int schalter_R = 3;
const int schalter_W = 2;


// Blink-
int blink_LED_L_state = LOW;
int blink_LED_R_state = LOW;

long blink_previousMillis_L = 0;
long blink_previousMillis_R = 0;
//-Blink 

long interval = 1000;


//Schalter-
int schalter_reading_L;
int schalter_reading_R;
int schalter_reading_W;

int schalter_previous_L;
int schalter_previous_R;
int schalter_previous_W;

long schalter_L_time = 0;
long schalter_R_time = 0;
long schalter_W_time = 0;

long debounce = 200;
//-Schalter

int schalter_L_zustand;
int schalter_R_zustand;

void setup(){

  pinMode(LED_L, OUTPUT);
  pinMode(LED_R, OUTPUT);
  pinMode(schalter_L, INPUT);
  pinMode(schalter_R, INPUT);
  pinMode(schalter_W, INPUT);

}

void links_schalter(){

  schalter_reading_L = digitalRead(schalter_L);

  if (schalter_reading_L == HIGH && schalter_previous_L == LOW && millis() - schalter_L_time > debounce)
  {

    schalter_L_zustand = 1;

    schalter_L_time = millis();

  }
  else 
  {
    schalter_L_zustand = 0;

  }

  schalter_previous_L = schalter_reading_L;

}


void rechts_schalter(){

  schalter_reading_R = digitalRead(schalter_R);

  if (schalter_reading_R == HIGH && schalter_previous_R == LOW && millis() - schalter_R_time > debounce)
  {
   
    schalter_R_zustand = 1;
   
    schalter_R_time = millis();

  }
  else 
  {
    schalter_R_zustand = 0;

  }

  schalter_previous_R = schalter_reading_R;

}


void links_blinken(){

  unsigned long blink_currentMillis_L = millis();

  if(blink_currentMillis_L - blink_previousMillis_L > interval) {

    blink_previousMillis_L = blink_currentMillis_L;   


    if (blink_LED_L_state == LOW)
      blink_LED_L_state = HIGH;
    else
      blink_LED_L_state = LOW;


    digitalWrite(LED_L, blink_LED_L_state);
  }

}

void rechts_blinken(){

  unsigned long blink_currentMillis_R = millis();

  if(blink_currentMillis_R - blink_previousMillis_R > interval) {

    blink_previousMillis_R = blink_currentMillis_R;   


    if (blink_LED_R_state == LOW)
      blink_LED_R_state = HIGH;
    else
      blink_LED_R_state = LOW;


    digitalWrite(LED_R, blink_LED_R_state);
  }

}

void loop(){


  links_schalter();
  rechts_schalter();

   
 while (schalter_R_zustand == 1 && schalter_L_zustand == 0)
  {
    rechts_blinken();
  } 
  
 while (schalter_L_zustand == 0 && schalter_R_zustand == 1)
  {
     links_blinken();
  } 
 
  }

Nur passiert nicht das, das ich mir erwünscht habe :frowning:
Folgende Situation:
Zu Beginn garnichts, alle LEDs aus.
Beim betätigen von pin 3 (Schalter Rechts) beginnt LED 6 (Blinker Rechts) zu blinken. Beenden lässt sich dies über ein erneutes betätigen des pin 3 nicht.
Beim Versuch, das ganze für den Linken Blinker zu erreichen, passiert nichts.
Für den Warnblinker hab ich noch nichts gemacht, dieser existiert derzeit nur als Eingang. Das kommt dann wenn Links und Rechts blinken funktionieren.

Ich vermute, dass das Problem in der loop-Funktion bei der while-Schleife liegt. Ist aber nur eine Vermutung, und alle Versuche meinerseits haben nicht geholfen.
Es wäre echt super, wenn mir jemand helfen könnte.

Viele Grüße,
Simon

Hast Du Pulldownwiderstände an den Tasteneingängen?
Grüße Uwe

Hallo!
Das hier funktioniert recht gut,
http://www.rockcrawler.de/index.php?page=Thread&threadID=22718
Kannst sicher für deine Zwecke adaptieren.

mfg Martin

simon97:
Beim betätigen von pin 3 (Schalter Rechts) beginnt LED 6 (Blinker Rechts) zu blinken. Beenden lässt sich dies über ein erneutes betätigen des pin 3 nicht.

Als erstes mal müßtest Du Dir über die genaue Schaltlogik im Klaren werden.
Oben schreibst Du einerseits von RC-Kanälen, über die Steuerinformationen gesendet werden
Dann schreibst Du von Tastern, die beim Betätigen mal ein- und mal ausschalten sollen

Meine Kenntnisse über RC-Fernsteuerungen sagen mir: Eine Funktion wird geschaltet, so lange ein Steuersignal gesendet wird, das besagt, die Funktion soll geschaltet sein. Wenn Du dieses RC-Verhalten mit einer Taster-Logik nachbilden wolltest, wäre die Logik (bei einer RC-Fernsteuerung wie ich sie kenne):

  • RC-Funktion geschaltet / Taster ist runtergedrückt ==> zugehöriger Blinker blinkt
  • RC-Funktion nicht geschaltet /Taster ist losgelassen ==> Blinker ist aus
    Für diese Art Steuerung wird ein RC-Kanal für jede Steuerfunktion benötigt.
    Bzw. ein RC-Kanal für insgesamt zwei Steuerfunktionen, von denen aber nur eine zur Zeit gesetzt sein kann (links-rechts-aus).

Daneben gibt es noch "Multiswitch" Schaltlogik, bei der ein Kanal in verschiedene Schaltfunktionen aufgeteilt wird und im Endeffekt ist es so, dass es für jede Schaltfunktion einen verschiedenen Schalter zum Ein- und Ausschalten gibt:

  • RC-Funktion für EIN geschaltet / Taster EIN wurde gedrückt ==> zugehöriger Blinker blinkt
  • RC-Funktion für AUS geschaltet / Taster AUS wurde gedrückt ==> Blinker ist aus
    Mit einem Multischwitch, können dann z.B. fünf verschiedene Funktionen pro RC-Kanal ein/aus geschaltet werden, das entspricht fünf Einschaltern und fünf Ausschaltern, wenn man es mit Schaltern nachbilden möchte: Je ein Einschalter und ein Ausschalter pro Funktion.

Und Du möchtest stattdessen diese Logik haben, die nicht so wirklich RC-kompatibel ist:

  • RC-Funktion wird einmal geschaltet / Taster wird einmal runtergedrückt ==> zugehöriger Blinker blinkt
  • RC-Funktion nicht geschaltet / Taster ist losgelassen ==> bereitmachen für nächstes Kommando
  • RC-Funktion wird nochmal geschaltet / Taster wird nochmal runtergedrückt ==> Blinker ist aus
    ???

@uwefed: Ja, hab ich. Ich hab auch die Schalter mit einem einfachen sketch getestet, da gab's kein Problem. Ich werde aber nochmal prüfen, ob alles passt.
@Wasjetzt: Danke, ich les mir das mal durch und schau wie viel ich davon verwenden kann!
@jurs: Ich habe immer von einem Taster geschrieben, da die Schaltung momentan mit solch einem zum testen aufgebaut ist. Später, wenn alles funktioniert, soll das ganze in dem RC-Fahrzeug über einen Multiswitch gesteuert werden. Dieser gibt wie ein Taster nur bei betätigung des entsprechenden Schalters auf der Fernbedienung ein Signal für den jeweilien Kanal aus.
Wenn der Blinker aus ist und gedrückt wird soll er angehen bis wieder gedrückt wird, dann geht er wieder aus.

Ich hoffe ich konnte ein bisschen Klarheit schaffen.

Vielen Dank,
Simon

simon97:
Später, wenn alles funktioniert, soll das ganze in dem RC-Fahrzeug über einen Multiswitch gesteuert werden. Dieser gibt wie ein Taster nur bei betätigung des entsprechenden Schalters auf der Fernbedienung ein Signal für den jeweilien Kanal aus.
Wenn der Blinker aus ist und gedrückt wird soll er angehen bis wieder gedrückt wird, dann geht er wieder aus.

OK, es kann jetzt sein, dass ich da etwas verwechselt habe, was für ein Signal Du später auswerten möchtest. Ich war davon ausgegangen, Du wolltest mit dem Arduino direkt am RC-Empfänger die Impulse auswerten und danach schalten. Offenbar möchtest Du aber tatsächlich zwischen RC-Empfänger und Arduino noch einen Multiswitch-Decoder dazwischenstecken, der Dir ein bereits decodiertes Signal liefert.

Ich finde es immer schön, wenn ein Programm nach dem EVA-Prinzip strukturiert wird:

  • Eingabe
  • Verarbeitung
  • Ausgabe

Da bei diesem Programm nicht viel zu tun ist, habe ich den Schritt "Verarbeitung" hier mal der "Eingabe" mit zugeschlagen.

Beispiel-Code (ungetestet) anbei.

// Blinker Demo by 'jurs' for German Arduino Forum
#define INPUT_TYPE INPUT_PULLUP  // INPUT oder INPUT_PULLUP
#define BLINKTAKT 500   // in Millisekunden
#define ENTPRELLZEIT 5  // in Millisekunden
byte tasteLinks=2;  // Pins für zwei Taster
byte tasteRechts=3;
byte blinkerLinks=12; // Pins für zwei Blink-LEDs
byte blinkerRechts=13;

boolean linksBlinken=false; // Blinker links gesetzt
boolean rechtsBlinken=false; // Blinker rechts gesetzt

void blinkEingabe()
{
  static unsigned long lastMillis=0;
  static boolean altTasteL=false;
  static boolean altTasteR=false;
  if (millis()-lastMillis<ENTPRELLZEIT) return;
  lastMillis=millis();
  boolean neuTasteL=digitalRead(tasteLinks);
  boolean neuTasteR=digitalRead(tasteRechts);
  if (INPUT_TYPE==INPUT_PULLUP) // vertauschte Tastenlogik bei PullUp
  {
    neuTasteL=!neuTasteL;
    neuTasteR=!neuTasteR;
  }
  if (neuTasteL==HIGH && altTasteL==LOW) linksBlinken=!linksBlinken;
  if (neuTasteR==HIGH && altTasteR==LOW) rechtsBlinken=!rechtsBlinken;
  altTasteL=neuTasteL;
  altTasteR=neuTasteR;
}

void blinkAusgabe()
{
  static unsigned long lastMillis=0;
  static boolean onTakt=false;
  static unsigned long diffMillis=0;
  unsigned long nowMillis=millis();
  diffMillis+=nowMillis-lastMillis;
  if (diffMillis>=BLINKTAKT)
  {
   diffMillis=0;
   onTakt=!onTakt;
   if (onTakt && linksBlinken) digitalWrite(blinkerLinks,HIGH);
   else digitalWrite(blinkerLinks,LOW);
   if (onTakt && rechtsBlinken) digitalWrite(blinkerRechts,HIGH);
   else digitalWrite(blinkerRechts,LOW);

   Serial.print(digitalRead(blinkerRechts));
   Serial.print(digitalRead(blinkerLinks));
   Serial.println();
  }
  lastMillis=nowMillis;
}


void setup() {
  Serial.begin(9600);
  pinMode(tasteLinks,INPUT_TYPE);
  pinMode(tasteRechts,INPUT_TYPE);
  pinMode(blinkerLinks,OUTPUT);
  pinMode(blinkerRechts,OUTPUT);
}

void loop() 
{
  blinkEingabe();
  blinkAusgabe();
}

Je nachdem, ob Du Deine Taster mit PullDown-Widerständen angeschlossen hast oder die internen PullUps des Atmega an den Tastern verwenden möchtest, kannst Du den INPUT_TYPE als entweder "INPUT" oder "INPUT_PULLUP" definieren, abhängig von Deiner Schaltung.

Beide Blinker werden übrigens unabhängig voneinander geschaltet, so dass sich Warnblinken schalten läßt, indem man sowohl den linken als auch den rechten Blinker einschaltet. Also diese Schaltlogik entspricht nicht der Straßenverkehrszulassungsordnung.

Die "Serial" Befehle habe ich übrigens nur zum Debuggen für die Programmentwicklung drin, um mir hier keine Taster und LEDs tatsächlich aufbauen zu müssen, die "Serial" Befehle kannst und solltest Du natürlich für das engültige Programm rauslöschen.