Author Topic: RFM69 at 2Mhz, struggling [solved]  (Read 2206 times)

twastvedt

  • NewMember
  • *
  • Posts: 8
RFM69 at 2Mhz, struggling [solved]
« on: January 17, 2020, 06:21:36 PM »
Hello! I'm new to all of this (electronics and radios), and slowly building my way towards a basic sensor network. Right now I'm prototyping the wireless communication using RFM69s on two breadboards. As far as I can tell the setup is pretty standard (see diagram below):
  • 3v power from arduino
  • 16MHZ crystal and the CKDIV8 fuse set so the 328p is running at 2MHZ
  • RFM69W connected via SPI as shown

I have written a short test program (code below) which should make some pseudo Morse code: node 0 blinks a three-item code, then node 1 blinks the same three-item code. Then they switch: node 1 sends a message to node 0.

Several things are working:
  • Program on both nodes starts up correctly, and the `testRadio` function returns true (tests that the RFM69 is working by trying to set a register and then confirming that it was set by reading the register out).
  • Node 0 blinks a code, at expected speed.
  • Node 1 starts to listen for a message.

And then node 0 lights up indicating that the message was not received and node 1 continues to listen for a message. I'm not sure how to debug from here. The only thing I've thought of is to solder two replacement RFM69s to perf board in case I accidentally busted the radio by running briefly without an antenna. I might have also let 5v in at one point or another, but then I wouldn't think `testRadio` would work. I was hoping that instead my naivete has lead to some obvious error.

Questions / curiosities:
  • R4, on the slave-select pin, is necessary for programming (to disable the SPI communication with the radio?). However, leaving it connected when running the program seems to have no effect. This seems strange to me.
  • In the RFM69 library I believe the SPI clock is normally set to 4,000,000 (4 MHZ?) (`_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);`). Based on what I've read it should be 1/4 the 328p's clock speed, so I tried changing that to 500,000, but with no change in the results above.

Thanks for any suggestions!



Code: [Select]
// Copyright Felix Rusu 2016, http://www.LowPowerLab.com/contact
...
// http://www.gnu.org/licenses/gpl-3.0.txt

#include <Arduino.h>
#include <RFM69.h>     //get it here: https://github.com/lowpowerlab/rfm69
#include <RFM69_ATC.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <RFM69_OTA.h> //get it here: https://github.com/lowpowerlab/RFM69
#include <SPIFlash.h>  //get it here: https://github.com/lowpowerlab/spiflash
#include <SPI.h>       //included with Arduino IDE (www.arduino.cc)

//unique for each node on same network
#define NODEID 0

#define NODES 2

#define NETWORKID 100 //the same on all nodes that talk to each other

#define FREQUENCY RF69_915MHZ

#define ENCRYPTKEY "Ow4ihs(*E#qt8HOH" //exactly the same 16 characters/bytes on all nodes!

#define LED_SEND 9
#define LED_RECEIVE 8

#define MESSAGE_LENGTH 3

#define DIT_MS 300

#define SERIAL_BAUD 9600

int TRANSMITPERIOD = 2000; //transmit a packet to gateway so often (in ms)
char buff[50];
byte sendSize = 0;
int targetNodeId;

#ifdef ENABLE_ATC
RFM69_ATC radio;
#else
RFM69 radio;
#endif

void Blink(byte PIN, int DELAY_MS)
{
  digitalWrite(PIN, HIGH);
  delay(DELAY_MS);
  digitalWrite(PIN, LOW);
}

void BlinkBits(byte pin, byte data)
{
  int i = 0;

  Serial.print("Blink: ");
  Serial.println(data, BIN);

  while (i < MESSAGE_LENGTH)
  {
    if (data & 0x01)
    {
      Serial.print(1);
      Blink(pin, DIT_MS * 3);
    }
    else
    {
      Serial.print(0);
      Blink(pin, DIT_MS);
    }

    delay(DIT_MS);

    i++;
    data = data >> 1;
  }

  delay(DIT_MS * 2);
  Serial.println();
}

bool testRadio()
{
  if (radio.readReg(0x2F) != 0x2D)
  {
    return false;
  }

  uint32_t start = millis();
  uint32_t timeout = 1000;

  do
  {
    radio.writeReg(0x2F, 0xAA);
    if (millis() - start > timeout)
      return false;
  } while (radio.readReg(0x2F) != 0xAA);

  // Rewrite config value from initialize.
  radio.writeReg(0x2F, 0x2D);

  return true;
}

void errorDisplay()
{
  digitalWrite(LED_SEND, HIGH);
  digitalWrite(LED_RECEIVE, HIGH);

  while (1)
  {
  }
}

void setup()
{
  pinMode(LED_SEND, OUTPUT);
  pinMode(LED_RECEIVE, OUTPUT);

  Serial.begin(SERIAL_BAUD);

  SPI.setClockDivider(SPI_CLOCK_DIV16);

  if (!radio.initialize(FREQUENCY, NODEID, NETWORKID) || !testRadio())
  {
    Serial.println("Error: Unable to initialize radio!");
    // Turn both lights on to indicate an error.
    errorDisplay();
  }

  radio.encrypt(ENCRYPTKEY);

#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif

  randomSeed(analogRead(0));

  targetNodeId = (NODEID + 1) % NODES;

  sprintf(buff, "\nNode %d, transmitting to node %d at %d Mhz...", NODEID, targetNodeId, FREQUENCY == RF69_433MHZ ? 433 : FREQUENCY == RF69_868MHZ ? 868 : 915);
  Serial.println(buff);

  Blink(NODEID == 0 ? LED_SEND : LED_RECEIVE, 3000);
  delay(500);
}

byte randNumber = 0;
bool sendMessage = NODEID == 0;
int blinkCounter = 0;
int blinkFrequency = 10000;
bool blinkOn = true;

void loop()
{
  if (sendMessage)
  {
    sendMessage = false;

    randNumber = random(pow(2, MESSAGE_LENGTH));

    Serial.print("Sending data to node ");
    Serial.print(targetNodeId);
    Serial.println(":");

    Serial.println(randNumber, BIN);

    BlinkBits(LED_SEND, randNumber);

    if (radio.sendWithRetry(targetNodeId, &randNumber, 1))
    {
      Serial.print(" Sent ok!");
    }
    else
    {
      Serial.print(" No response...");
      errorDisplay();
    }

    Serial.println();
  }
  else if (radio.receiveDone())
  {
    digitalWrite(LED_SEND, LOW);

    Serial.print("Receiving from node ");
    Serial.print(radio.SENDERID, DEC);
    Serial.println(":");

    Serial.println(radio.DATA[0], BIN);

    Serial.print("   [RX_RSSI:");
    Serial.print(radio.RSSI);
    Serial.print("]");

    if (radio.ACKRequested())
    {
      radio.sendACK();
      Serial.print(" - ACK sent");
    }

    BlinkBits(LED_RECEIVE, radio.DATA[0]);
    Serial.println();

    sendMessage = true;
  }
  else if (blinkCounter++ > blinkFrequency)
  {
    if (blinkOn)
    {
      Serial.print(".");
      digitalWrite(LED_SEND, HIGH);
    }
    else
    {
      digitalWrite(LED_SEND, LOW);
    }

    blinkOn = !blinkOn;
    blinkCounter = 0;
  }
}

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #1 on: January 26, 2020, 08:40:39 PM »
Well, I went ahead and soldered up two more RFM69W's, replaced them, and same results. Bummer. My use of a low clock speed (2MHZ) seems the most likely culprit to me. Should the below work?

Questions / curiosities:
In the RFM69 library I believe the SPI clock is normally set to 4,000,000 (4 MHZ?) (`_settings = SPISettings(4000000, MSBFIRST, SPI_MODE0);`). Based on what I've read it should be 1/4 the 328p's clock speed, so I tried changing that to 500,000, but with no change in the results above.

Would I be better off using a higher clock? I was thinking to save battery, but I'm not sure if it's better to run fast for short periods or slower for longer periods. They won't be doing much: gathering sensor readings and sending them off every minute.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 at 2Mhz, struggling
« Reply #2 on: January 27, 2020, 09:16:12 AM »
Just run at the recommended 4mhz, even if your main clock is 8mhz.

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #3 on: January 29, 2020, 09:53:03 AM »
Thanks for the reply Felix! I just tried again with the default RFM69 library, as you suggest, with no success. I should note that my main clock is 2MHZ, not the 8 that you mention in your post.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 at 2Mhz, struggling
« Reply #4 on: January 29, 2020, 10:47:38 AM »
Why do you use 2mhz? Power savings? How much power do you save?

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #5 on: January 31, 2020, 08:34:00 AM »
I'm not attached to the 2MHZ. Yes, that was the original thinking: "If I run at lower speed, I'll use less power." But I realize that it then takes longer, and I'm unclear on where the minimum on that curve is. I'm also at 2MHZ because I had a 16MHZ crystal handy. Also I don't really know what I'm doing. Is there a recommended speed to use if I'm running the 328P at 3V and so can't use 16MHZ (looks like I can run at anything 12 or under)? Is running the SPI at less than 4MHZ even possible?

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 at 2Mhz, struggling
« Reply #6 on: January 31, 2020, 09:54:05 AM »
3V - 8Mhz.

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #7 on: February 07, 2020, 09:32:57 AM »
Cool. So, I acquired an 8 MHZ crystal, changed fuses (no CKDIV8), adjusted f_cpu, uploaded, and ... same result. My initialization appears to go OK, but no connection is made.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 at 2Mhz, struggling
« Reply #8 on: February 07, 2020, 11:57:21 AM »
 :'( :-X :-\ ???

That is why I made the Moteino, and the Moteino-8mhz. So people that are getting started have a good experience with a known working setup, and they would not have to reinvent the wheel.
I would also not recommend using breadboards except for very basic things. They can be really crappy quality and buggy (shorts!) and create all sorts of signal integrity issues.
« Last Edit: February 08, 2020, 05:03:48 PM by Felix »

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #9 on: February 08, 2020, 10:35:56 PM »
It works! Well, at least the two nodes communicate. Something gets hung up after a message is exchanged, but I'm pretty sure that's a software bug, not a hardware one. Those I feel more confident about fixing. I stared at some data sheets some more, and realized the bottom yellow wire in the diagram above was attached to the wrong pin of the RFM69. Should be on the second from the left, DIO0, not RESET. Whoops.

Well, I've learned quite a bit already, so, maybe not the best experience, but sometimes reinventing the wheel can be enlightening! I take your point about the breadboards, and I do want to get to making my own boards soon, but all this exploration would have been so much slower if I had to make a board every time!

Thanks again for your help!
« Last Edit: February 08, 2020, 10:41:33 PM by twastvedt »

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #10 on: February 08, 2020, 10:45:13 PM »
So, for anyone coming after, in summary this is what is working:

(3V power)

Fuses:
lfuse = 0xD2
hfuse = 0xD2
efuse = 0xFE

(Another thing I realized from looking at the Moteino specs, is that I didn't need the crystal at all, as the 328P's internal clock runs at 8MHZ. All things I'd read at one point or another, just took me a while to put it all together!)
« Last Edit: February 08, 2020, 10:46:59 PM by twastvedt »

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: RFM69 at 2Mhz, struggling
« Reply #11 on: February 10, 2020, 02:57:18 PM »
So, for anyone coming after, in summary this is what is working:
(Another thing I realized from looking at the Moteino specs, is that I didn't need the crystal at all, as the 328P's internal clock runs at 8MHZ. All things I'd read at one point or another, just took me a while to put it all together!)
So did you manage to get it to work at 8mhz? What was the culprit? Some wiring detail?

twastvedt

  • NewMember
  • *
  • Posts: 8
Re: RFM69 at 2Mhz, struggling
« Reply #12 on: February 11, 2020, 09:06:30 AM »
Yup!

A number of things. The latest, as I said above, is that I had the DIO0 wire attached to RESET instead. But I started all this out running at 2MHZ, so the switch to 8 was also essential. Classic example of the difficulty of having more than one fatal error! If you happen to fix one, you don't know it because still nothing works!