Fernebdienung Taster Druck Simulation ohne Delays

Hey leute,
vlt könnt ihr mir ja helfen

Ich habe ein Unterprogramm geschrieben und versucht über den blinkwithout_delay Beispiel eine Zeitverzögerung zwischen den Pegelwechsel zu erreichen, da die Delays ja den Ganzen Arduino anhalten. Das Unterprogramm soll an den Tasterkontakten einer Fernbedienung das Betättigen per Hand nachahmen.

Also zur Zusammenfassung Arduino kriegt einen Befehl (inform eines Hexcodes) und dann soll das rummdrücken auf der Fernbedienung simuliert werden um damit die Rollos zu steuern.
(Fernbedienung auslösen nicht möglich aufgrund von Rolling codes)

Ich hoffe ihr könnt mir helfen.

Mit freundlichen Grüßen

int Channel_Up = 25;
int Channel_Zero = 12;//27
int Channel_Down = 29;
int Rollo_Up = 31;
int Rollo_Stop = 33;
int Rollo_Down = 35;

unsigned long previousMillis = 0; 
const long interval = 300; 



void Rollos() {

        
        /********************Rollo Wohn1**************************/
        if(Alexa_lesen == 0x0F)
        {
          digitalWrite(Channel_Zero, HIGH);   //HIGH     
                unsigned long currentMillis = millis();                               //Zeitverzögerung
                if (currentMillis - previousMillis >= interval)
                {
                  previousMillis = currentMillis;
                  digitalWrite(Channel_Zero, LOW);    //LOW
                  Serial.println("Zero LOW");
                  
                 }
              
          digitalWrite(Channel_Up, HIGH);
                unsigned long currentMillis2 = millis();                              //Zeitverzögerung
                if (currentMillis2 - previousMillis >= interval)
                {
                  digitalWrite(Channel_Up, LOW);
                  previousMillis = currentMillis2;
                 }

          digitalWrite(Rollo_Up, HIGH);
                unsigned long currentMillis3 = millis();                              //Zeitverzögerung
                if (currentMillis3 - previousMillis >= interval)
                {
                  digitalWrite(Rollo_Up, LOW);
                  previousMillis = currentMillis3;
                 }
          
        }
        if(Alexa_lesen == 0x10)
        {
            digitalWrite(Channel_Zero, HIGH);
                unsigned long currentMillis4 = millis();                               //Zeitverzögerung
                if (currentMillis4 - previousMillis >= interval)
                {
                  previousMillis = currentMillis4;
                  digitalWrite(Channel_Zero, LOW);
                 }

            digitalWrite(Channel_Up, HIGH);
                unsigned long currentMillis5 = millis();                              //Zeitverzögerung
                if (currentMillis5 - previousMillis >= interval)
                {
                  digitalWrite(Channel_Up, LOW);
                  previousMillis = currentMillis5;
                }   

          digitalWrite(Rollo_Down, HIGH);
                unsigned long currentMillis6 = millis();                              //Zeitverzögerung
                if (currentMillis6 - previousMillis >= interval)
                {
                  digitalWrite(Rollo_Down, LOW);
                  previousMillis = currentMillis6;
                 }
          
        }
        if(Alexa_lesen == 0x1B)
        {
          digitalWrite(Channel_Zero, HIGH);
                unsigned long currentMillis7 = millis();                               //Zeitverzögerung
                if (currentMillis7 - previousMillis >= interval)
                {
                  previousMillis = currentMillis7;
                  digitalWrite(Channel_Zero, LOW);
                 }    

          digitalWrite(Channel_Up, HIGH);
                unsigned long currentMillis8 = millis();                              //Zeitverzögerung
                if (currentMillis8 - previousMillis >= interval)
                {
                  digitalWrite(Channel_Up, LOW);
                  previousMillis = currentMillis8;
                }     

          digitalWrite(Rollo_Stop, HIGH);
                unsigned long currentMillis9 = millis();                              //Zeitverzögerung
                if (currentMillis9 - previousMillis >= interval)
                {
                  digitalWrite(Rollo_Stop, LOW);
                  previousMillis = currentMillis9;
                }
        }

      
}

Hausautomatik_1.3.ino (4.01 KB)

Rollo_Remote.h (37.8 KB)

Möglicherweise hast Du CurrentMillis und LastMillis verwechselt. Zumindest macht es keinen Sinn, die aktuellen Millis in 9 verschiedenen Variablen zu halten, die letztendlich alle in previousMillis zurückgeschrieben werden. Wenn schon, dann die previousMillis für jeden Schritt einzeln merken, wenn eine Aktion begonnen hat. currentMillis muß nur einmal pro Durchlauf ermittelt werden.

Auf jeden Fall fehlt noch eine Status-Variable, welcher Schritt gerade aktiv ist. Dann wird nur noch dieser Schritt überprüft, bis sein Intervall abgelaufen ist, und dann der nächste Schritt gestartet. Informiere Dich mal über endliche Automaten (state machine).

Wenn die Codes von Alexa kürzer vorhanden sind als die Impulszeit, benötigst Du noch einen Merker, der so lange gesetzt ist, wie die Zeit läuft.

        if(Alexa_lesen == 0x0F) Alexa_Merker_0F = true;  // besser mit switch/case

        if(Alexa_Merker_0F)
        {
          digitalWrite(Channel_Zero, HIGH);   //HIGH
...
          Alexa_Merker_0F = false;  // nach Ablauf der Zeit

Unabhängig von Deiner Fragestellung ruft die Rollosteuerung nach einer Funktion oder besser einer Methode, da die Logik aller Rollos wohl gleich sein sollte. Eine Funktion/Methode läßt sich dann auch leichter korrigieren.

Vielen Dank für euer schnelle Antworten, ich werde versuchen eure Vorschläge umzusetzen und dann Bericht erstatten!

Augin_Aho:
.....
Also zur Zusammenfassung Arduino kriegt einen Befehl (inform eines Hexcodes) und dann soll das rummdrücken auf der Fernbedienung simuliert werden um damit die Rollos zu steuern.
(Fernbedienung auslösen nicht möglich aufgrund von Rolling codes)
.....

Das ist mir nicht ganz klar.

Widerspricht sich das nicht ?

Ich vermute daß das Herumdrücken auf der Tastatur durchgeführt werden soll, nicht simuliert.

DrDiettrich:
Ich vermute daß das Herumdrücken auf der Tastatur durchgeführt werden soll, nicht simuliert.

Achso....verstehe das mit einem Servo o.ä. ?

Also da sollte sich der TO doch mal verständlicher ausdrücken (nicht simulieren :wink: ).

Hi

So denke ich nicht, denke eher an Opto-Koppler, Die auf die Platine kommen.
Also für den Sender kommen schon ganz normal Tastendrücke an - nur drückt Keiner mechanisch das Leitgummi auf die Platine.

MfG

Genau

ich habe eine Fernbedienung mit Tastern drauf (also keine mit Leitgummi oder so) An diese Fernbedienung möchte ich über Transistoren/Optokoppler die Taster Kontakte quasi brücken wenn den Transistoren vom Arduino angesteuert werden.

Somit gauckle ich der Fernbedienung vor das ein Mensch auf der Fernbedienung rum drückt,
stattdessen macht das der Arduino/ESP8266 für mich.

Augin_Aho:
Genau

ich habe eine Fernbedienung mit Tastern drauf (also keine mit Leitgummi oder so) An diese Fernbedienung möchte ich über Transistoren/Optokoppler die Taster Kontakte quasi brücken wenn den Transistoren vom Arduino angesteuert werden.

Somit gauckle ich der Fernbedienung vor das ein Mensch auf der Fernbedienung rum drückt,
stattdessen macht das der Arduino/ESP8266 für mich.

Ahhh....das ist dann mal eine verständliche Erklärung.
So sollte es funktionieren. Allerdings musst du schon darauf achten, ob die Tasten einfach nur gegen GND oder VCC geschaltet sind, oder als Matrix aufgebaut sind.

Wenn Optokoppler eingesetzt werden, muß man nur drauf achten, wo Plus (Kollektor) und Minus (Emitter) an den Tasten anliegen.

darauf achten, ob die Tasten einfach nur gegen GND oder VCC geschaltet sind, oder als Matrix aufgebaut sind

Wenn jede Taste ihren eigenen Optokoppler kriegen soll, ist das egal.

Ansonsten könnte man die n*m Taster-Matrix auch mit n+m Optokopplern bedienen, von denen man immer zwei gleichzeitig durchsteuern müsste.

In jedem Fall eine fummelige Lötarbeit, fürchte ich. Hoffentlich überlebt die Fernbedienung das.

Ich habe das ganze jetzt mal so gelößt es funktioniert bis hier hin, aber ich glaube nicht das es so 100% richtig ist vorallem müsste ich dann für jeden Kanal der Fernbedienung (Bis 15 möglich, Wählbar durch einen Up-taster)

eine Eigene Switch Case Anweisung geben und dann oben jeweils nach der reihe antriggern, vlt denke ich zu Kompliziert…

const byte Ch_Up_Pin = 3; //25
const byte Ch_Zero_Pin = 5;//27
const byte Ch_Down_Pin = 29;
const byte Rollo_Up_Pin = 6;//31
const byte Rollo_Stop_Pin = 33;
const byte Rollo_Down_Pin = 4;//35

enum ZUSTAENDE {Ch_Up_An, Ch_Up_Aus, Ch_Zero_An, Ch_Zero_Aus, Ch_Down_An, Ch_Down_Aus,
                Rollo_Up_An, Rollo_Up_Aus, Rollo_Stop_An, Rollo_Stop_Aus, Rollo_Down_An, Rollo_Down_Aus, Keiner};

byte Kanal, Position, Kanal1 = Keiner;

                
const int BUTTON_PUSH = 50;      //Kanal0 Taster(Zeit)
const int BUTTON_PUSH1 = 150;     //Kanal1 Taster(Zeit)
const int BUTTON_PUSH2 = 300;     //Positions Taster (Zeit)
unsigned long buttonMillis;
unsigned long buttonIntervall;

//Hex Codes anpassen
void Abfrage_Rollo_Code(){
  
  if(Alexa_lesen == 0x0F){    //Alle Rolloss Hoch (Kanal 0)
    Kanal = Ch_Zero_An;
    Position = Rollo_Up_An;
    }
    else if (Alexa_lesen == 0x10){      //Runter
    Kanal = Ch_Zero_An;
    Position = Rollo_Down_An;
    }

  if(Alexa_lesen == 0x0D){    //Rollo Wohn1 Hoch (Kanal1)
    Kanal = Ch_Zero_An;
    Kanal1 = Ch_Up_An;
    Position = Rollo_Up_An; 
    }
    else if (Alexa_lesen == 0x0E){      //Runter
    Kanal = Ch_Zero_An;
    Kanal1 = Ch_Up_An;
    Position = Rollo_Down_An; 
    }
}


void Steuerung_Rollos() {

  if (millis() - buttonMillis >= buttonIntervall) {
    switch (Kanal) {
/*****************Kanal 0*******************/       
      case Ch_Zero_An:
        digitalWrite(Ch_Zero_Pin, HIGH);
        Kanal = Ch_Zero_Aus;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
      case Ch_Zero_Aus:
        digitalWrite(Ch_Zero_Pin, LOW);
        Kanal = Keiner;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
} }
/*********************Kanal 1******************/ 
if (millis() - buttonMillis >= buttonIntervall) {
    switch (Kanal1) {
      case Ch_Up_An:
        digitalWrite(Ch_Up_Pin, HIGH);
        Kanal1 = Ch_Up_Aus;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH1;
        break;
      case Ch_Up_Aus:
        digitalWrite(Ch_Up_Pin, LOW);
        Kanal1 = Keiner;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH1;
        break;
    } }


  
/********************Position Rollos***********************/
if (millis() - buttonMillis >= buttonIntervall) {
    switch (Position) {
      case Rollo_Down_An:
         digitalWrite(Rollo_Down_Pin, HIGH);
         Position = Rollo_Down_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Down_Aus:
         digitalWrite(Rollo_Down_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
/********************Rollo Hoch*********************/
      case Rollo_Up_An:
         digitalWrite(Rollo_Up_Pin, HIGH);
         Position = Rollo_Up_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Up_Aus:
         digitalWrite(Rollo_Up_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
/**********************Rollo Runter********************/         
      case Rollo_Stop_An:
         digitalWrite(Rollo_Stop_Pin, HIGH);
         Position = Rollo_Stop_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Stop_Aus:
         digitalWrite(Rollo_Stop_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
    }
  } 


 
}

Hausautomatik_1.3.ino (4.06 KB)

Rollo_Remote.h (3.69 KB)

Steuerung_Licht_Alexa.h (1.57 KB)

Taster_Steuerung.h (8.49 KB)

Hausautomatik_Alexa_1.1.ino (4.76 KB)

Versuchs mal so:
Jeder Rollo hat die Zustände {oben, unten, rauf, runter).
Als Kommando kommt der gewünschte Zustand, also oben oder unten. Wenn dieser Zustand nicht der aktuelle ist, muß der Rollo rauf oder runter fahren, dafür die beiden zusätzlichen Zustände. Wenn das rauf oder runter fahren beendet ist, entweder nach einem Zeitintervall oder Endschalter, dann wird der Motor wieder gestoppt und der Zustand auf oben oder unten gesetzt.

Und das für jeden Rollo, am einfachsten mit Arrays oder einem struct Array. Da drin stehen dann die Pins des Motors, der aktuelle Zustand und ggf. die Zeit, die das rauf/runter fahren noch dauern muß.

Habs jetzt so gelöst, funktioniert bis jetzt ohne Probleme, stelle mir grad nur die frage (da ich grad von dem thema gelesen habe) ob ich probleme mit dem millis overflow bekomme oder ist das bei mir uninteressant?

/****Rollo Remote.h**************/
const byte Ch_Up_Pin = 31; //25
const byte Ch_Zero_Pin = 29;//27
const byte Rollo_Up_Pin = 27;//31
const byte Rollo_Stop_Pin = 35;//33
const byte Rollo_Down_Pin = 33;//35

enum ZUSTAENDE {Ch_Up_An, Ch_Up_Aus, Ch_Zero_An, Ch_Zero_Aus, Rollo_Up_An, Rollo_Up_Aus,
                Rollo_Stop_An, Rollo_Stop_Aus, Rollo_Down_An, Rollo_Down_Aus, Awake_An, Awake_Aus, Keiner};

byte Kanal, Position = Keiner;


const int BUTTON_PUSH = 100;      //Kanal0 Taster(Zeit)
const int BUTTON_PUSH1 = 150;     //Kanal1 Taster(Zeit)
const int BUTTON_PUSH2 = 150;     //Positions Taster (Zeit)
unsigned long buttonMillis;
unsigned long buttonIntervall;




void Kanal_Schleife() {Kanal = Ch_Up_An;}

void wait_Up() {Position = Rollo_Up_An;}

void wait_Down() {Position = Rollo_Down_An;}




//Hex Codes anpassen
void Abfrage_Rollo_Code(){

  if(Alexa_lesen == 0x0F){    //Alle Rolloss Hoch (Kanal 0)
    Kanal = Awake_An;
    Position = Rollo_Up_An;
    }
    else if (Alexa_lesen == 0x10){      //Runter
    Kanal = Awake_An;
    Position = Rollo_Down_An;
    }
/**************************************************************************/
  if(Alexa_lesen == 0x11){    //Rollo Wohn1 Hoch (Kanal1)
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 1); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(550, wait_Up);  //Position = Rollo_Up_An
    }
    else if (Alexa_lesen == 0x12){      //Runter
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 1); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(550, wait_Down);    //Position = Rollo_Down_An           wait muss immer länger als Kanal sein!
    }
/**************************Rollo Wohn2***********************************/
    if(Alexa_lesen == 0x13){    //Rollo Wohn2 Hoch (Kanal1)
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 2); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(1200, wait_Up);  //Position = Rollo_Up_An
    }
    else if (Alexa_lesen == 0x14){      //Runter
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 2); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(1200, wait_Down);    //Position = Rollo_Down_An           wait muss immer länger als Kanal sein!
    }
/**************************ROLLO_TERASSE1***********************************/
    if(Alexa_lesen == 0x15){    //Rollo Terasse Hoch (Kanal1)
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 3); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(1650, wait_Up);  //Position = Rollo_Up_An
    }
    else if (Alexa_lesen == 0x16){      //Runter
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 3); //Kanal1 = Ch_Up_An 1mal
    timer.setTimeout(1650, wait_Down);    //Position = Rollo_Down_An           wait muss immer länger als Kanal sein!
    }
/**************************ROLLO_KOCHEN1************************************/
    if(Alexa_lesen == 0x17){    //Rollo Kochen Hoch (Kanal1)
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 4); //Kanal4 = Ch_Up_An 4mal
    timer.setTimeout(2150, wait_Up);  //Position = Rollo_Up_An
    }
    else if (Alexa_lesen == 0x16){      //Runter
    Kanal = Awake_An;
    timer.setTimer(500, Kanal_Schleife, 4); //Kanal4 = Ch_Up_An 4mal
    timer.setTimeout(2150, wait_Down);    //Position = Rollo_Down_An           wait muss immer länger als Kanal sein!
    }

    if(Alexa_lesen == 0x19){    //Alle Rollos Stop (Kanal 0)
    Kanal = Awake_An;
    Position = Rollo_Stop_An;
    }
    else if (Alexa_lesen == 0x1A){      //Stop
    Kanal = Awake_An;
    Position = Rollo_Stop_An;
    }
}




void Steuerung_Rollos() {

  if (millis() - buttonMillis >= buttonIntervall) {
    switch (Kanal) {
/*****************Kanal 0*******************/
      case Awake_An:
        digitalWrite(Ch_Zero_Pin, HIGH);
        Kanal = Awake_Aus;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
      case Awake_Aus:
        digitalWrite(Ch_Zero_Pin, LOW);
        Kanal = Ch_Zero_An;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
 /************************************************/
      case Ch_Zero_An:
        digitalWrite(Ch_Zero_Pin, HIGH);
        Kanal = Ch_Zero_Aus;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
      case Ch_Zero_Aus:
        digitalWrite(Ch_Zero_Pin, LOW);
        Kanal = Keiner;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH;
        break;
/************************************************/
      case Ch_Up_An:
        digitalWrite(Ch_Up_Pin, HIGH);
        Kanal = Ch_Up_Aus;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH1;
        break;
      case Ch_Up_Aus:
        digitalWrite(Ch_Up_Pin, LOW);
        Kanal = Keiner;
        buttonMillis = millis();
        buttonIntervall = BUTTON_PUSH1;
        break;

} }




/********************Position Rollos***********************/
if (millis() - buttonMillis >= buttonIntervall) {
    switch (Position) {
      case Rollo_Down_An:
         digitalWrite(Rollo_Down_Pin, HIGH);
         Position = Rollo_Down_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Down_Aus:
         digitalWrite(Rollo_Down_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
/********************Rollo Hoch*********************/
      case Rollo_Up_An:
         digitalWrite(Rollo_Up_Pin, HIGH);
         Position = Rollo_Up_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Up_Aus:
         digitalWrite(Rollo_Up_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
/**********************Rollo Stop********************/
      case Rollo_Stop_An:
         digitalWrite(Rollo_Stop_Pin, HIGH);
         Position = Rollo_Stop_Aus;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
      case Rollo_Stop_Aus:
         digitalWrite(Rollo_Stop_Pin, LOW);
         Position = Keiner;
         buttonMillis = millis();
         buttonIntervall = BUTTON_PUSH2;
         break;
    }
  }
}

Bei einer Formulierung wie

 if (millis() - buttonMillis >= buttonIntervall) {

bekommt man keine Probleme beim Überlauf.
Die Differenz ist positiv, relativ klein und vor allem richtig, selbst wenn millis() 0 oder kurz darüber liefert, und buttonMillis eine Zahl kurz vor dem Überlauf ist.