The Dark Side of rf12_sendWait(2)

Around 18 months ago, I noticed that the energy level in my Mk2 related sketches was being upset by RF transmissions, but have never understood the reason.  I have recently found that the Jeelib function, rf12_sendWait(2) is a blocking function which causes the main processor to freeze for 2 mS.

To investigate this effect, I created a version of my RawSamplesTool (as attached) which runs on the emonTx V3 and shows this interruption clearly.  A single RF message is transmitted at the mid point of the selected mains cycle when data is being collected.  

The rf12_sendWait(2) line is a part of the standard send_rf_data() function which appears in many of the standard OEM sketches: 

void send_rf_data()
{
  rf12_sleep(RF12_WAKEUP);
  // if ready to send + exit route if it gets stuck 
  int i = 0; 
  while (!rf12_canSend() && i<10)
  { 
    rf12_recvDone(); 
    i++;
  }
  rf12_sendStart(0, &tx_data, sizeof tx_data);
  rf12_sendWait(2);
  rf12_sleep(RF12_SLEEP);
}

With this call in place, the 2 ms gap in the sampling process is clear to see:

2

1

0

No of cycles recorded = 1

cycleCount 252,  samplesRecorded 38

2                                      1v                                       |

2                                      1.   v                                   |

2                                      1.      v                                |

2                                      1.         v                             |

2                                      1.            v                          |

2                                      1.              v                        |

2                                      1.                 v                     |

2                                      1.                   v                   |

2                                      1.                      v                |

2                                      1.                         v             |

2                                      1.                           v           |

2                                      1.                            v          |

2                                      1.                            v          |

2                                      1.                             v         |

2                                      1.                             v         |

2                                      1.                             v         |

2                                      1.                             v         |

2                                      1.                            v          |

2                                      1.                          v            |

2                                      1.                       v               |

2                                      1.                    v                  |

2                                      1.                v                      |

2                                      1.             v                         |

2                                      1.         v                             |

2                                      1.     v                                 |

2                                      1.  v                                    |

2                                      1.                                       |

2       v                              1.                                       |

2       v                              1.                                       |

2         v                            1.                                       |

2            v                         1.                                       |

2               v                      1.                                       |

2                  v                   1.                                       |

2                     v                1.                                       |

2                         v            1.                                       |

2                             v        1.                                       |

2                                v     1.                                       |

2                                    v 1.                                       |

min_V 110,  max_V 902

 

The rf12_sendWait(2) routine is however doing its job because the test payload that I'm sending is being correctly received at the far end of the RF-link:

 

transmission lost!

transmission lost!

101,  102,  103,  104,  105,  106

transmission lost!

transmission lost!

 

If I comment out the rf12_sendWait(2) statement, the sampling scheme then looks fine at the critical point:

 

2                                      1.       v                               |

2                                      1.   v                                   |

2                                      1.v                                      |

2                                     v1.                                       |

2                                 v    1.                                       |

2                             v        1.                                       |

 

but no RF data is seen at the far end.  This is presumably because the RFM12B is being instructed to sleep before being able to send the data.

An alternative way to send the RF chip to sleep at a suitable later occasion was required.   To implement this, I decided to:

- create a new global flag, boolean RFM12_isActive;

- whenever an RF message is sent,

    set this flag to true instead of the rf12_sendWait() and rf12_sleep() commands;

- check this flag at the start of every mains cycle.  If it's true

    send the RF chip to sleep and clear the flag, otherwise do nothing;

With this mechanism in place, the sampling process looks fine:

 

2                                      1.                      v                |

2                                      1.                   v                   |

2                                      1.               v                       |

2                                      1.           v                           |

2                                      1.        v                              |

2                                      1.    v                                  |

2                                      1. v                                     |

2                                     v1.                                       |

2                                  v   1.                                       |

2                               v      1.                                       |

2                            v         1.                                       |

2                         v            1.                                       |

2                      v               1.                                       |

2                   v                  1.                                       |

and the received RF data is good too :)

transmission lost!

transmission lost!

101,  102,  103,  104,  105,  106

transmission lost!

transmission lost!

* * *

For any RF-enabled code that monitors continuously, including all such sketches that I have ever posted, the above solution would appear to be a satisfactory workaround.  For code that doesn't need to continue monitoring after an RF message is sent, a short break in the proceedings is presumably not a problem.

In due course, I hope to issue upgrades to my Mk2i rev5 and rev6 lines which will include this change.  Rev5 allows an additional load to be controlled by RF; Rev6 supports datalogging by RF.  My "continuous monitoring" code for the emonTx V3 (on Github) could also benefit from a similar upgrade.

For each of these code lines, the quality of the energy measurements can only be improved by not having 2 mS gaps in their data gathering processes.  The overall effect of these interruption is not, however, very great.  If RF transmissions are occurring once per second, a 2mS gap on each occasion would only comprise a 0.2% loss of energy data.

 

JBecker's picture

Re: The Dark Side of rf12_sendWait(2)

Hi Robin,

the workaround you created seems to be a very good solution.

In fact, whenever the RFM12B routines are not used in a battery powered unit, it should be possible to remove the calls to rf12_sendWait() and rf12_sleep() completely (and in a 'continuously' running sketch only rf12_sleep() will have a noticeable effect at all). 

rf12_sendWait puts the AVR into one of the low power modes for the time between issuing the rf12_sendStart() command and (transmit) interrupts coming in. In a continuously running sketch this is a bit overkill (and using mode 2 as in rf12_sendWait(2) can principally loose ticks of the millisecond timer as the documentation specifies. Mode 0 or 1 should be safe here). 

rf12_sleep() is only needed to put the RFM12B into one of its low power modes. It will go into RF_IDLE_MODE automatically after a successful transmission. Only if you want it to use even less power in the RF_WAKEUP or RF_SLEEP modes it is  necessary to call rf12_sleep().

Hope this is 100% correct. Any of the RFM12B experts disagree?

BR, Jörg.

 

 

calypso_rae's picture

Re: The Dark Side of rf12_sendWait(2)

Thanks for that insight Jörg. 

Given that my applications are always mains powered, it may be better for the RF module to spend most of its time in idle mode rather than being forcing into a lower power state.

<whispers>  I think our RFM12B experts must all be asleep ...

JBecker's picture

Re: The Dark Side of rf12_sendWait(2)

:-)

I was asking for the experts advice because there are so many 'side-effects' in this driver that it is better to look at these things with more than two eyes (and one 50+ year old brain).

 

calypso_rae's picture

Re: The Dark Side of rf12_sendWait(2)

... (and one 50+ year old brain).

Make that two!

CidiRome's picture

Re: The Dark Side of rf12_sendWait(2)

Hi.

Today I'm detecting this one problem in my sketches, let's see if I can apply this solution to my code.

Thank you!

Cheers 

Comment viewing options

Select your preferred way to display the comments and click "Save settings" to activate your changes.