Fenstersteuerung im Auto mit Arduino Nano verwirklichen

Hallo Gemeinde,

mir schwebt folgendes vor:

Ich möchte in mein Auto die Automatische Fenster auf/zu Funktion mittels Arduino verwirklichen.
Die Schaltung an den Fenstermotoren ist denkbar einfach und bereits getestet.
Arduino Nano ins Auto verpflanzen, Spannungsregler auf 5V davor und 5V Relais (2er Platine) dran.
Da ich das KeyFob Signal (öffnen/Schliessen) nicht auslesen kann, wollte ich es über die Anzahl der Öffnungs/Schliessimpulse am Door Lock Actuator versuchen.

Drücke ich Tür auf, zähler 1, nochmal innerhalb 2 sek, Zähler 2, nochmal innerhalb 2Sek, Zähler 3 und Relais impuls ein, für Fenster auf, Zähler = 0
Verstreichen 5 Sek während des Hochzählens, Zähler = 0.
Dasselbe mit Tür zu: 1 x Drücken Zähler 1, innerhalb 2Sek drücken, Zähler 2, innerhalb 2Sek drücken, Zähler 3, Relais ein, Fenster zu, Zähler =0

Ich habe es nun schon mit Delay und Millis versucht aber bisher sind die Ergebnisse noch zu ungenau, bzw. bekomme ich den TimeOut nicht vernünftig hin. Er zählt und zählt.

Wie behandele ich die 12V Impulse? Setze ich die auch per Regler auf 5V runter?

Wie setze ich am TimeOut und Countreset an?

PS: Code ist noch die Breadboard Variante mit Taster und LED

Gruß

Karsten

const byte LED = 6;
const byte Button = 7;
const byte LED2 = 8;

byte ButtonState;
byte lastState = LOW;
byte count = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  pinMode(LED2, OUTPUT);
  pinMode(Button, INPUT);
}

void loop() {
  ButtonState = digitalRead(Button);

  if(ButtonState && ButtonState != lastState)  // button latch, no debounce needed.
  {
    if(count < 3) // This will check to see if the count is within a range of 0 - 3, and anything over that, it will reset count back to 0.
      count += 1; // same as count = count + 1;
    else
      count = 0;
     
    digitalWrite(LED, HIGH);
    delay(200);
    digitalWrite(LED, LOW);
    Serial.println(count);
  }
 // if (count = 3)
 // {
    //digitalWrite(LED2, HIGH);
    //delay(5000);
    //digitalWrite(LED2, LOW);
    //count = 0;
 // }
 // else
  lastState = ButtonState;
}

Taster-Test-LED-Counter.ino (758 Bytes)

Bitte den Sketch hier im Forum in Code-Tags posten.

Verwende dazu die Schaltfläche </> oben links im Editorfenster.
Das kannst du auch nachträglich machen.
Dazu den Sketch markieren und die Schaltfläche klicken.

Damit wird dieser für alle besser lesbar.

Moin,

nachdem die Resonanz eher nüchtern ausfiel, habe ich mit viel probieren (das ist ja das schöne am Arduino) eine Version erstellt, welche mit TimeOut und Wechselschutz funktioniert.
Das 4. Relais an der 4 Relais Platine werde ich dann noch gegen Zündung am Auto legen, das der Arduino bei Fahrbetrieb NICHT mitläuft.

Hier für alle die es Interessiert mal der Code:

// Global Open/Close - Written by LaForge from www.dr-Mustang.com

const byte LED = 6;
const byte UPREL = 8;
const byte LED3 = 9;
const byte DWNREL = 11;
const byte DACCREL = 12;
const int Button = 7;
const int Button2 = 10;

byte ButtonState;
byte ButtonState2;
byte lastState = LOW;
byte lastState2 = LOW;
byte count = 0;
byte count2 = 0;

unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 2000;    // Interval zwischen zwei Änderungen

void setup() {
  Serial.begin(9600);
  pinMode(LED, OUTPUT);
  pinMode(UPREL, OUTPUT);
  pinMode(LED3, OUTPUT);
  pinMode(DWNREL, OUTPUT);
  pinMode(DACCREL, OUTPUT);
  pinMode(Button, INPUT);
  pinMode(Button2, INPUT);
}

void loop() {
  
  ButtonState = digitalRead(Button);
     
  if(ButtonState && ButtonState != lastState)  // button latch, no debounce needed.
  {
    if(count < 3) // This will check to see if the count is within a range of 0 - 3, and anything over that, it will reset count back to 0.
      count += 1; // same as count = count + 1;
    else
      count = 0;
      count2 = 0;    // Den Input 2 auf 0 setzen um den Zähler zu löschen! Verhindert Zählspeicher und versehentliches Auslösen!
           
    digitalWrite(LED, HIGH);
    delay(200);
    digitalWrite(LED, LOW);
    Serial.println(count);
  }
  lastState = ButtonState;

  if(count == 3){
    digitalWrite(UPREL, HIGH);
    digitalWrite(DACCREL, HIGH);
    delay(5000);
    digitalWrite(UPREL, LOW);
    digitalWrite(DACCREL, LOW);
    count = 0;
  }

  ButtonState2 = digitalRead(Button2);

  if(ButtonState2 && ButtonState2 != lastState2)  // button2 latch, no debounce needed.
  {
    if(count2 < 2) // This will check to see if the count is within a range of 0 - 255, and anything over that, it will reset count back to 0.
      count2 += 1; // same as count = count + 1;
    else
      count2 = 0;
      count = 0;    // Den Input 1 auf 0 setzen um Zähler zu löschen!
     
    digitalWrite(LED3, HIGH);
    delay(200);
    digitalWrite(LED3, LOW);
    Serial.println(count2);
  }
  lastState2 = ButtonState2;

  if(count2 == 2){
    digitalWrite(DWNREL, HIGH);
    digitalWrite(DACCREL, HIGH);
    delay(5000);
    digitalWrite(DWNREL, LOW);
    digitalWrite(DACCREL, LOW);
    count2 = 0;
  }
 
// Code der immer läuft kommt ÜBER die MILLIS Abfrage, dann klappt der TimeOut
    
    if (millis() - previousMillis > interval) {
        previousMillis = millis();   // aktuelle Zeit abspeichern
        count = 0;
        count2 = 0;
        }
}

Jetzt warte ich noch auf meinen China Arduino Nano (2,47€) und löte das mit Dioden und Spannungswandlern ins Auto.

Gruß

Karsten

So,

das Projekt ist fertig, der Arduino NANO im Auto verpflanzt.
Die Fenster lassen sich problemlos per Fernbedienung steuern.

Gruß

Karsten

Die mangelnde Resonanz liegt wohl an Deiner mangelhaften (um nicht zu sagen unverständlichen) Beschreibung.

Was für Regler sollen das denn sein, mit denen Du die 12V Signale auf 5V umsetzst? Normalerweise nimmt man dafür einfache Spannungsteiler.

Und die Beschreibung der Anzahl Drücke (Tastendrücke?), was hat die mit den Impulsen der Bordelektronik zu tun? Eine Taster-Abfrage ohne Entprellen liefert nur Murks.

Aber wenn jetzt alles läuft, dann hat sich Deine Frage wohl auch so schon erledigt.

@DR.Dittrich:

so habe ich das ggf. nicht gesehen, daher nur zum abschliessenden Verständnis die Erklärung der Absicht:

Ja, einfache Spannungsregler wurden für die 12V auf 5V Geschichte verwendet.

Die Anzahl der Tastandrücke rührt aus folgenden Vorgaben:

Viele amerikanische Autoe öffnen bei 1 x Klick nur die Fahrertür. Um das Fahrzeug komplett zu öffnen benötige ich 2x Klick.
Der Actuator im Auto reagiert bei JEDEM Klick mit einem 12V Impuls. Dieser ist mein Zählimpuls!
2x Klicken muss ich um das Auto komplett zu öffnen, daher 3x klick für Fenster auf. Dann gehen beim Öffnen die Fenster NICHT auf, wenn ich es NICHT will.

Wenn ich nun das Auto schliesse, reicht 1 x klick. Um den Alarm scharf zu schalten benötige ich 2 x klick und das Fahrzeug hupt kurz auf (auch eine amerikanische Besonderheit)
Damit es nun nicht ewig umherhupt, habe ich die Schliessimpulse auf 2x klick festgelegt.
Ich schliesse mein Auto schnell (2x schnell klick) und die Fenster gehen zu.

Als Deprellwert war der Delay 200 in der Routine drin, den habe ich im finalen Code auf 30 runter gesetzt da das Ergebnis vorher unsauber war.

Da setze ich nun meine Frage an die Experten an:

Manchmal ist die Routine trotz allem nicht sauber (ich muss öfter klicken um die Reaktion auszulösen).
Woran kann das ggf. liegen?

Ich habe den FINALEN CODE mal angehängt.

Danke und Gruß

Karsten

// Global Open/Close V1.3 - Written by LaForge from www.dr-Mustang.com
// Version to give away

const byte UPREL = 8;
const byte DWNREL = 11;
const byte DACCREL = 12;
const int Button = 7;
const int Button2 = 10;

byte ButtonState;
byte ButtonState2;
byte lastState = LOW;
byte lastState2 = LOW;
byte count = 0;
byte count2 = 0;

unsigned long previousMillis = 0; // speichert wie viele Sekunden seit derletzten Änderung vergangen sind
unsigned long interval = 2000;    // Interval zwischen zwei Änderungen

void setup() {
  pinMode(UPREL, OUTPUT);
  pinMode(DWNREL, OUTPUT);
  pinMode(DACCREL, OUTPUT);
  pinMode(Button, INPUT);
  pinMode(Button2, INPUT);
  digitalWrite(DACCREL, HIGH);
  digitalWrite(UPREL, HIGH);
  digitalWrite(DWNREL, HIGH);
}

void loop() {
  
  ButtonState = digitalRead(Button);
     
  if(ButtonState && ButtonState != lastState)  // button latch, no debounce needed.
  {
    if(count < 3) // Checkt count bis 3, dann zurück auf 0.
      count += 1; // selbe wie count = count + 1;
    else
      count = 0;
      count2 = 0;    // Den Input 2 auf 0 setzen um den Zähler zu löschen! Verhindert Zählspeicher und versehentliches Auslösen!
           
    delay(30); //Wert zum Deprellen
  }
  lastState = ButtonState;

  if(count == 3){
    digitalWrite(UPREL, LOW);
    digitalWrite(DACCREL, LOW);
    delay(5000);
    digitalWrite(UPREL, HIGH);
    digitalWrite(DACCREL, HIGH);
    count = 0;
  }

  ButtonState2 = digitalRead(Button2);

  if(ButtonState2 && ButtonState2 != lastState2)  // button2 latch, no debounce needed.
  {
    if(count2 < 2) // Checkt Count2 bis Wert 2, dann zurück auf 0.
      count2 += 1; // selbe wie count2 = count2 + 1;
    else
      count2 = 0;
      count = 0;    // Den Input 1 auf 0 setzen um Zähler zu löschen!
     
    delay(30); //Deprellen
  }
  lastState2 = ButtonState2;

  if(count2 == 2){
    digitalWrite(DWNREL, LOW);
    digitalWrite(DACCREL, LOW);
    delay(5000);
    digitalWrite(DWNREL, HIGH);
    digitalWrite(DACCREL, HIGH);
    count2 = 0;
  }
 
// Code der immer läuft kommt ÜBER die MILLIS Abfrage, dann klappt der TimeOut
    
    if (millis() - previousMillis > interval) {
        previousMillis = millis();   // aktuelle Zeit abspeichern
        count = 0;
        count2 = 0;
        }
}

Ich vermute mal mehrere Anfängerfehler in Deinem Code.

Zum Entrprellen findest Du schon in der IDE Beispiele, wie man es richtig macht. Ein delay() sollte im fertigen Programm normalerweise nicht mehr vorkommen.

Und dann deuten Deine Einrückungen an, daß mehrere Statements zu einem if oder else gehören sollen. Das versteht der Compiler aber nur, wenn diese zusammengehörenden Statements in geschweifte Klammern eingeschlossen sind.

Wenn Du schon bei so einfachen Vorgängen schlechten oder fehlerhaften Code schreibst, brauchst Du Dich nicht zu wundern, wenn nachher irgendwas nicht so funktioniert, wie es soll.

laforge-1701e:
Manchmal ist die Routine trotz allem nicht sauber (ich muss öfter klicken um die Reaktion auszulösen).
Woran kann das ggf. liegen?

    delay(5000);
    delay(5000);

@Dr.Dittrich:

Nun wo wir alle wissen, das Du wohl zigfach besseren Code als ich schreiben kannst, wäre es schön einen fachlichen Kommentar zu erhalten. Ich war auch verwundert, wieviele Klammern der Compiler an manchen Stellen möchte.
Alles in allem funktioniert aber alles wie es soll, d.h. zu jedem Statement gibt es laufenden Code.
Geprüft wurde das alles mit LEDs und Serial Monitor in der Rohphase.

Die Lösung einen kurzen (10 oder 30er) Delay zum Entprellen zu nehmen kommt im Netz sehr oft vor, so dass es für mich das Naheliegendste war.
Ich werde mich dahingehend belesen, da ich ja noch weitere Projekte mit Arduino und Auto Komponenten plane. Da ist Hilfe zum Erstellen von fachlich besserem und/oder übersichtlichem Code immer Willkommen.

@ Whandall:

The Arduino should work as an intelligent relay. Nothing more. So it has to hold a function about 5 seconds. NOTHING MORE!!! So a delay seems to be the best way to wait until this function is done.
I know there are better ways to solve this, but it has to do no more as wait 5 seconds.

Best regards to all of you.

Karsten

Meine Muttersprache ist Deutsch, aber ich kann auch Englisch recht flüssig.

Wenn du delays in deinen Programmen verwendest, kannst du keine wirklich reaktive Tastenauswertung garantieren
und deshalb darf dich das Folgende nicht wundern:

Manchmal ist die Routine trotz allem nicht sauber (ich muss öfter klicken um die Reaktion auszulösen).

Ein "intelligentes" Relay, das 5 Sekunden nicht auf an dem Gerät angebrachte Tasten reagiert,
verdient den Namen nicht.

laforge-1701e:
Nun wo wir alle wissen, das Du wohl zigfach besseren Code als ich schreiben kannst, wäre es schön einen fachlichen Kommentar zu erhalten.

Was findest Du an meinem Kommentar unfachlich?