Author Topic: [RFM69 Library] Initialize function always returns true  (Read 2726 times)

bartikus

  • NewMember
  • *
  • Posts: 5
  • Country: us
[RFM69 Library] Initialize function always returns true
« on: November 29, 2016, 02:01:20 PM »
EDIT: Problem solved. Go to Reply #5 for solution.



...even with the radio completely removed from the board.

Basically, I have a project using a moteino and the RFM69 library. It is not my first project with this hardware or library. The only difference is that the first project I was using arduino 1.0.6, and now I'm using arduino 1.6.11. I say that just in case there is a known difference between the arduino SPI libraries that would cause this.

In my project, I try to initialize the radio like so:
Code: [Select]

debugOn = true; //this can be turned on via serial port, turning on now for duration of development

pinMode(ON_BOARD_LED, OUTPUT);
digitalWrite(ON_BOARD_LED, HIGH);

if(debugOn){
Serial.println("\nInit Radio ... ");
}
if(initRadio() == true){
if(debugOn){
Serial.println("OK");
}
delay(300); //delay so that the LED is on long enough to be noticeable
}
else{
if(debugOn){
Serial.println("BAD");
}
delay(100);
for(int i = 0; i < 5; i++){
digitalWrite(ON_BOARD_LED, LOW);
delay(100);
digitalWrite(ON_BOARD_LED, HIGH);
delay(100);
}
}
digitalWrite(ON_BOARD_LED, LOW);
And initRadio() looks like this:
Code: [Select]
boolean initRadio(void)
{
boolean retVal = false;
if(radio.initialize(RF69_915MHZ,PROBEID,NETWORKID)){
retVal = true;
}
#ifdef IS_RFM69HW
radio.setHighPower(); //only for RFM69HW!
#endif
radio.encrypt(ENCRYPTKEY);
radio.promiscuous(false);
radio.setPowerLevel(1);//14);
delay(20);
return retVal;
}
I wanted to get a visual indicator of whether or not the radio initialized properly. On the other projects I would just turn on the LED and enter an infinite loop, but in this case I am running off a coin cell battery and don't want to kill it, so I just want to blink 5x and go to sleep (later in the code, not shown above). This visual indicator is paired with the serial debug statements.

No matter what I do, including COMPLETELY REMOVING the radio from the moteino, the radio.initialize() function always returns true, the LED never blinks 5x, and the debug statement is always "OK."

Has anyone else had this issue?
« Last Edit: November 30, 2016, 09:32:56 AM by bartikus »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: [RFM69 Library] Initialize function always returns true
« Reply #1 on: November 29, 2016, 02:13:08 PM »
There's this code in RFM69.initialize() which should return false if there is no radio:

Code: [Select]
  start = millis();
  while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && millis()-start < timeout); // wait for ModeReady
  if (millis()-start >= timeout)
    return false;

You sure you have the latest lib code?

bartikus

  • NewMember
  • *
  • Posts: 5
  • Country: us
Re: [RFM69 Library] Initialize function always returns true
« Reply #2 on: November 29, 2016, 02:51:28 PM »
Hey Felix thanks for replying.

There's this code in initialize() which should return false if there is no radio:
Yes, I have seen and am currently looking right at this code.

Quote
You sure you have the latest lib code?
Seeing that your latest commit was 8 days ago, no I definitely do not. I am downloading now and will try again.

bartikus

  • NewMember
  • *
  • Posts: 5
  • Country: us
Re: [RFM69 Library] Initialize function always returns true
« Reply #3 on: November 29, 2016, 03:22:02 PM »
Okay, I have now downloaded your latest library and still the same issue.

It slipped my mind before that I have replaced the 328p on this board with a 328pb. I haven't had any other problems with the pb, other than when I initially got the part I had to change some avrdude scripts I had written to bypass the device signature check. I reallyl shouldn't call this a moteino anymore I guess, because I've modified it so much. Either way, it appears that the initialize function does not time out and return false like it should be.

bartikus

  • NewMember
  • *
  • Posts: 5
  • Country: us
Re: [RFM69 Library] Initialize function always returns true
« Reply #4 on: November 29, 2016, 03:49:57 PM »
New info. I saw the timeout in the RFM69::initialize() function is 50 ms, supposedly 3 times. So the function should take 150ms to complete.

Using millis(), the following times were gathered:
at entry into initialize(): 75ms
before the code listed by Felix: 176ms
after initialize returns: 176ms


So it seems like that third timeout does not tick at all.

bartikus

  • NewMember
  • *
  • Posts: 5
  • Country: us
Re: [RFM69 Library] Initialize function always returns true
« Reply #5 on: November 30, 2016, 09:31:27 AM »
Problem Solved
Problem:
The problem I was having was with this code:
Code: [Select]
#define RF_IRQFLAGS1_MODEREADY  0x80
...
while (((readReg(REG_IRQFLAGS1) & RF_IRQFLAGS1_MODEREADY) == 0x00) && (millis()-start) < timeout); // wait for ModeReady
if (millis()-start >= timeout)
    return false;
With no radio soldered onto my board, the SPI transaction readReg(REG_IRQFLAGS1) returns 255 (0xFF). Bit-wise and with 0x80 results in 0x80 which != 0x00, so this line is completely skipped, therefore it never returns false.

Solution:
I changed the while to a do while, and continue to read while readReg(REG_IRQFLAGS1) returns 255. I tested this code with the radio removed and it properly returned false, then attached the radio
but left the chip select pin disconnected and it properly returned false, and then finally I connected the chip select and the radio initialized properly. Code below:
Code: [Select]
start = millis();
uint8_t regIRQflags1; //added variable to require only one read for two comparisons (below)
do regIRQflags1 = readReg(REG_IRQFLAGS1); while (((regIRQflags1 == 0xFF) || ((regIRQflags1 & RF_IRQFLAGS1_MODEREADY) == 0x00)) && (millis()-start) < timeout); // wait for ModeReady
if (millis()-start >= timeout)
  return false;

I hope this helps anyone with the same problem and maybe this fix will make it into the next library commit.


perky

  • Hero Member
  • *****
  • Posts: 873
  • Country: gb
Re: [RFM69 Library] Initialize function always returns true
« Reply #6 on: November 30, 2016, 10:22:14 AM »
I assume that the MISO pin has it's pull-up enabled, otherwise this might not be safe (it should, given that it would be tri-stated when the radio isn't selected). Worth checking.

Also this particular conditional return happens well into the initialization code (after setting all the registers).  This could have been caught much earlier on, in the write to SYNCVALUE1 register in fact. I guess this return of false is really to check that the radio appears to be working once initialized, I doubt it was originally intended to detect a radio that's not fitted as that would not normally be done. I would probably suggest adding a "if (millis()-start >= timeout) return false;" on the SYNCVALUE1 register for that.

Mark.


Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: [RFM69 Library] Initialize function always returns true
« Reply #7 on: November 30, 2016, 09:58:44 PM »
Thanks guys for the conversation and proposals.
I thought of adding a dedicated function that would check if radio is present - something like radioOK() but it seems too much overhead.
I think what perky suggested is reasonable and would translate into something like this:

Code: [Select]
do {
  writeReg(REG_SYNCVALUE1, 0xAA);
  if (millis()-start > timeout) return false;
}
while (readReg(REG_SYNCVALUE1) != 0xaa);

We could implement several ways to verify the radio is attached. But that doesn't guarantee the radio is prime time ready. So part of this initialize was that type of attempt, that after loading the whole config, it would respond at a minimum as expected.

Just polling the SPI and expecting 0xFF is not going to work since those lines can sometimes float - I've seen this happen, it's not a reliable method. It's better to say write a register value then read it back.
But as a poor man's check the above will work. I will need to test this around for a while before integrating but feel free to use it on your local copy until it's merged (or until i come up with a better method).

Thank you again.