0
\$\begingroup\$

I'm trying to build a remotely-controlled switch using Atmega328p.

For radio communication, I've chosen a generic RF433 transmitter/receiver combo, just like in this tutorial: https://randomnerdtutorials.com/rf-433mhz-transmitter-receiver-module-with-arduino/

The receiver is battery-operated, so power consumption is really important.
My plan was to power a receiver from a digital pin and give it power every second, see if any data is coming through for 20ms and either read it if there is any data or power it down for the next second.

The transmitter would send the same message in a loop for 2 seconds so the receiver would be able to 'catch' it between sleep cycles.

My problem is that it seems like it takes a while for the receiver to "wake up" and start reading the data.
Her is my code:

#include <Arduino.h>
#include <Servo.h>
// uncomment #define RH_ASK_ARDUINO_USE_TIMER2" in RH_ASK.cpp
#include <RH_ASK.h>
#include <SPI.h>

Servo servo;
RH_ASK rf_driver;

int NEUTRAL_POSITION = 57;
int POWER_PIN = 5; // VCC of RF433 is connected to this pin

void setup() {
  servo.attach(9);
  pinMode(POWER_PIN, OUTPUT);
  digitalWrite(POWER_PIN, LOW);
  rf_driver.init();
  Serial.begin(9600); 
}

void on() {
  servo.write(137);
  delay(500);
  servo.write(NEUTRAL_POSITION);
  delay(500);
}

void off() {
  servo.write(10);
  delay(500);
  servo.write(NEUTRAL_POSITION);
  delay(500);
}

uint8_t buf[1];
uint8_t buflen = sizeof(buf);

void loop() {

  digitalWrite(POWER_PIN, HIGH);
  long start = millis();
  
  bool isAvailable = rf_driver.waitAvailableTimeout(700);
  long waited = millis() - start;
  
  Serial.print("isAvailable: ");
  Serial.print(isAvailable);
  Serial.print(", waited");
  Serial.println(waited);
  if(rf_driver.recv(buf, &buflen)) {

    int command = atoi((const char*) buf);

    Serial.println(command);
    if (command == 0) {
      off();
      delay(500);
    } else if (command == 1) {
      on();
      delay(500);
    }
  }

  digitalWrite(POWER_PIN, LOW);
  delay(1000);

}

I'm using RadioHead library for RF433 communication.

When the data is being transmitted it takes about 600ms for the receiver to be able to detect that, hence the 700ms timeout:

rf_driver.waitAvailableTimeout(700);

Here is the transmitter code:

#include <Arduino.h>
// uncomment #define RH_ASK_ARDUINO_USE_TIMER2" in RH_ASK.cpp
#include <RH_ASK.h>
#include <SPI.h>

RH_ASK rf_driver;

void setup() {
  Serial.begin(9600);
  Serial.println("starting");
  rf_driver.init();  
  pinMode(LED_BUILTIN, OUTPUT);
}

uint8_t on[] = {"1"};
uint8_t off[] = {"0"};

void sendOn() {
  digitalWrite(LED_BUILTIN, HIGH);
  unsigned long end = millis() + 2000;
  while(millis() < end) {
    rf_driver.send(on, sizeof(on));
    rf_driver.waitPacketSent();
    delay(30);
  }

  digitalWrite(LED_BUILTIN, LOW);
}

void sendOff() {
  digitalWrite(LED_BUILTIN, LOW);
  unsigned long end = millis() + 2000;
  while(millis() < end) {
    rf_driver.send(off, sizeof(off));
    rf_driver.waitPacketSent();
    delay(30);
  }
}

void loop() {
  if (Serial.available() > 0) {
    
    String command = Serial.readStringUntil(';');

    if (command.equals("on")) {
      Serial.println("Sending on");
      sendOn();
    } else if (command.equals("off")) {
      Serial.println("Sending off");
      sendOff();
    } else {
      Serial.print("Unrecognized command: '");
      Serial.print(command);
      Serial.println("'");
    }
  }
}

Obviously this is far from the original idea of sleeping most of the time and just wake up for a quick 20ms check.

Is it the correct approach to build this kind of system?
Should it really take 600ms for RF433 to get up-and-running and detect that there is data being transmitted?
Is there maybe a different RF/BLE module to achieve this kind of sleep/check-for-data pattern?

\$\endgroup\$
  • \$\begingroup\$ Those are truly horrible radios. Even if you want to use 433 OOK, consider one of the SPI-based digital radios from TI or SiLabs, especially if you want to briefly poll things and then go back to sleep. Note also that a long transmission may violate regulatory limits, at least depending on which rule option you are trying to meet. \$\endgroup\$ – Chris Stratton Jul 30 at 3:25
  • \$\begingroup\$ You are powering from a digital pin ? How much current can the pin supply ? Is the module intended to be used that way ? If the module draws too much current from the pin at startup, the voltage may drop and affect the time to stabilise. Have checked if the 600ms figure will hold good if the module was powered by a proper supply instead of a pin kept high ? \$\endgroup\$ – AJN Jul 30 at 6:06
  • \$\begingroup\$ "turn ON time from VCC off" for a 433 MHz module from its data sheet is mentioned as 25ms (typical). What is the expected value for your module? I couldn't find a data sheet from your links. A data sheet mentions that it will draw 4mA (quiscent). How much can you digital pin supply ? \$\endgroup\$ – AJN Jul 30 at 6:12
  • \$\begingroup\$ "When the data is being transmitted it takes about 600ms for the receiver to be able to detect that". How was this measured? Using an oscilloscope or by trial and error with the Arduino ? \$\endgroup\$ – AJN Jul 30 at 6:12
  • \$\begingroup\$ I've used 434 MHz receivers that were up and running well within 10 ms. It was an FM system if that's any help and came from a company called Radiometrix. \$\endgroup\$ – Andy aka Jul 30 at 8:29

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Browse other questions tagged or ask your own question.