LowPowerLabs Radio Repeater using an EmonTH or JeeLink

I’ve been setting up a monitoring system in a building where the standard 433MHz radio range is not quite enough. A long time ago now I used a USB powered EmonTH as a repeater to get around this issue and thought I would take the same approach again here but get this working with the LowPowerLabs library. It’s also possible to use a JeeLink (right) to do the same. Thought I would share this in case it’s useful for others.

The EmonTx4 in this case first transmits on group 200 , this message is received by the repeater and forwarded on on group 210, which is then received by the base station.

Here’s the code to make this work:

#include <RFM69.h>
RFM69 radio;

byte nativeMsg[66];

#define MAXMSG 66
char outmsg[MAXMSG];
byte outmsgLength;

struct {
  byte srcNode = 0;
  byte msgLength = 0;
  signed char rssi = -127;
  bool crc = false;
} rfInfo;

void setup() 
{
  Serial.begin(38400);
  //Serial.println("Repeater");
  radio.initialize(RF69_433MHZ,5,200);  
  radio.encrypt("89txbe4p8aik5kt3");
  radio.setPowerLevel(31);
}

void loop()             
{
  if (radio.receiveDone())
  {
    rfInfo.srcNode = radio.SENDERID;
    rfInfo.msgLength = radio.DATALEN;
    for (byte i = 0; i < radio.DATALEN; i++) {
      nativeMsg[i] = radio.DATA[i];
    }
    rfInfo.rssi = radio.readRSSI();
    
    if (radio.ACKRequested()) {
      radio.sendACK();
    }
    
    Serial.print(F("OK")); 
    Serial.print(F(" "));
    Serial.print(rfInfo.srcNode, DEC);
    Serial.print(F(" "));
    for (byte i = 0; i < rfInfo.msgLength; i++) {
      Serial.print((word)nativeMsg[i]);
      Serial.print(F(" "));
    }
    Serial.print(F("("));
    Serial.print(rfInfo.rssi);
    Serial.print(F(")"));
    Serial.println();
    
    // Repeat
    radio.setAddress(rfInfo.srcNode);
    radio.setNetwork(210);
    radio.sendWithRetry(5, nativeMsg, rfInfo.msgLength);
    radio.setAddress(5);
    radio.setNetwork(200);
  }
}

and platformio.ini for those who prefer using platformio to compile:

[platformio]
default_envs = default
src_dir = .

[env:default]
platform = atmelavr
framework = arduino
board = uno
monitor_speed = 38400
lib_deps =
  https://github.com/LowPowerLab/RFM69

The above code also repeats at the higher power level (level 31 or 13dBm).

2 Likes

I’d need to go through the Hope data sheet very carefully, but I have a feeling that the same buffer is used in the RFM69CW for both receive and transmit. If this is correct, you might not even need to get the message out of the RFM69CW. I’m not sure where this leaves the ACKs & retries of LPL.

1 Like

Thanks @Robert.Wall yes radio.sendACK(); clears radio.DATA hence the need for nativeMsg I did wonder the same.

You’re acknowledging each step? Is it possible to forward the message all the way to the ultimate destination, then relay the ACK back by the same route in reverse. The ACK will take longer of course to return, but it’s a true acknowledgement of receipt, rather than of it getting half way.

Yes ack for each step. Il check the packet loss rate and get back to you.