Author Topic: How to speed up RFM69 data throughput on Moteino M0? [solved]  (Read 42021 times)

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
I am trying to stream data real time from a sensor on a rotating platform to a stationary receiving station using a Moteino M0 on each end, each with a RFM69HCW 915 Mhz module. 

It takes 13 ms for each sendWithRetry() to complete.  The payload for each packet is a 20 byte struct.  Ideally I would like to get 1000 packets through per second.  So I would like to reduce send time to more like 1 ms.  Is this possible?

Indeed, I tried using send() instead.  That only takes 7 ms which is a good improvement.  Is there any way to improve it further?  I'd prefer to use ACKs so speeding up sendWithRetry would be welcomed. 

Power draw does not matter.  The radios will only be a couple of meters apart.

Thanks!  -JD

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #1 on: March 23, 2020, 10:14:30 AM »
I would start by disabling encryption and maxing out the bitrate, there's some sample code in the OTA examples here:
https://github.com/LowPowerLab/RFM69/tree/master/Examples/WirelessProgramming_OTA

Also you could try bumping up the SPI clock (up to 10mhz is max RFM69/SX1231 supports per DS), but the gains there would likely be marginal.

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #2 on: March 23, 2020, 01:52:59 PM »
Nice, Felix!  From your Target.ino, I did this to both the remote and local sides:

Added this to the global section:
Code: [Select]
#define BR_300KBPS             //run radio at max rate of 300kbps!
Added this to Setup():
Code: [Select]
  #ifdef BR_300KBPS
  radio.writeReg(0x03, 0x00);  //REG_BITRATEMSB: 300kbps (0x006B, see DS p20)
  radio.writeReg(0x04, 0x6B);  //REG_BITRATELSB: 300kbps (0x006B, see DS p20)
  radio.writeReg(0x19, 0x40);  //REG_RXBW: 500kHz
  radio.writeReg(0x1A, 0x80);  //REG_AFCBW: 500kHz
  radio.writeReg(0x05, 0x13);  //REG_FDEVMSB: 300khz (0x1333)
  radio.writeReg(0x06, 0x33);  //REG_FDEVLSB: 300khz (0x1333)
  radio.writeReg(0x29, 240);   //set REG_RSSITHRESH to -120dBm
  #endif
On the remote (sending) side, in loop(), I had already changed:
Code: [Select]
if (radio.sendWithRetry(GATEWAYID, (const void*)(&RFDataPktToSend), sizeof(RFDataPktToSend))) ...
to:
Code: [Select]
      radio.send(GATEWAYID, (const void*)(&RFDataPktToSend), sizeof(RFDataPktToSend));
These measures reduced the time to complete sending from 13 ms (with acks) to 7 ms (without acks) to 3 or 4 ms with bit rate changes.  Good!

Then on both sides, I commented out encryption like this:
Code: [Select]
  //radio.encrypt(ENCRYPTKEY);
That further reduced send time (averaged over 10 sends) to 1.8 to 2.4 ms.  Better! 

On the local side I now see about 4 ms between updates.  Some of that is me.  On the remote side SPI is being used not just to talk to the radio but to collect data from the accelerometer, the latter of which is taking about 2 ms.  So I am hopeful that will make a difference too.  I'll report back once I speed up SPI.

This was easier than I thought it would be.  The future is looking bright!  Thanks!  -JD

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #3 on: March 23, 2020, 02:55:52 PM »
It is also pretty easy to speed up the SPI functions quite a lot.  Felix's library caches and then restores SPI settings before/after every SPI write which takes extra time.  If you only have the radio using the SPI bus, there is no need to thrash settings.  See my work here: https://lowpowerlab.com/forum/low-power-techniques/speeding-up-the-rfm69-library/

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #4 on: March 23, 2020, 03:01:45 PM »
Very good point ChemE, I remember fiddling with that a while ago and forgot this detail.
Definitely removing the arduino SPI session stuff should help in a significant way.
The current SPI clock is at 4Mhz I think. The limiting factor for the clock itself is the RFM69/SX1231h chip 10mhz).

Looking forward to see how fast the M0 can make it go  :)

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #5 on: March 23, 2020, 04:56:20 PM »
Hmmm... I also have an accelerometer on the SPI bus.  Would I do better to move it to I2C then remove the caching from SPI?   The LIS3DH accelerometer board can do either SPI or I2C.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #6 on: March 23, 2020, 06:09:03 PM »
Depends how often you need updates from the accel. I2c is much slower, even at 1mhz.
I would use another SPI perhaps but you're still tying up the MCU to do the reads so I don't think in your case that is of advantage.

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #7 on: March 23, 2020, 08:19:19 PM »
When going fast I need the updates from the accel at the same rate I need to transmit them over the RF link.  But they won't be asked to happen simultaneously.  I read the accel then send the data out the radio.  When the send is done, I repeat.  Does this mean I could get away with removing the SPI caching for the radio sends while continuing to use SPI for the accel?

I will just try upping the SPI clock rate first.  Thanks!  -JD

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #8 on: March 23, 2020, 09:11:52 PM »
I2C is slow as Christmas no matter what you do (believe me, I tried hard).  SPI comparatively is blazing fast.  If you are motivated by refresh rate, you should endeavor to keep everything 10MHz SPI and pare that code aggressively.  If you want to go find a clock cycle to take back, find it on the SPI bus and you'll get it many thousands of times just through repetition.

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #9 on: March 23, 2020, 11:15:33 PM »
Okay, I give up.  How do I change the SPI clock speed?

In RFM69.cpp I tried this:
Code: [Select]
#ifdef SPI_HAS_TRANSACTION
  //_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);
  _settings = SPISettings(10000000, MSBFIRST, SPI_MODE0); // JD - attempting to speed up spi clock
#endif
and saw no difference in the radio send time.  Reading it with a scope now, it was 1.93 ms before and after the above change.  Do I just change it, save the file, recompile my code in the IDE then upload it to the Moteino M0?  Or is there some intermediate step to recompile the library or something?

Thanks.  -JD

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #10 on: March 24, 2020, 06:27:56 PM »
When I scope SPI SCK, I see a 1 Mhz square wave regardless of what I put in SPISettings() in RFM69.cpp.  (Should it be this low?  I was expecting 4 MHz.)  So I tried changing SPI.setClockDivider(SPI_CLOCK_DIV16) to SPI.setClockDivider(SPI_CLOCK_DIV2).  Bingo, the clock signal frequency is now 8.02 MHz.  But, since Felix suggested I make it 10 MHz, how do I do that?

This reduced my accelerometer reads from about 165 µs to 82 µs, and my radio sends from 1.93 ms to 1.50 ms.  Now my throughput is 318 Hz.  Even better.

Though it is time for me to work on reducing my time spent processing data and sending it out USB, I would still like to see if I can get the send time down further.  But I have no idea what to do to get rid of the SPI caching (thrashing?) that you mentioned, ChemE.  In the thread you pointed me to, it looks like maybe you rewrote the entire library?  The code in these libraries is a bit over my head.  Is there a relatively simple change I could make to remove the SPI settings "thrashing"?

This is exciting stuff!  I am very pleased to have made this much progress so quickly and simply.  -JD

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #11 on: March 24, 2020, 09:42:57 PM »
To get 10mhz you will need to change the way that the SAMD core splits the main clock to assign a clock to the SPI peripheral, mucky work, I would not bother unless you think that extra 2mhz will really make an important difference, IMO 8mhz is plenty.

I will add to the discussion that if you're looking to stream data as fast as possible, the transitions between radio modes are time expensive. If you can stay in TX mode that will save significant time. But this gets you into gutting away lots of code from the library and putting it in custom functions that just do the streaming. Sorry I don't have an example to publish and this would be highly experimental but doable with significant effort and lots of radio packets timings analysis (CurrentRanger + scope very useful in such scenario!).

jdheinzmann

  • NewMember
  • *
  • Posts: 40
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #12 on: March 26, 2020, 11:16:01 AM »
I agree, Felix, 8 MHz is plenty and another 2 Mhz would make little further difference.  I am curious though, why you originally expected I would find the clock running at 4 Mhz.

Indeed, I only need the remote system to transmit, never receive.  But I am in no position to try to muck around for that.  I would think I am not the only person who would find a transmit-only library useful though.  Remote streaming sensors can be quite handy in a number of data acquisition situations.

Though this is probably as solved as you can help me make it for now, I will wait a little before I declare this completely solved as I want to see how I can further speed things up by streamlining the rest of my code.  I will post my results here.

For example, cutting out some processing on the local receiving side cut the time spent in the loop in half.  However, that had no effect on throughput because the remote transmitting side appears to what is pacing the transfers.


Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #13 on: March 26, 2020, 01:31:16 PM »
I am curious though, why you originally expected I would find the clock running at 4 Mhz.
Just an overlook, the AVR SPI clock was set to 4mhz, I replied without looking at the code.

ChemE

  • Sr. Member
  • ****
  • Posts: 419
  • Country: us
Re: Best way to speed up RFM69HCW data throughput on Moteino M0?
« Reply #14 on: March 26, 2020, 04:39:40 PM »
...I would still like to see if I can get the send time down further.  But I have no idea what to do to get rid of the SPI caching (thrashing?) that you mentioned, ChemE.  In the thread you pointed me to, it looks like maybe you rewrote the entire library?  The code in these libraries is a bit over my head.  Is there a relatively simple change I could make to remove the SPI settings "thrashing"?...

Yes, it took me a while but I had fun (mostly).  That is exactly what I did; I rolled my own by distilling others' work down rather than building up from the datasheets.  I don't have any SAMD21 uCs so I'm at a loss for how portable the code I wrote is.