RC-Switch "value" löschen wegen Taster losgelassen

Hallo zusammen,

erstmal Danke für die Aufnahme hier im Forum.

Ich hänge an folgendem Problem:

Ich möchte mittels RC-Switch über Funk 2 Relais tastend schalten, also nur EIN, solange auf der Fernbediening die entsprechende Taste gedrückt wird, danach wieder AUS.

Der Sender sendet entsprechend der Beispiel-Sketche bei einer Taste die "1234", bei der anderen die "5678"

Das funktioniert soweit, kommt beim Empfänger an und wird auch ausgeführt. Doch bleibt der Status dann so stehen, wie der letzte Funkbefehl kam.

Hier der Code dazu, zumindest ein Auszug:

 if (value == 1234)   
        {   
        Serial.print("Relais 1 ein");
        digitalWrite(Pin1, HIGH); 
        } 
        else {
       digitalWrite(Pin1, LOW); 

Das "else" greift hier aber nicht, weil "value" gespeichert ist und erst geändert wird, wenn etwas anderes empfangen wird.

Also am Sender sendet Taste 1 "1234" und Taste 2 "5678". Das möchte ich gerne so zuordnen, dass solange 1234 empfangen wird, Pin 1 auf HIGH geht, wenn es nicht mehr gesendet wird, Pin 1 auf LOW geht, dementsprechend auch für Pin 2 mit 5678.

Ich habe nun schon soviel kreuz und quer gelesen, dass ich gar nicht mehr weiß, wie ich weiterkomme. Irgendwas hatte ich noch gefunden mit einer Art Timeout, um zu erkennen, ob neu gesendet wurde, aber das ist mir dann doch zu hoch.

Grüße und erstmal guten Rutsch ins neue Jahr

Dirk

Hallo Dirk

Wenn die Zeichenfolge "ABCD" empfangen worden ist, dann wird eine Eieruhr aufgezogen und der Ausgang gesetzt. Läuft diese Eieruhr ab, da sie nicht mehr aufgezogen wird, dann wird der Ausgang zurückgesetzt.

Nehme das BLINKWITHOUTDELAY Beispiel aus dem IDE und programmiere damit die Eieruhr.

Ich wünsche einen geschmeidigen Abend und viel Spass beim Programmieren in C++.

Der zeigt leider nicht mal, wie value auf 1234 gesetzt wird.
Noch interessanter wäre zu sehen was passiert, wenn nichts gesendet wird, bzw. Woran man erkennt, dass eine Taste dauernd gedrückt ist.

Ich kann Dir Bestätigen daß im Auszug kein Fehler vorhanden ist.

Der Fehler könnte im Rest des Sketches stecken.
Kann mir Vorstellen zB daß die Variable auch nach loslassen des Tasters bzw Nicht mehr senden das Codes immernoch den Wert 1234 enthält.

Oder mit anderen Worten Bitte den gesamten Sketch zeigen.
Grüße Uwe

Im Gegensatz zu Uwe muss ich Dir mitteilen, das der Schnipsel fehlende Klammern hat.
Wenn die schliessenden Klammer da drunter aufgefüllt ist, kannst Du nach der letzten Klammer schreiben:

value=0;

Damit dürfte beim nächsten Durchlauf die Bedingung für den ELSE-Zweig stimmen.

Alternativ: Value nicht global festlegen sondern nur lokal und initialisieren mit der Inhaltszuweisung.

value wird von rcswitch gesetzt. Das ist genau das, was vom Sender empfangen wurde. Es ändert sich nur, wenn etwas anderes empfangen wurde. Der Sender sendet zwar nicht weiter, aber value bleibt auf dem letzten Status stehen.

Den ganzen Sketch habe ich absichtlich nicht gepostet, weil er von der Rumprobiererei zuviel auskommentierte Sachen enthält. >rotwerd<
Ja genau, valuewird vom Empfang her gesetzt und bleibt so stehen, bis was anderes gesetzt wird.

Du hast noch keine rumprobiercodes gesehen.
Es gibt vermutlich sehr wenig, was erschüttert.

1 Like

5m Spaghetticode erschüttern mich schon ein wenig. :wink: :wink:

Grüße Uwe

Löche die Variable nach dem kontrollieren ob sie einem Code entpricht.

also ( Achtung nur Auszug):

if (value == 1234)   
        {   
        LED 1 an;
       value = 9999;
        } 
if (value == 5678)   
        {   
        LED 2 an;
       value = 9999;
        } 

if (value == 9999)   
        {   
        LED 1 aus;
        LED 2 aus;
       value = 0;
        } 

In diesem Fall wäre besser ein switch case zu verwenden, ich war aber zu faul das zu machen.

Grüße Uwe

Hallo howy-1

Hier kommt ein einfaches Beispiel zum Schalten der I/O Pins.
Da ich keine Fernsteuerung habe, habe ich eine rcSim() Funktion geschrieben, die die Fernsteuerung simuliert.
Einfach ausprobieren, spielen und an deine Anforderungen anpassen.

/* BLOCK COMMENT
  - https://forum.arduino.cc/t/rc-switch-value-loschen-wegen-taster-losgelassen/1071626/1
  - RC-Switch “value” löschen wegen Taster losgelassen
  - This sketch may contain traces of C++.
  - In case of indisposition:
  - https://www.learncpp.com/
  - Hardware:
  - Thanks to LarryD
  - https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
  - Tested @ Arduino: Mega[X] - UNO [ ] - Nano [ ]
*/
#define ProjectName "RC-Switch “value” löschen wegen Taster losgelassen"
// make names
enum OnOff {Off, On};
// make structures
struct RC2PIN
{
  const int value;
  const byte Pin;
}
rc2Pins[]
{
  {1234, 9},
  {5678, 10},
};
int rcSim()
{
  static int getBack = 0;
  if (Serial.available())
  {
    switch (Serial.read())
    {
      case '1':
        Serial.println("value = 1234");
        getBack = 1234;
        break;
      case '2':
        Serial.println("value = 5678");
        getBack = 5678;
        break;
      case '\n':
        break;
      default:
        Serial.println("value = unknown");
        getBack = 0;
        break;
    }
  }
  return getBack;
}
void setup()
{
  Serial.begin(115200);
  Serial.print(ProjectName), Serial.print(" in "), Serial.println(__FILE__);

  for (auto rc2Pin : rc2Pins) {
    pinMode(rc2Pin.Pin, OUTPUT);
    Serial.println("led test");
    digitalWrite (rc2Pin.Pin, On);
    delay(1000);
    digitalWrite (rc2Pin.Pin, Off);
  }
  Serial.println("\n enter [1] to send '1234' or [2] to send '5678'");
}
void loop()
{
  for (auto rc2Pin : rc2Pins) digitalWrite (rc2Pin.Pin, rc2Pin.value == rcSim());
}

Ich wünsche einen geschmeidigen Tag und viel Spass beim Programmieren in C++.

So, nun mal verspätet der Ausgangssketch, von allen Auskommentierungen bereinigt.
Es funktioniert so erstmal, dass beim Empfang von 1234 das Relais 1 eingeschaltet wird und bleibt.
Bei 5678 geht Relais 1 aus und Relais 2 geht an und bleibt.

#include "RCSwitch.h"

RCSwitch mySwitch = RCSwitch();



//--------------------------------------------------------------


int Pin1 = 27;
int Pin2 = 25; 


void setup() {
  Serial.begin(115200);
 
  Serial.println("Fernsteuerung wurde gestartet!");
  mySwitch.enableReceive(digitalPinToInterrupt(2)); // Daran hängt der DATA-Pin des Empfängers
 
  

     // Outputs:
    pinMode(Pin1, OUTPUT);
    pinMode(Pin2, OUTPUT);


       Serial.print("   Begonnen    ");
    
    
       
   }

void loop() {
  
 
  if (mySwitch.available())// Wenn ein Code Empfangen wird...
  
  {
  int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
  if (value == 0) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      Serial.println("Unbekannter Code");
    } 
    
    else // Wenn der Empfangene Code brauchbar ist, wird er hier an den Serial Monitor gesendet.
    {
      Serial.print("Empfangen: ");
      Serial.println( value );

    }   
        
    if (value == 1234)   
        {   
        Serial.print("Relais 1 ein");
        digitalWrite(Pin1, HIGH); 
        
        } 
        else {
       digitalWrite(Pin1, LOW); 
        };     

     if (value == 5678)   
        {   
        Serial.print("Relais 2 ein ");
        digitalWrite(Pin2, HIGH); 
        } 
        else {

       digitalWrite(Pin2, LOW); 
       }   
   
  
  }   
    mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"
}  
 

Dann habe ich die if etwas verändert, um zu sehen, wie es reagiert:

 if (value == 5678)   
        {   
        Serial.print("Relais 2 ein ");
        digitalWrite(Pin2, HIGH);
        delay(1000);
        value = 8888;
        Serial.println( value );
        } 


       if (value == 8888)   
        {   
        Serial.print("Alles Aus ");
        digitalWrite(Pin1, LOW);
        digitalWrite(Pin2, LOW);
        delay(1000);
        Serial.println( value );
        } 

Ist klar, nach wahrwerden von 5678 geht das Relais an und value wird auf 8888 gesetzt. Darauf kommt das nächste if und macht alles wieder aus. Durch das Delay schön im Sekundentakt :wink:
Ohne das Delay würde sofort gleich alles wieder ausgeschaltet werden, ohne jemals die Chance zum einschalten bekommen zu haben. Also so klappt das schonmal nicht so wie ich es gerne hätte.

Dann werde ich mal versuchen, ob ich mit dem Beispiel von @paulpaulson klarkomme. :face_with_monocle:

Dann dreh die Reihenfolge um.
Zuerst Wert vom Empfänger holen wenn einer da ist.
dann kontrollieren ob ausschalten
dann kontrollieren ob einschalten und code für ausschalten setzen.
Von vorne.
Grüße Uwe

Du denkst zu kompliziert.
Es ist nur eine Klammer.
Dann hast Du einen Grundstock.
Schau Dir den Unterschied an und dann überlege, was ich da warum verändert haben könnte :wink:

#include "RCSwitch.h"

RCSwitch mySwitch = RCSwitch();



//--------------------------------------------------------------


int Pin1 = 27;
int Pin2 = 25;


void setup()
{
  Serial.begin(115200);
  Serial.println("Fernsteuerung wurde gestartet!");
  mySwitch.enableReceive(digitalPinToInterrupt(2)); // Daran hängt der DATA-Pin des Empfängers
  // Outputs:
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  Serial.print("   Begonnen    ");
}

void loop()
{
  int value = 0;
  if (mySwitch.available())// Wenn ein Code Empfangen wird...
  {
    value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
  }
  /*
    if (value == 0) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      Serial.println("Unbekannter Code");
    }
    else // Wenn der Empfangene Code brauchbar ist, wird er hier an den Serial Monitor gesendet.
    {
      Serial.print("Empfangen: ");
      Serial.println( value );
    }
  */
  if (value == 1234)
  {
    Serial.print("Relais 1 ein");
    digitalWrite(Pin1, HIGH);
  }
  else
  {
    digitalWrite(Pin1, LOW);
  };
  if (value == 5678)
  {
    Serial.print("Relais 2 ein ");
    digitalWrite(Pin2, HIGH);
  }
  else
  {
    digitalWrite(Pin2, LOW);
  }
  mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"
}

Achtung die Ausgabe auf dem SerMon könnte Dich evtl. überrollen, aber das ist noch nebensächlich.

@my_xy_projekt
Okay, ich habe es jetzt so gemacht, wie von Dir geschrieben.
Das int value = 0; gleich zu Anfang des loop setzt value auf 0 . Bei empfangenem 1234 oder 5678 scheint nichts zu passieren, oder so schnell, dass es nicht zum tragen kommt.
Am Ende des loop habe ich ein

 Serial.print("Value ist   ");
      Serial.println( value );

eingefügt, um den Endstatus von value auf der Konsole zu sehen, und der ist immer 0, selbst mit einem delay(3000) am Ende, um nicht doch von der Ausgabe überrollt zu werden. :wink:

@paulpaulson
Sorry, ich kriege da nicht auseinandergepflückt, was zu Deiner Simulation gehört, und was ich in meinen Sketch einfügen könnte. :thinking:

Hallo howy-1

Ich habe den Sketch ergänzt, so dass man sehen kann welchen Wert die Variable "value" annimmt.
Die delay() Funktion ist nur zum Testen und kann gelöscht werden.

  - https://forum.arduino.cc/t/rc-switch-value-loschen-wegen-taster-losgelassen/1071626/1
  - RC-Switch “value” löschen wegen Taster losgelassen
  - This sketch may contain traces of C++.
  - In case of indisposition:
  - https://www.learncpp.com/
  - Hardware:
  - Thanks to LarryD
  - https://europe1.discourse-cdn.com/arduino/original/4X/7/e/0/7e0ee1e51f1df32e30893550c85f0dd33244fb0e.jpeg
  - https://forum.arduino.cc/t/beginners-software-needs-hardware/1066703
  - Tested @ Arduino: Mega[X] - UNO [ ] - Nano [ ]
  - https://forum.arduino.cc/u/paulpaulson/summary
*/
#define ProjectName "RC-Switch “value” löschen wegen Taster losgelassen"
// make names
enum OnOff {Off, On};
// make structures
struct RC2PIN
{
  const int value;
  const byte Pin;
}
rc2Pins[]
{
  {1234, 9},
  {5678, 10},
};
int rcSim()
{
  static int getBack = 0;
  if (Serial.available())
  {
    switch (Serial.read())
    {
      case '1':
        Serial.println("value = 1234");
        getBack = 1234;
        break;
      case '2':
        Serial.println("value = 5678");
        getBack = 5678;
        break;
      case '\n':
        break;
      default:
        Serial.println("value = unknown");
        getBack = 0;
        break;
    }
  }
  return getBack;
}
void setup()
{
  Serial.begin(115200);
  Serial.print(ProjectName), Serial.print(" in "), Serial.println(__FILE__);

  for (auto rc2Pin : rc2Pins) {
    pinMode(rc2Pin.Pin, OUTPUT);
    Serial.println("led test");
    digitalWrite (rc2Pin.Pin, On);
    delay(1000);
    digitalWrite (rc2Pin.Pin, Off);
  }
  Serial.println("\n enter [1] to send '1234' or [2] to send '5678'");
}
void loop()
{
  int value=rcSim(); 
  Serial.print(F("value=")), Serial.println(value); 
  delay(1000); // for test purposes only 
  for (auto rc2Pin : rc2Pins) digitalWrite (rc2Pin.Pin, rc2Pin.value == value);
}

Ich habe es jetzt gelöst, nach vielem rumprobieren:

/*************************************************************************************************
                                      PROGRAMMINFO
**************************************************************************************************
  Funktion: ESP32 BT CAR APP
**************************************************************************************************
  Version: 11.03.2023 A135
**************************************************************************************************
  Board: ESP32vn IoT UNO V1.0.4

**************************************************************************************************
  C++ Arduino IDE V1.8.13
**************************************************************************************************
  Einstellungen:
  https://dl.espressif.com/dl/package_esp32_index.json
  http://dan.drown.org/stm32duino/package_STM32duino_index.json
  https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
**************************************************************************************************
**************************************************************************************************/

#include "RCSwitch.h"

RCSwitch mySwitch = RCSwitch();


int Pin1 = 27;
int Pin2 = 25;



void setup() {
  Serial.begin(115200);

  Serial.println("Fernsteuerung wurde gestartet!");
  mySwitch.enableReceive(digitalPinToInterrupt(2)); // Daran hängt der DATA-Pin des Empfängers



  // Outputs:
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);


  Serial.print("   Begonnen    ");

  }

void loop() {

  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
    int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
    if (value == 0) // Wenn die Empfangenen Daten "0" sind, wird "Unbekannter Code" angezeigt.
    {
      Serial.println("Unbekannter Code");
    }

    else 
    {
      Serial.print("Empfangen: ");
      Serial.println( value );


      if (value == 1234)
      {
        Serial.println("Relais 1 ein");
        digitalWrite(Pin1, HIGH);
        digitalWrite(Pin2, LOW);
      }


      if (value == 5678)
      {
        Serial.println("Relais 2 ein ");
        digitalWrite(Pin2, HIGH);
        digitalWrite(Pin1, LOW);
      }

    }
    mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"
    delay(200);
  }
  else
  {
    Serial.println("  nichts Empfangen ");
    digitalWrite(Pin2, LOW);
    digitalWrite(Pin1, LOW);
  }

  
}

Die erste if-Abfrage fragt ja danach, ob überhaupt etwas empfangen wird. ein else dazu gibt es in den Beispielen nicht.
Das habe ich am Schluss hinzugefügt, aber erst durch das delay davor funktioniert es. :grinning:

Vielen Dank an alle, die mir helfend beistanden.

Nun habe ich erstmal bloß noch die Frage, ob dieses else bzw. die ständige Ausführung der dazugehörigen Befehle, irgendwas blockieren oder überlasten könnte.

Dirk

nein.

Aber ich frag mich ob nicht ein switch case schöner wäre und einfacher zu lesen ist:

/*************************************************************************************************
                                      PROGRAMMINFO
**************************************************************************************************
  Funktion: ESP32 BT CAR APP
**************************************************************************************************
  Version: 11.03.2023 A135
**************************************************************************************************
  Board: ESP32vn IoT UNO V1.0.4

**************************************************************************************************
  C++ Arduino IDE V1.8.13
**************************************************************************************************
  Einstellungen:
  https://dl.espressif.com/dl/package_esp32_index.json
  http://dan.drown.org/stm32duino/package_STM32duino_index.json
  https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_dev_index.json
**************************************************************************************************
**************************************************************************************************/

#include "RCSwitch.h"

RCSwitch mySwitch = RCSwitch();


int Pin1 = 27;
int Pin2 = 25;



void setup() {
  Serial.begin(115200);

  Serial.println(F("Fernsteuerung wurde gestartet!"));
  mySwitch.enableReceive(digitalPinToInterrupt(2)); // Daran hängt der DATA-Pin des Empfängers

  // Outputs:
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  Serial.print(F("   Begonnen    "));
}

void loop() {

  if (mySwitch.available()) // Wenn ein Code Empfangen wird...
  {
    int value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.

    switch (value)
    {
      case 0 :
        Serial.println(F("Unbekannter Code"));
        break;
      case 1234:
        Serial.print(F("Empfangen: "));
        Serial.println( value );
        Serial.println(F("Relais 1 ein"));
        digitalWrite(Pin1, HIGH);
        digitalWrite(Pin2, LOW);
        break;
      case  5678:
        Serial.print(F("Empfangen: "));
        Serial.println( value );
        Serial.println(F("Relais 2 ein "));
        digitalWrite(Pin2, HIGH);
        digitalWrite(Pin1, LOW);
    }
    mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"
    delay(200);
  }
  else
  {
    Serial.println(F("  nichts Empfangen "));
    digitalWrite(Pin2, LOW);
    digitalWrite(Pin1, LOW);
  }
}

übrigens, lies mal zur Verwendung vom Arduino F-Makro nach.

Das wird genau so sein.
Bedenke, das Deine Relaisschaltung sehr träge ist und der Code eben nicht dauerhaft kommt.
Der SerMon wird Dir den empfangenen Code nicht anzeigen, weil das ständige 0 den Puffer zum überlaufen bringt.
Dein delay() ist aber auch keine Lösung, weil Du damit Deinen Code komplett blockierst.

Ich bin noch nicht durch die RC-lib durch, aber ich hoffe, das da solange gewartet wird, bis der Code vollständig ist.
Darum hab ich mal den Code ohne delay und mit einer zusätzlichen Ausgabe versehen.
Wenn Du keine Taste drückst, sollte nix passieren und wenn Taste, dann immer vollständiger Code

#include "RCSwitch.h"

RCSwitch mySwitch = RCSwitch();



//--------------------------------------------------------------


int Pin1 = 27;
int Pin2 = 25;


void setup()
{
  Serial.begin(115200);
  Serial.println("Fernsteuerung wurde gestartet!");
  mySwitch.enableReceive(digitalPinToInterrupt(2)); // Daran hängt der DATA-Pin des Empfängers
  // Outputs:
  pinMode(Pin1, OUTPUT);
  pinMode(Pin2, OUTPUT);
  Serial.print("   Begonnen    ");
}

void loop()
{
  int value = 0;
  if (mySwitch.available())// Wenn ein Code Empfangen wird...
  {
    value = mySwitch.getReceivedValue(); // Empfangene Daten werden unter der Variable "value" gespeichert.
    mySwitch.resetAvailable(); // Hier wird der Empfänger "resettet"
  }
  if (value == 1234)
  {
    Serial.print(F("Relais 1 ein"));
    digitalWrite(Pin1, HIGH);
    digitalWrite(Pin2, LOW);
  }
  if (value == 5678)
  {
    Serial.print(F("Relais 2 ein "));
    digitalWrite(Pin2, HIGH);
    digitalWrite(Pin1, LOW);
  }
  if (value != 0)
  {
    Serial.println(value);
    startTime = millis();
  }
  if (millis() - startTime > 200)
  {
    digitalWrite(pin1, LOW);
    digitalWrite(pin2, LOW);
  }
}