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:
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:
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?
There's this code in RFM69.initialize() (https://github.com/LowPowerLab/RFM69/blob/master/RFM69.cpp#L42) which should return false if there is no radio:
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?
Problem Solved
Problem:
The problem I was having was with this code:
#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:
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.
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:
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.