RFM69W (RFM69HW) transceiver + T3

Status
Not open for further replies.
Hello,
Sorry for bringing up an old thread - but why was it necessary to comment out the SPI.setDataMode line? And to add the pinMode() line?

SPI.setDataMode()
was commented out due to a bug in Teensyduino's AVR emulation code for SPI. It was corrected in late May, 2014 as I recall. I suppose the correction is in release 1.19.
The pinMode(), I think, is to reestablish a pin mode that is undone by SPI initialization - if I recall correctly.

The RadioHead library is the best approach.
 
Hello,

I hope it is ok to post into this old thread, but I think it matches.

I've tried to connect a RFM69 Module to the teensy 3.1 using the lowpowerlab.com library
Here are the changes in the library I made (inspired by #67)
In RFM69.cpp inserted at line 93 after the SPI.begin();
Code:
pinMode( _interruptPin, INPUT);
I've commented out the SPI settings, because as far as i understand the teensy spi implementation, the default values should match. So the relevant code in RFM69.cpp is here:
Code:
// select the transceiver
void RFM69::select() {
  noInterrupts();
  // save current SPI settings
  _SPCR = SPCR;
  _SPSR = SPSR;
  // set RFM69 SPI settings
  //SPI.setDataMode(SPI_MODE0);
  //SPI.setBitOrder(MSBFIRST);
  //SPI.setClockDivider(SPI_CLOCK_DIV4); // decided to slow down from DIV2 after SPI stalling in some instances, especially visible on mega1284p when RFM69 and FLASH chip both present
  digitalWrite(_slaveSelectPin, LOW);
}

[/CODE]
And in the RFM69.h fix the Pins (the interrupt pin of the rfm module is connected to teensy's pin 0)
Code:
#define RF69_IRQ_PIN          0
#define RF69_IRQ_NUM          0

Finally, here the sketch:
Code:
#include <RFM69.h>    //get it here: https://www.github.com/lowpowerlab/rfm69
#include <SPI.h>

//Radionetwork specific settings
#define NODEID        1    //unique for each node on same network
#define NETWORKID     100  //the same on all nodes that talk to each other
#define FREQUENCY     RF69_433MHZ
#define ENCRYPTKEY    "sampleEncryptKey" //exactly the same 16 characters/bytes on all nodes!
#define ACK_TIME      30 // max # of ms to wait for an ack

#define SERIAL_BAUD   57600

RFM69 radio; //The RF69 Module

typedef struct {
  char key[15];
  char value[40];
} Payload;
Payload theData;

void setup() {
  Serial.begin(SERIAL_BAUD);
  
  delay(10);

  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(false);
}

int now = millis();
int sendTime = now;

void loop() {
  
  now = millis();
  
  if(sendTime + 1000 < now) {
    Serial.println("Pulse, I'm still alive");
    sendTime = now;  
  }
  

  if(radio.receiveDone()) {
    uint8_t senderId = radio.SENDERID;
    
    if(radio.ACKRequested()) {
      radio.sendACK();
    }
    
    theData = *(Payload*)radio.DATA;
    
    Serial.print(senderId);
    Serial.print('/');
    Serial.print(theData.key);
    Serial.print('$');
    Serial.print(theData.value);
    Serial.print('\n');  
  }
}


I have a few other rfm69 modules driven by arduinos, they work well and I use one of these to send a test message a second.
Now I the strange thing is, that those messages first will be recognised and send via the serial port as expected.
But after half a minute, nothing is received anymore. The "Pulse"-message of the sketch is still send, so the program is still working.

Any ideas where to look at?
I tried using a pullup at the interrupt-pin, which maybe give 10 seconds to the system to work.
 
I use the RadioHead protocol stack with the RFM69's, on Teensy and AVR without issues.
Glancing at the code posted above
void RFM69::select()

It's imprudent to configure the SPI within the slave select function. Normally, the SPI is configured once (if you're not using SPItransactions).

Interrupt on pin 0? Thats UART1's Receive. I suppose it'll work anyway. Has to be external interrupt capable, rising edge.

You might want to try using RadioHead. My opinion is that it is the better of the two, by far.


Just some general observations as I am unfamiliar with Felix's Low Power Lab code.


this
noInterrupts();
doesn't seem to have a mating enable
 
Thank you for your reply.
Interrupt on pin 0? Thats UART1's Receive. I suppose it'll work anyway. Has to be external interrupt capable, rising edge.
That should be no problem. I tried another pin as well and it shows the same behavior.

this
noInterrupts();
doesn't seem to have a mating enable
it has in the unselect() function, sorry for not posting this. But I think there could be a problem with the interrupts.

It's imprudent to configure the SPI within the slave select function. Normally, the SPI is configured once (if you're not using SPItransactions).
Do you think that this part
Code:
  // save current SPI settings
  _SPCR = SPCR;
  _SPSR = SPSR;
is the problem? Because in the unselect routine, they will be restored:
Code:
void RFM69::unselect() {
  digitalWrite(_slaveSelectPin, HIGH);
  // restore SPI settings to what they were before talking to RFM69
  SPCR = _SPCR;
  SPSR = _SPSR;
  interrupts();
}

Thank you for the hint with the radioHead library. Maybe i should use this (although that means a complete rewrite of all my arduino wireless nodes :))
 
You shouldn't need the noInterrupts()

And the select and unselect routines normally/should have just altering the SS pin, nothing else.

If you have 2 SPI devices on the same SPI controller, you might need some code similar to what Felix has. Better, use Arduino/Teensyduino's new SPI Transactions library if you have 2+ devices sharing one SPI port.
If you have just one, then that complexity isn't needed.
This includes the save and resort of SPCR.

Altering for radiohead... I'd think your calls to available() and send, receive reliable datagrams would be a small percentage of the code. Be sure to use reliable datagrams.
 
Strange things.... (maybe I'am to stupid)
I decided to try the radioHead library (very nice, indeed). On the arduinos first, after a few minutes, everything was working with the radiohead library. You were correct, nothing to change really :)
But then for the teensy. At first, I thought it worked well, but then, after a minute (longer than with the lowpowelab library), it stoped working as well. And it shows problems sending (especially the ACK is not send). Another issue, the temperature readings from the chip are flattering from 18 to 29. Perhaps it is a hardware error. I will check this (unfortunately, i don't have a spare arduino or a spare rfm69 module)
 
Not much help, but I have used radiohead + RFM69H for a long time in some quantity.
Do you mean the ACK is not sent or do you mean the error was no ACK received?


Temperature.. be sure to read it only when you put the radio in the idle mode. I haven't paid attention to accuracy.
 
Hello,

I found the time to try with a new Arduino and a new RF69 Module. Using the same RF69 Module on Arduino works out of the box with the examples from the radiohead library, but when I connect it to the teensy 3.1, the board prints the following to the serial console:
Code:
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
sendtoWait failed
got request from : 0x1: Hello World!
After these, nothing happens anymore and the LED of the Teensy is alway on (instead of flashing, showing the SPI clock).
Any idea whats happening?
I'm using the standard SPI pins, and pin 2 for the interrput

EDIT: Just to mention, I've tried serveral other SS and interrupt pins as well, and powering the RF69 module via a external power supply
 
Last edited:
progress, particullary:
When adding a delay in the main loop, it is working, but only if the delay is higher than 200ms. Here is my code:
Code:
#include <RHReliableDatagram.h>
#include <RH_RF69.h>
#include <SPI.h>

#define SERVER_ADDRESS 1

uint8_t buf[RH_RF69_MAX_MESSAGE_LEN]; // for received message
char txbuf[RH_RF69_MAX_MESSAGE_LEN];
char displayBuf[128];

uint8_t myAddress;

RH_RF69 driver;

RHReliableDatagram manager(driver, SERVER_ADDRESS);


void setup() {
  myAddress = SERVER_ADDRESS;
  Serial.begin(9600);
  
  delay(4000);
  Serial.println("Start Initializing");
  delay(500);

  while (1)  {
    if (!manager.init())  {
      Serial.print(millis()); Serial.println(" init failed");
      delay(500);
    } else {
      break; // init success
    }
  }
  
  Serial.println("init radio OK!");
  driver.setThisAddress(SERVER_ADDRESS);
}

int rssiTo_dBm(uint8_t rssi)  {
  return( (int)(int8_t)rssi);
}

void loop() {

  if (manager.available()) {
    uint8_t len = sizeof(buf);
    uint8_t from, to, id, rssi;
    if (manager.recvfromAck(buf, &len, &from, &to, &id)) {
      rssi = driver.lastRssi();
      sprintf(displayBuf, "\nmsg from #%d id:%-3d RSSI:0x%02X(%ddBm) len:%d Is:%s\n", from, id, rssi, rssiTo_dBm(rssi), len, buf);
      Serial.println(displayBuf);
      snprintf(txbuf, (int)sizeof(txbuf)-1, "me:#%d to:#%d millis=%lu", myAddress, from, millis());
      if (!manager.sendtoWait((uint8_t *)txbuf, strlen(txbuf)+1, from)) {
        Serial.println("sendtoWait failed");
      }
    }
  }

  delay(200); //Without nothing works
}
 
I don't see anything wrong.
sendtoWait failed - for reliable datagrams usually means there was no ACK from the receiving device - presuming it too is using reliable datagram mode.
If the interrupt line from the radio to the MCU is missing/miswired or declared wrong in the class instancing, then you should just get a hang and the transmitting unit - hangs without timeout on transmit complete interrupt.

The delay(200) is outside the polling on available() so it has the effect of checking available() every 200mSec. I can't see what difference that makes.

A nit: I prefer to avoid declaring and initializing in a loop - never sure that, e.g., len will get reinitialized each iteration of the loop. I put the declaration at the top of the function and in the loop, do a len = sizeof(buf) each iteration.
if (manager.available()) {
uint8_t len = sizeof(buf);
uint8_t from, to, id, rssi;

Did you run the sample client/server code verbatim (except for Teensy IRQ bit number, etc.)?

I have T3's with RFM69H but no time right now to recreate your problem. Sorry.
 
thanks for your reply. very quick as always.
Did you run the sample client/server code verbatim (except for Teensy IRQ bit number, etc.)?
Of course, this was the code i started with.
The delay(200) is outside the polling on available() so it has the effect of checking available() every 200mSec. I can't see what difference that makes.
when i remove this delay, the teensy is not able to send any package anymore, especially no ACKs. And after about 10 packages, the teensy hangs completely.
When using the example code from the library, it shows exactly the same behavior, adding delay, everything is fine, without not.

What puzzles me is that the same code runs quite well on the arduinos without the delay.
sendtoWait failed - for reliable datagrams usually means there was no ACK from the receiving device
this only fails on the teensy. All my arduino nodes send the ack correctly.
Normally, everything works with my teensy, i haven't encounter any problem so far. Don't know whats happening here.
A nit: I prefer to avoid declaring and initializing in a loop
i would disagree here a bit. Using local variables is much better regarding information hiding and especially you can save a lot of memory avoiding global variables. In this example, when there is no incomming message, you save 5 Bytes (ok, veeeery much).

Do you think I should try an older version of the library? Which version do you use?
 
Last edited:
I agree that using locals is a commonplace idea. I was suggesting keeping them as locals, but I suggest putting
uint8_t len;
in the function but before any code.
Then in the loop, put len = sizeof(buf); so that it executed on every iteration rather than just once as an initialized local - initialized only on the first call of the function.

OK. You say that the client/server demos unmodified run OK on a pair of T3's, right. So we don't have a hardware problem. Right? Or is it an AVR and a T3? I've run AVRs and T3s interoperating.
Older library - no. This is too basic.
 
oh sorry, I completely missunderstood you. Of course, this is dump to have it like that.

I run the client on an AVR (atmega 328) and the server on the teensy. The unmodified code shows this behavior.
Mhh, one thing i assume is different to your setup. I'm using the rfm69cw module. But as far as i know, this should completely compatible with the rfm69w
 
I recall reading that the CW is incompatible with the W and H. Can't recall why.
Search or ask on the RH user forum.
 
ITS WORKING!!!!!!!!!!

Searching the radiohead user forum reveals that i should use another modem config. So I changed it to GFSK_Rb55555Fd50 and now everything is working.
Strange that the default value works with the arduino.

Thank you very very much! And sorry again for the misunderstanding about the variables
 
it must have been that the both devices were not using the same modulation mode. The GFSK_Rb55555Fd50 is a mode I don't recommend.
I suggest that both / all devices use a lower bit rate and channel width, for the sake of better range.
Run as low as you app can tolerate, as lower channel width and bit rate = fewer bit errors, esp. with large packets.
 
Both devices use the same modulation mode for sure (I'm still using the unmodified example sketch, except for the modem setting, which is the same on both).
I tried a few modem configurations:
GFSK_Rb55555Fd50 working quite well
GFSK_Rb250Fd250 teensy is not able to send anything (receive works)
GFSK_Rb125Fd125 teensy is not able to send anything (receive works)
GFSK_Rb57_6Fd120 teensy somethimes is able to send something (receive works)
GFSK_Rb38_4Fd76_8 best setting, sending 500 messages without any fail
GFSK_Rb19_2Fd38_4 7 fails in 500 messages
GFSK_Rb9_6Fd19_2 4 fails in 500 messages

avr to avr, every of the above settings were working. So I think I'm confident now.
 
If you search the RadioHead forum, you'll see that I posted test results of the different modulation modes. Several don't work right. I and Mike tried to get the radio chip vendor to help resolve this. The issue is the modes are Mike's guesstimate. HopeRF finally did reply with a useless sophomoric response. They don't understand the inner workings of the radio chip that they buy from.

Mike's guess had the modulation index too aggressive in many cases. And FSK worked better than GFSK.
I use a high bit rate FSK with a wide channel - since I need speed, not long range. It works very well.
I can lookup and post what modes I use.
steve
 
Thanks! I'm searching...

One thing is a bit strange though, why is the default modulation config working with the avrs and not the teensy? Does this make sense?

I can lookup and post what modes I use.
That would be nice!

Just for documentation purposes. If anyone has problems with the teensy and a rfm69cw module, try to change the modulation settings.
 
Doesn't make sense. That 5555 modulation is some screwy thing that Moteino came up with for some interoperabiliity reason.
Maybe it's the 'CW radio - I did read somewhere, maybe the RH forum, that the CW has incompatibilites with the HW.
 
Doesn't make sense. That 5555 modulation is some screwy thing that Moteino came up with for some interoperabiliity reason.
Stevech, could you please be a little bit less negative towards libraries - besides RadioHead - which deal with RFM69 radios?

The datasheet for RFM69CW details quite a lot additional parameters which you can tune for all modulation parameters. When I wrote my own library for the RFM69 radio series (as introduced in this post) I dived into the datasheet to calculate the optimal parameters for the fastest modulation; 300000 baud, there are some more options you can configure to improve the transmission. You can find the parameters I use in plainRFM69.cpp#L299, you should be able to figure out which registers those are by looking in bareRFM69.h.

I always use this configuration and never have problems with reception. But, I have to agree with Stevech, it can be better to lower the baudrate for more reliable transmissions if your application can tolerate the lower data rate.
 
Status
Not open for further replies.
Back
Top