Avoid duplicates inputs from RF 433 RC transmitter waiting while() loop

Hello! I created a code based on the RC-Switch radio reception library, which should write the value of the received frequency from the radio control to a json file, and then write it to EEPROM. I need to store 18 button codes in EEPROM. But I ran into the problem that when you press one button quickly, the signal can be sent several times and the same button will be recorded several times. The second or third repeating signal comes almost instantly (less than 100 milliseconds) and I decided to make a condition with timers that will not execute the function if the data came less than 100 milliseconds ago. But unfortunately, millis() doesn't work because I have a while loop that waits for the next button to be pressed. How to properly organize my counter, which timers should I use? Maybe someone knows if there is such a possibility inside the RC-Switch library? I need that my conditions were executed with a strict delay of 100 ms after the first execution, and everything that came faster than 100 ms was ignored
I will be grateful for the answers.
Here is my code:

#include <RCSwitch.h>
#include <ArduinoJson.h>
#include <StreamUtils.h>
#include <EEPROM.h>
RCSwitch mySwitch = RCSwitch();
//StaticJsonDocument<440> doc;
DynamicJsonDocument doc(440);
EepromStream eepromStream(0, 440);
unsigned long btn1_code_rec_time = 0;
unsigned long no_repeat_delay = 100;

void setup() {
  Serial.begin(9600);
  pinMode(8, OUTPUT); //set a pin to output data (leds connected to this pin in my example)
  mySwitch.enableReceive(0);  // receiver must be connected to digital pin 2
}

void jSondb() {
  unsigned long recVal[18];
  int a = 0;
  while (a < 18) {
    if (mySwitch.available()) { //if any data from RF remote was received
      if  (((millis() - btn1_code_rec_time) > no_repeat_delay)) { //If the data was received within 100 milliseconds after the first one was received, ignore it.
        btn1_code_rec_time = millis(); //record the time the button was pressed
        recVal[a] = mySwitch.getReceivedValue();
        doc["Buttons"][a] = recVal[a];
        a += 1; // waiting for receive value next button
        mySwitch.resetAvailable();
      }
    }
  }
  serializeJson(doc, eepromStream);
}

Consider letting loop() do what it does best, ie loop, and put the data, including the millis() value of when the button presses are detected, in arrays

It's a part of a big project, so I can't contain it in void loop(); I need this while , because I need to follow the order of pressing the buttons, I don't know what the button keycodes will be, and I don't know the timings when the button will pressed.

There is no need for the code to be contained in the loop() function, it can be in its own function called from loop()

This, however, assumes that you don't have any blocking code elsewhere in the sketch

Can you describe more details, please? How can I create this blocking code? My while after pressing the button waits until all the conditions are met (i.e. when the receiver receives a radio signal), then pluses to counter 1 and again waits for the conditions to be met (the radio signal of the next button).
Earlier, I created code, which checks if the previous value is repeated with the next one (the values ​​will always be different), and it works fine, but it takes up quite a lot of board memory, which I do not have enough. Therefore, I decided that if I build my code with delays, it will be more economical.

I am short of time but something like this is what I had in mind

void jSondb()
{
  unsigned long recVal[18];
  static int a = 0;
  if (a < 18)
  {
    if (mySwitch.available())   //if any data from RF remote was received
    {
      if  (((millis() - btn1_code_rec_time) > no_repeat_delay))   //If the data was received within 100 milliseconds after the first one was received, ignore it.
      {
        btn1_code_rec_time = millis(); //record the time the button was pressed
        recVal[a] = mySwitch.getReceivedValue();
        doc["Buttons"][a] = recVal[a];
        a += 1; // readt to receive value for next button
        mySwitch.resetAvailable();
      }
    }
  }
  else
  {
    serializeJson(doc, eepromStream);
  }
}

Call the function each time through loop()

I got your idea, thank you. But I can't use loop(); for this purpose. Because this function will only be called when the condition is met.

void loop() {
  unsigned long start;
  if (mySwitch.available()) {
    start = mySwitch.getReceivedValue();
    if (start == 5957121) {
      delay(1000);
      mySwitch.resetAvailable();
      jSondb();
    }
  }
}

If you want to collect data from the function when the condition becomes true then set a boolean to true and call the function each time through loop() whilst the boolean is true. When the function has been called enough times have it set the boolean to false to stop it being called again

Note the difference between calling the function when the condition becomes true and calling it when the condition is true

It looks like a state machine using switch/case would be useful in your sketch

1 Like

Thank you for your suggestion, I got your idea. But I made my choice in favor of the repetition filtering logic, it looks like this:

void jSondb() {
  unsigned long recVal[19]; // [19] - index of recorded value
  int a = 0; // index counter
  while (a < 19) {
    if (mySwitch.available()) {
      if (a == 0) { //if we record first value
        recVal[a] = mySwitch.getReceivedValue(); // assign value to [a] index
        doc["Buttons"][a] = recVal[a]; //recocrd it to the json array
        Serial.println(recVal[a]); //service info
        a += 1; // next counter
      }
      else if (a >= 1 && recVal[a - 1] != mySwitch.getReceivedValue()) { // repetition filter, if the past value is equal to the current value, do not write to the array
        recVal[a] = mySwitch.getReceivedValue();
        doc["Buttons"][a] = recVal[a];
        Serial.println(recVal[a]);
        a += 1;
      }
      mySwitch.resetAvailable(); //clear buffer
    }
  }
  serializeJson(doc, eepromStream); //send json to eeprom
}

As for me, this logic is easier and clearer.

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.