RFM69W (RFM69HW) transceiver + T3

Status
Not open for further replies.
It would help users if there was some sort of guidance document on such things as when/why MUTEX by any means is needed. Can be a huge time-waster as the bugs cause obscure symptoms.
 
Would it run more reliably if I put the RFM69 radio to sleep while sending/receiving messages over Ethernet?
Don't need to sleep the radio, just ensure it's in the idle state before using the SPI for Ethernet. This is a paradox if you need the receiver on most of the time.
 
But for the initial RFMxx radios and Wiznet and maybe SD card - I'd suggest getting it all going with a big polling loop

A big polling loop? Wouldn't that imply that I would not use interrupts? What if I modified the RFM library to use a soft SPI library, and use different pins for SPI? That seems like the easiest solution that would completely avoid conflict.

Seems like checking for idle before using Ethernet wouldn't work, because the RF transceiver might receive a transmission before finishing the Ethernet transmissions.

How does the Wiznet and SD work together? They come on the same Ethernet Shield and use the same SPI port, I would assume the libraries address the potential conflict between these two devices.

Eric
 
Polling loop... have to do that if you don't have an event driven task scheduler (RTOS).
The radio can still interrupt, as it does now, and save interrupt cause status and change radio to idle state if appropriate to do so. (in the case of an interrupt due to transmit FIFO error, it will restart the transmission, etc.)
For the radio, the polling calls the available() method in the class. This will return true due to an interrupt from the radio. If true, next you call recv() to copy the data from the ISR's buffer to yours. This done, before you analyze the received data, you may wish to elect to start another receive state.

WizNet - some drivers for Arduino don't use interrupts. Some do. Some hog the CPU. All these things have to have a way to get ownership of the SPI port for their work, and do so in a mutual exclusion way.

A receive interrupt from the radio has to be handled, dismissed then the non-ISR level code needs to get the data copied out before new data arrives and would cause a FIFO overrun. In my code, I added double-buffered receive to the RF22 to prevent this.

The ethernet and radio can be active, waiting for received data. When either gets an interrupt, it will use the SPI port. It will then set a flag that the application must check later in a polling loop, to know that data is available to be read. (one doesn't do a slow data copy in an ISR). At this point, the non-ISR code needs to OWN the SPI port and now this includes preventing ISRs from using it.

Then there's the situation where there's a read pending on the radio or ethernet and the app decides to transmit. Now, the app needs to own the SPI port for a while.

The above are examples of a non-RTOS/non-scheduler method as would happen with single-minded Arduino code. Perhaps the SD card code is the worst, since it has to own the SPI interface so much of the time. Ideally, something like an SD card used a lot would go on a separate hardware SPI port.

Careful selection of the right driver strategy is needed. It is doable, but not with the existing simple-minded libraries for these devices.
 
Last edited:
What if I modified the RFM library to use a soft SPI library, and use different pins for SPI? That seems like the easiest solution that would completely avoid conflict.

With the simple way things are designed today, that probably is the easiest way.

Adafruit actually designs most of their SPI-based libraries to have 2 constructors, one for hardware SPI and the other for slower bit-bashing. Their main motivation for the bit-bashing is probably shield compatibility, so the shields they sell can at least work (slowly) when people buy them and plug them into Arduino's other non-Uno boards. But having a bit-bashing fallback can also solve this type of software compatibility issue.


How does the Wiznet and SD work together? They come on the same Ethernet Shield and use the same SPI port, I would assume the libraries address the potential conflict between these two devices.

Neither uses interrupts.

When you call the available(), read() and write() functions, SPI transactions are performed and completed. For a single-threaded program, only one function can be called at a time, so there's no possibility for conflicts.

Well, no conflicts when used with each other and other non-interrupt SPI libraries. As soon as you throw a library using SPI from interrupts into the mix, conflicts can happen.

Long-term, I do want to solve this well on Teensy3, so these types of things "just work" when used together. But it's not simple. I know that doesn't help you right now, but at least this pain you're suffering has prompted the discussion about a long-term solution.
 
The RF22 library concept is that an interrupt from the radio (nIRQ) occurs when a valid preamble is detected then again when the receiver FIFO is almost full. The FIFO size is smaller than the max message length which is #ifdef defined at 50 or 255 bytes. When there's an error (FIFO overflow, CRC error, Invalid preamble) there's also an interrupt. So the software SPI has to be aware of these things. The interrupt pin defaults to 0, and no other devices interrupt on that pin, so it shouldn't be an issue.

On the transmit side, there's an interrupt when the FIFO is almost empty (needs refilling) and when empty / end of transmission.

There's also the clear channel assessment (CCA) interrupt - here, the receiver looks for RSSI > x, for some period of time. If a signal is present, there's an interrupt to be processed saying channel is occupied. Disable receiver, wait, try later. CCA can be disabled, at the risk of collisions, from both your own nodes, and transmissions of other devices.

It's imperative that an SPI transaction, softSPI or hardware SPI, not occur in the non-ISR level while the radio device is in a state that may yield an interrupt. For example, to read the RSSI or status register, from not within the ISR, you need to disable all (or just the radio's) interrupts, do the SPI read, reenable interrupts. I did this by just not doing SPI transactions with an active receive or transmit. To force a state change to disable the receiver, you have to disable interrupts.

If you don't do these things correctly, you'll have one of those systems that hangs every 2nd thursday.

The K20 in T3 has but one SPI port?
 
Last edited:
Thanks for all the help Steve and Paul. Something that "just works" would be wonderful. I don't have much experience with ISRs and microcontroller programming. My experience is mostly with application programming. I am experienced with multi-threading programming in a windows or linux environment, but not without an OS.

I will attempt the easiest work-around for now, and can revisit this later if needed. Dropping messages from the sensor nodes is not a problem if it doesn't happen to frequently. They get resent every minute, and the measurements change very little minute to minute. The Ethernet transmissions are all initiated from the Teensy 3.1. Each ethernet transmission will be followed by a response from the server. Before sending & receiving using Ethernet, I will check if the RFM is idle, and if so, disable interrupts for the RFM69. If not idle, I will skip the Ethernet sending/receiving, and check again next time the loop() function is called.

This approach would require no changes to any libraries. The other options are more than I have time to implement, or to study and understand at this time.
 
Last edited:
Mike's RF22 library has software SPI built in. There's 2 examples, rf22_client_softwarespi and rf22_server_softwarespi. The library appears to be designed so you can just use that alternate software SPI constructor and everything in the library will automatically use it.

If you can spare the extra pins, I'd go with the software SPI approach. It should work together nicely with Ethernet, so long as the pins are all separate.
 
I didn't see the post on RadioHead until after I posted the last message. If it supports RFM69 on the Teensy 3.1 using software SPI, then that sounds like the way to go. I'm not using the RF22, as I already purchased the RFM69 modules and Moteino's. The Moteino's come in RF12 and RFM69 versions. I will be using a 3.3v power supply, so the 100mA limit on the 3.3V pin is not an issue.
 
Suggest using Mike's new library - new names but same as RF22 lib. Now called RadioHead lib. Added support for RF69 thus the name change. Download of lib has examples ready to run.
I'm testing this new lib with Teensy 3 now, using my test program previously done for the RF22.
Ordered some RF69 modules. From http://www.anarduino.com/miniwireless/
I'm not interested in their mini modules that have radio and AVR on same board. Radio is a sub-module.

overview of new lib with what radios it supports
http://www.airspayce.com/mikem/arduino/RadioHead/index.html
 
those are 915mhz. No. America only.
It's OK.
we've been using the 433Mhz version. Same chip, different antenna matching L/C.
A bit better range in the lower freq.
I use mine at 469 MHz, a ham radio band where I'm legal.
 
Last edited:
No, any band will do. Desktop testing of 2+ units.
Be mindful that choice of data rate, modulation mode, etc., will affect the duration of data frames and thus software timing and interrupt rates.
But this is second order.
 
I'm testing the Teensy 3.1 with the Hope RFM69HW, and it is hanging on radio.initialize();

I'm using the LowPowerLabs RFM69HW driver https://github.com/LowPowerLab/RFM69 and I'm trying to run the Node example.

I have the RFM69HW connected the same as on the Moteino R4, http://lowpowerlab.com/moteino/#designfiles, with the exception of Data0 (IRQ) which is connected to connected to D0 rather than D2.

RFM69HW.....Teensy 3.1
NSS.........D10
SCK.........D13
MISO........D12
MOSI........D11
Data0.......D0


3.3V is connected to a regulated 3.3V supply

I verified all the connections with an ohm meter. Is there anything I'm overlooking?

Thanks in advance,
Eric

01c03899fdb9befea32b26238eef968f24d6223601.jpg
 
I commented outSPI.setDataMode(SPI_MODE0) in RFM69::initialize(), and now the radio initializes successfully!

Seems like this call is not compatible with the Teensy 3.1. Is this the case?

It's not needed in most cases since the default is Mode 0, and most devices use Mode 0.
 
You're using the software from Low Power lab, right? I have not. I've used only the RF22 library with the RFM22. And I'm struggling to get its replacement, RadioHead to work.
The wiring you have looks correct. But I can't see in the photo that the RFM69 is oriented correctly - probably OK, not 180 out.
The RFM69 is quite a bit different than the RFM22, in how the pins are used.
No doubt you have the GND for the teensy and RFM69 and external 3.3V power all joined.

Your setDataMode() fault is the same place I'm hung up with in RadioHead. The first access to the SPCR causes a trap - like the ARM says there's nothing enabled for that I/O mapped address. The Teensy 3 SPI emulation code (as I speak of in my other thread on this), works OK with the RF22 lib. But with RadioHead and perhaps the LowPowerLabs driver, there's a missing call somewhere to initialize the SPI hardware in the Teensy 3 before accessing the SPI registers as in setDataMode(). I've studied this avr_emulation.h code for a long time, and how its constructors are supposed to init the ARM hardware. But haven't figured it out yet. There are essentially no comments in the code which makes it hard.

Need to get Paul to help a bit.. with an explanation of how this is supposed to work, since the avr_emulation.h plus teensyduino SPI.h code isn't self-evident (to me).
It's odd that yours doesn't work, as it would be the same as the RF22 library which does work.

Well, that's all I can say for now.
 
Last edited:
Steve, I did have everything wired correctly, as it is now working. It's only the call to SPI.setDataMode(MODE0) that does not work.

I'm using the Low Power Lab library for now. I look forward to testing RadioHead with the RFM69 on Teensy 3.1 once it is working.

Eric
 
That inspired me, in my RadioHead testing! I skipped that call to setDataMode() in SPI.cpp. That's where I had been working.. where that function's use of SPCR = leads to a trap/exception in hardware, from the code in avr_emulation.h for the SPCR = operator overload is the culprit.
I'm looking in the RF22 library to see if it simply didn't use SPCR = or didn't use that data mode bit.
 
I commented outSPI.setDataMode(SPI_MODE0) in RFM69::initialize(), and now the radio initializes successfully!

Seems like this call is not compatible with the Teensy 3.1. Is this the case?

It's not needed in most cases since the default is Mode 0, and most devices use Mode 0.

Yeah, I noticed that, too (see page 1 of this thread). Not sure why, but it did finally work after that.

David
 
Status
Not open for further replies.
Back
Top