Author Topic: RFM69 Listen Mode? [discussion+code]  (Read 77642 times)

street

  • NewMember
  • *
  • Posts: 9
RFM69 Listen Mode? [discussion+code]
« on: December 08, 2014, 04:53:12 PM »
Hi,

I'm trying to design a receiver to listen on a persistent basis with battery power so I'm trying to reduce the power consumption of the Rx. The transmissions it will be designed to hear will be infrequent (a few times a day) and will not be on a timer basis - they will be triggered by unpredictable sensor conditions. It would be possible to adopt an Ack with Retry Tx regime to support periodic Rx listening.

The low power modes available for Arduino and ATMEGA328P boards are really attractive and power control for the RFM69 variants Tx is pretty easy. As far as I know, power saving in the Rx mode isn't easy/currently supported. The RFM69 datasheets talk about a Listen Mode for the Rx where the Rx goes into idle mode (very low power ~ few uA) and periodically wakes up into Rx Mode (16mA). If it receives a valid signal and various configurable conditions are met, it comes out of Listen Mode and you can crack on to receive the message.

I can see that the Listen Mode settings are in this Cosa library (https://github.com/mikaelpatel/Cosa/blob/master/cores/cosa/Cosa/Wireless/Driver/RFM69.hh) do you think this could be incorporated in the/an RFM69 library?
EDIT: I see that these registers and values are already covered in RFM69registers.h . How is this implemented in the other .h and .cpp files to give a Listen Mode as an Rx option?

I'm a novice when it comes to library writing and the RFM69 comms protocols. I'm happy to try and do as much of this as possible but I'd like some help getting started. I have read the Arduino libraries guide but I really need a bridge between the RFM library, protocols and the datasheets.

Any help or guidance will be gratefully received and I hope anything I can get to work could be of use to other people.

street
« Last Edit: February 04, 2015, 12:32:13 PM by Felix »

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: RFM69xx Listen Mode?
« Reply #1 on: December 08, 2014, 06:02:29 PM »
I have to ask: why do you need to constantly receive on a battery operated mote?

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69xx Listen Mode?
« Reply #2 on: December 08, 2014, 08:48:25 PM »
As far as I know, power saving in the Rx mode isn't easy/currently supported. The RFM69 datasheets talk about a Listen Mode for the Rx where the Rx goes into idle mode (very low power ~ few uA) and periodically wakes up into Rx Mode (16mA). If it receives a valid signal and various configurable conditions are met, it comes out of Listen Mode and you can crack on to receive the message.
There is a listen mode indeed. I have not implemented that mode since it will not really buy you much. I have repeated this many times: to receive ANYTHING you have to be AWAKE (RX mode). That means the whole radio RX end is operating and using power (about 15ma or so). There's no magic bullet to avoiding that. In no radio receiver on this earth.
The listen mode allows you to switch between sleep and RX quickly. That also means you are in SLEEP Nms, RX Mms, SLEEP Nms, RX Mms and so on, you choose your duty cycle. But ... you cannot receive when you are in SLEEP. There, I just repeated that again :)

So to save space in the library and such, I left that part out. You can always add it yourself OR better... just implement that mode with the existing functionality in a custom sketch. Like ... sleep for Nms, then wakeup and activate the radio RX ... listen for Mms, then repeat. Simple eh? It's the same thing.

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69xx Listen Mode?
« Reply #3 on: December 09, 2014, 11:44:36 AM »
@ TomWS, the Tx is attached to a  low power proximity sensor and the Rx is attached to a remote camera system which needs to be turned off most of the time. The proximity sensor is there to tell the Rx Arduino to power the camera system up and will also be used as a trigger for taking stills.

@Felix, thanks for your reply. I fully understand that no message can be received in idle or sleep mode, which is why I mentioned the Ack with Retry setting being useful. I appreciate that the library is more efficient without the listen function but I understand that in general it is more efficient to implement something like this in a library, rather than a sketch and the RFM69 series has good hardware support for this, which is why I'm hoping to do it. You say I can do it, which is encouraging. Please could someone give me a steer on how to go about implementing this?

Street.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69xx Listen Mode?
« Reply #4 on: December 09, 2014, 12:34:21 PM »
Like I said, it's pretty easy to do it in a sketch. If you want to implement an interface/add that functionality to the library, then a good place to start is the datasheet. There are some registers that need to be set, listen mode is described on page 39 of the DS: http://www.semtech.com/images/datasheet/sx1231h.pdf

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69xx Listen Mode?
« Reply #5 on: December 09, 2014, 12:45:39 PM »
Thanks, I have the datasheet - perhaps I just need to dive in and try something. One thing which is making me think I'll make a mistake is that the modes need to be changed from one to another in a particular sequence. Does  the library do this or is it handled in hardware once you set the registers?

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69xx Listen Mode?
« Reply #6 on: December 09, 2014, 03:19:37 PM »
The library doesn't do anything by itself, you have to make all the changes. The datasheet will mention if there is any sequence that needs to be followed or if the hardware will do anything automatically.

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: RFM69xx Listen Mode?
« Reply #7 on: December 09, 2014, 05:00:43 PM »
@ TomWS, the Tx is attached to a  low power proximity sensor and the Rx is attached to a remote camera system which needs to be turned off most of the time. The proximity sensor is there to tell the Rx Arduino to power the camera system up and will also be used as a trigger for taking stills.

<snip...>
Street.
Ok, thanks for the explanation.  So both TX & RX are battery powered.  What's the range between them?  And what kind of response time do you need on detecting movement and taking the snap?

Tom

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69xx Listen Mode?
« Reply #8 on: December 09, 2014, 06:29:23 PM »
@ Felix, thank you.

@ TomWS, I'm budgeting a second or two to get a very short message across, eg address of Tx and an "I've been triggered" flag. Perhaps a battery health indication of there's no degradation of performance. I realise there's probably a calculation which then indicates the idle/Rx duty cycle which can service those response times for a given data rate etc. Not sure how to approach that part yet. Given that the Tx is so infrequent, it doesn't matter if it sends several repeat messages to try and ensure that the idle/Rx duty is worth having and actually helps minimise Rx power consumption. My ideal range is 100m in the open or low density woodland. Thanks for your interest.

Street

TomWS

  • Hero Member
  • *****
  • Posts: 1930
Re: RFM69xx Listen Mode?
« Reply #9 on: December 09, 2014, 08:43:33 PM »
@ Felix, thank you.

@ TomWS, I'm budgeting a second or two to get a very short message across, eg address of Tx and an "I've been triggered" flag. Perhaps a battery health indication of there's no degradation of performance. I realise there's probably a calculation which then indicates the idle/Rx duty cycle which can service those response times for a given data rate etc. Not sure how to approach that part yet. Given that the Tx is so infrequent, it doesn't matter if it sends several repeat messages to try and ensure that the idle/Rx duty is worth having and actually helps minimise Rx power consumption. My ideal range is 100m in the open or low density woodland. Thanks for your interest.

Street
Assuming you have the same power source for your 'rx' and 'tx' sides.  The obvious answer is that it would be far better to have more false receive cycles than transmit cycles - the power difference being dramatically different between the two and I think that's the way you're leaning. 

So, given the response time you're willing to accept (1-2 seconds), it seems as if the receive interval would need to be less than your max response time (ie, you come out of sleep and listen for a very brief time and do this once a 1/2 second or so) and your tx cycle bursts until contact is made (ie, set a high retry count for send with retry) then you should have a good chance of triggering within your budgeted time - without  any changes to existing RFM69 library.

A listen window of around 40mS should 'catch' any device sending with retry (you might have to play with this somewhat).  At 16mA for Receive (in the RFM69HW) then 40mS on/460mS off would average to 800uA or, about 62 days running on AAA batteries...  Uh, how long do you want to leave this running without recharge/replacement of batteries???

Tom

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69xx Listen Mode?
« Reply #10 on: December 11, 2014, 10:27:52 AM »
That sounds great - thank you. Is there a particular sketch you recommend using as a test bed for this from the library examples? I was going to use the TxRxBlinky one if there isn't something obviously better.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 Listen Mode?
« Reply #11 on: December 11, 2014, 01:30:08 PM »
Hey guess what, I found some old stuff I experimented with for Listen Mode. I am just dumping here everything I got and it's up to you to figure it out and test it.
Basically there is a RFM69Ext library that you add in the same folder as RFM69.
Then there are 2 sketches, a listener and a sender. All in the ZIP file. I think it should give you a good head start as opposed to doing everything from scratch.
Please let us know how this goes.
Cheers

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69 Listen Mode?
« Reply #12 on: December 11, 2014, 05:56:29 PM »
 :) @Felix, that's really supportive, thank you. I shall probably take longer to come back with findings than most on this forum as I'm just starting out in this area of coding, but I hope my efforts will benefit others. I'll probably be back with questions before answers!

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 Listen Mode?
« Reply #13 on: December 11, 2014, 07:21:47 PM »
No problem, you're most welcome. I hope this works for you, do mind that the RFM library I developed that against has changed with some updates and bug fixes but it should work the same, it was a while ago.
The most important thing to understand is how the LIsten mode works, I think it's worth spending some time reading the datasheet, unce you get a good grasp of the radio, modes, packet engine and listen mode, then everything should come much easier. A lot of people want to do big things but they are not willing to do that hard homework.
In your case you're lucky and half of that is done :)

street

  • NewMember
  • *
  • Posts: 9
Re: RFM69 Listen Mode?
« Reply #14 on: December 28, 2014, 06:39:06 PM »
Hi, this may seem like slow progress but I have honestly had to go and find out what hexadecimal numbers are, what bitwise operators are and how they work etc, so you can imagine this isn't a quick process for me. I have got to looking at the RFM69Ext.cpp file and have noticed that in your interrupt handler you only switch to Standby mode if the radio was in Rx mode, not Listen mode. Please could you confirm if I have read this right and, if so, why you don't need to switch to Standby from Listen when the interrupt is called?

Thanks, street

Code: [Select]
void RFM69Ext::interruptHandler() {
  //pinMode(4, OUTPUT);
  //digitalWrite(4, 1);
  Serial.print("*");
  byte irq2 = readReg(REG_IRQFLAGS2);
  if ((_mode == RF69_MODE_RX || _mode == RF69_MODE_LISTEN) && (irq2 & RF_IRQFLAGS2_PAYLOADREADY))
  {
    byte isRX = _mode == RF69_MODE_RX;
    if (isRX)
      setMode(RF69_MODE_STANDBY);

    select();
    SPI.transfer(REG_FIFO & 0x7f);
    PAYLOADLEN = SPI.transfer(0);
    DATALEN = PAYLOADLEN - 3;
    PAYLOADLEN = PAYLOADLEN > 66 ? 66 : PAYLOADLEN; //precaution
    TARGETID = SPI.transfer(0);
    if(!(_promiscuousMode || TARGETID==_address || TARGETID==0)) //match this node's address, or broadcast addr 0x0 or anything in promiscuous mode
    {
      PAYLOADLEN = 0;
      unselect();
      //digitalWrite(4, 0);
      return;
    }
    SENDERID = SPI.transfer(0);
    byte CTLbyte = SPI.transfer(0);
   
    ACK_RECEIVED = CTLbyte & 0x80; //extract ACK-requested flag
    ACK_REQUESTED = CTLbyte & 0x40; //extract ACK-received flag
   
    for (byte i= 0; i < DATALEN; i++)
    {
      DATA[i] = SPI.transfer(0);
      Serial.print((char)DATA[i]);
    }
    Serial.println();
    unselect();
    if (isRX)
      setMode(RF69_MODE_RX);
  }

 
  Serial.print(_mode);
  Serial.print("*");
  Serial.print(irq2, HEX);
  Serial.print("*");
  //digitalWrite(4, 0);
}