Very indeterministic problem with VirtualWire and SLEEP_MODE_PWR_DOWN

Hello all,

I'm currently attempting to build a receiver that will run for hopefully over a year on three AA batteries. For that I am trying to put the MCU into the SLEEP_MODE_PWR_DOWN sleep mode where it only consumes 30uA or so. The sleep code is using the watchdog timer to wake up the device every few seconds for a few milliseconds.

During this wake time the MCU is supposed to read RF-transmitted using the VirtualWire library. However, this doesn't work reliably at all. In the current setup I have the digital output or the TX MCU directly connected to the RX MCU to eliminate any issues with the RF modules.

My plan was to have the following loop:

void loop()
{
  vw_rx_start(); // start receiving RF data
  if (vw_wait_rx_max(50))
  {
    if (vw_get_message(buf, &buflen))
    {
      if (buflen == 1)
      {
        if (buf[0] == MSG_ON)
        {
          Serial.println("On");
        }
        else
        {
          Serial.print("Invalid command");
        }
      }
      else
      {
        Serial.print("Invalid message: ");
      }
    }
    delay(2); // wait for completion of serial transmission
  }
  vw_rx_stop(); // we're done, stop receiving
  
  system_sleep(); // helper method based on sleep_mode()
}

Well, this didn't work reliably at all. On the transmitting side, I'm sending a MSG_ON command every ms (just on char). Here is a sample Serial output, about 25% of the commands are received:

Wake
Wake
On
Wake
On
Wake
Wake
Wake
On
Wake
On
Wake
Wake
Wake
Wake
On
Wake
On
Wake
Wake
Wake
On
Wake
On
Wake
Wake

I made various changes trying to identify the cause:

  1. Move vw_rx_start() into setup() and never call vw_rx_stop(). Result: Less missed commands, but still not reliable.
  2. Replace sleep.h-related code with a simple delay(2000) call but reverse vw_rx_start/stop() changes from point #1. Result: Every second (exactly every second) command is missed. Weird!
  3. Use delay(2000), move vw_rx_start() into setup() and never call vw_rx_stop(). Result: Finally, the code works flawlessly. Result: Not a single missed command.

Question: Has anybody used the VirtualWire library with SLEEP_MODE_PWR_DOWN and seen similar issues? Anybody knows a solution to this?

Thanks, Christoph

So you want to sync up a receiver listening
"every few seconds for a few milliseconds."
with a transmitter sending
"MSG_ON command every ms (just on char)"

Maybe make the MSG_ON command longer so the receiver power on time has a better chance of overlapping and getting a valid part of the message all the time.

I use a promini as an RF Remote, press a keypad button, it wakes up, reads the button, sends it, goes back into power down sleep mode.

The receiver however is running all the time, while you more or less do the opposite.

Hello CrossRoads,

I think you're on the right track. I finally had the flash of genius :~ to remove the 1ms delay in the transmitting code (more commands transmitted per ms), increase the transmission speed (more bits and bytes per ms) and increase the wait time (more bits arrive during wait period). The number of missed signals dropped significantly, and at 7000bps and 30ms wait time I didn't see a single missed signal anymore.

I also took a look at the VirtualWire code and yes, it seems it needs some time to figure out where the bits start and where the packets start so that it can return complete messages. I'm wondering whether the speed of "latching on" could be improved (coming from software development, this would be a nice algorithmic problem :-)).

Thanks,

Christoph

I don't know about improving. You're dealing with a reciever that may have
Tune on Time, Ton. Vcc 0ff- turn on: 25-30 ms
Gonna be tough to improve the software to deal with that.

Hmm, hadn't thought of that. Should be fairly easy to test without the VirtualWire library. Have the TX send a constant 1, and measure the time from turning on the RX until it delivers a 1, too. I'll report the results.