Node not being "heard"

Started by n8twj, September 16, 2016, 02:46:23 PM

n8twj

HI Folks -  I have a Moteino USB with a 433mhz RFM69HW using an appropriately sized wire antenna running a simple gateway sketch....receive a packet, print out via Serial.print().   

ACKs are disabled.  The gateway code never blocks / delays.  Encryption is enabled, all nodes+gateway have the same shared secret. 

I then have 4 Moteino's with 433mhz RFM69HW (again with a wire antenna) acting as sensor nodes around my home and garden.   High power is selected. ATC is enabled (-70).   The farthest node isn't more than 30 meters away from the gateway.    I transmit weather and system data in a couple radio.send() iterations, once per minute-ish.

I am having trouble reliably receiving one node in particular, but all nodes have mysteriously stop being heard by the gateway at one time or another.  Then just as mysteriously started working again without even the node (or gateway) being power cycled.  Extensive Serial debugging hasn't lead me to any particular reasoning.   

I have setup an RTL-SDR based test environment, in hopes to prove that the node is actually transmitting the packet.  I haven't as of yet attempted to actually decode via the RTL-SDR...might be a fun exercise:)

So far it does ~seem~ like a given node is still transmitting, but the gateway doesn't seem to receive it. Like I said, without any external intervention say Node 5 stops being heard and maybe now Node 4 isn't heard... Give it a random amount of time and this time say Node 3 wont be heard.     I have even placed a node right next to the gateway and it too has gone unheard for several minutes at a time.

When I do receive packets, RSSI is usually pretty close to the -70 value when setting ATC.

Here is my quite simple gateway code:
#include <RFM69.h>
#include <RFM69_ATC.h>
#include <Wire.h>

#include <SensorData.h>  // my own lib defining the wire protocol  (structs / union) 
#include "config.h"

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  Blink(LED,50);
}

byte ackCount=0;
uint32_t packetCount = 0;
void loop() {
  Payload packet;
  if (radio.receiveDone()) {
    packet = *(Payload*)radio.DATA;
    Serial.print("Node:");
    Serial.print(packet.nodeId, DEC);
    Serial.print(" ");

    switch(packet.msg)  {
    case MESSAGE_SYSTEM:
      Serial.print("V:");
      Serial.print(packet.data.system.voltage);
      Serial.print(" U:");
      Serial.print(packet.data.system.uptime);
      break;
    case MESSAGE_BATTERY_DATA:
      Serial.print("BATLV:");
      Serial.print(packet.data.battery.loadVoltage);
      Serial.print(" BATC:");
      Serial.print(packet.data.battery.currentMa);
      break;
    case MESSAGE_SOLAR_DATA:
      Serial.print("PVLV:");
      Serial.print(packet.data.solar.loadVoltage);
      Serial.print(" PVC:");
      Serial.print(packet.data.solar.currentMa);
      break;
    case MESSAGE_RAIN_DATA:
      Serial.print("RAIN:");
      Serial.print(abs(packet.data.rain.amount - 1024)); // reverse sense for graphing
      break;
    case MESSAGE_ENVRIONMENT:
      Serial.print("T:");
      Serial.print(packet.data.env.temp);
      Serial.print(" H:");
      Serial.print(packet.data.env.humidity);
      if (packet.data.env.pressure != -1.00) {
        Serial.print(" P:");
        Serial.print(packet.data.env.pressure);
      }
      break;
    case MESSAGE_WIND_DATA:
      Serial.print("WindDir:");
      Serial.print(packet.data.wind.direction);
      Serial.print(" WindSpeed:");
      Serial.print(packet.data.wind.speed);
      break;
    default:
      Serial.print("WTF:1");
    }
    Serial.print(" RSSI:");
    Serial.print(radio.RSSI);
    Serial.println();
  }
}



Here is the serial.print() output from the gateway:
Node:3 T:6843.00 H:73.00 RSSI:-70
Node:3 V:3.80 U:15423890 RSSI:-70
Node:4 PVLV:4.36 PVC:104.40 RSSI:-71
Node:4 BATLV:4.18 BATC:-85.68 RSSI:-72
Node:4 RAIN:1 RSSI:-71
Node:4 V:-1.00 U:3723063 RSSI:-71
Node:3 T:6861.00 H:73.00 RSSI:-68
Node:3 V:3.80 U:15427982 RSSI:-70
Node:4 PVLV:4.60 PVC:88.06 RSSI:-71
Node:4 BATLV:4.18 BATC:-65.24 RSSI:-71
Node:4 RAIN:1 RSSI:-92
Node:3 V:3.80 U:15432075 RSSI:-70
Node:4 PVLV:4.54 PVC:79.66 RSSI:-71
Node:4 BATLV:4.18 BATC:-67.98 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:3 V:3.80 U:15436176 RSSI:-71
Node:4 PVLV:4.59 PVC:77.74 RSSI:-71
Node:4 BATLV:4.18 BATC:-67.86 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:4 V:-1.00 U:3728331 RSSI:-71
Node:5 PVLV:0.76 PVC:-0.21 RSSI:-69
Node:5 BATLV:4.14 BATC:10.17 RSSI:-91
Node:3 V:3.80 U:15440281 RSSI:-89
Node:4 PVLV:4.65 PVC:81.44 RSSI:-71
Node:4 BATLV:4.18 BATC:-67.10 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:5 PVLV:0.76 PVC:-0.25 RSSI:-69
Node:5 BATLV:4.14 BATC:10.28 RSSI:-70
Node:3 V:3.80 U:15444386 RSSI:-73
Node:4 PVLV:4.63 PVC:83.14 RSSI:-79
Node:4 BATLV:4.18 BATC:-73.32 RSSI:-71
Node:4 RAIN:1 RSSI:-92
Node:5 PVLV:0.76 PVC:-0.14 RSSI:-74
Node:3 T:6899.00 H:73.00 RSSI:-72
Node:5 BATLV:4.14 BATC:10.25 RSSI:-74
Node:3 V:3.80 U:15448492 RSSI:-71
Node:4 PVLV:4.56 PVC:82.18 RSSI:-71
Node:4 BATLV:4.18 BATC:-69.58 RSSI:-92
Node:4 RAIN:1 RSSI:-71
Node:4 V:-1.00 U:3733600 RSSI:-71
Node:5 PVLV:0.76 PVC:-0.19 RSSI:-69
Node:5 BATLV:4.14 BATC:10.28 RSSI:-73
Node:3 V:3.80 U:15452596 RSSI:-71
Node:4 PVLV:4.52 PVC:81.48 RSSI:-71
Node:4 BATLV:4.18 BATC:-67.90 RSSI:-92
Node:4 RAIN:1 RSSI:-71
Node:5 PVLV:0.76 PVC:-0.14 RSSI:-74
Node:3 T:6908.00 H:73.00 RSSI:-71
Node:5 BATLV:4.14 BATC:10.23 RSSI:-76
Node:3 V:3.80 U:15456703 RSSI:-71
Node:4 PVLV:4.41 PVC:83.08 RSSI:-92
Node:4 BATLV:4.18 BATC:-73.32 RSSI:-71
Node:4 RAIN:1 RSSI:-72
Node:5 PVLV:0.76 PVC:-0.15 RSSI:-72
Node:5 BATLV:4.14 BATC:10.16 RSSI:-71
Node:3 V:3.80 U:15460811 RSSI:-71
Node:4 PVLV:4.29 PVC:86.58 RSSI:-92
Node:4 BATLV:4.18 BATC:-73.98 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:4 V:-1.00 U:3738868 RSSI:-70
Node:3 V:3.80 U:15464918 RSSI:-71
Node:4 PVLV:4.31 PVC:95.36 RSSI:-71
Node:4 BATLV:4.18 BATC:-76.34 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:3 V:3.80 U:15469024 RSSI:-71
Node:4 PVLV:4.54 PVC:104.66 RSSI:-92
Node:4 BATLV:4.18 BATC:-101.46 RSSI:-71
Node:4 RAIN:1 RSSI:-71
Node:3 V:3.80 U:15473130 RSSI:-92
Node:4 PVLV:4.64 PVC:109.36 RSSI:-71
Node:4 BATLV:4.18 BATC:-102.44 RSSI:-71
Node:4 RAIN:1 RSSI:-77
Node:4 V:-1.00 U:3744136 RSSI:-71


Nodes 3, 4 and 5 are online and in all respects seem to be operating normally.  However, Node 5 isn't being heard for several minutes (in the included output). Then Node 5 is heard for a few minutes... then a couple of node 5's packets are not heard... Then nothing.   Perhaps 5 to 10 minutes later (in this example) Node 5 started being heard again, with no indication from captured serial debug from Node5 that it stopped transmitting data.     

Since node 5 is giving me the most trouble, I even swapped out the RFM69HW with a new module, but the behavior hasn't changed.   

Could it be that since I am transmitting every 64 seconds that collisions are happening?  ...and that the 5th node doing so is the problem?  I have experimented with less frequent transmission, but that didn't seem to resolve the issue, just made it harder/longer to detect the missing data. 

What else can I do to troubleshoot this?   

n8twj

#1
And here is Node code
#include <LowPower.h>
#include <Wire.h>
#include <Adafruit_INA219.h>
#include "RunningAverage.h"
#include <SensorData.h>
#include "config.h"

byte sendLoops = 0;
float shuntVoltage = 0;
float busVoltage = 0;
float currentMa = 0;
float loadVoltage = 0;

void setup() {
#ifdef SERIAL_EN
  Serial.begin(SERIAL_BAUD);
#endif
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); 
#endif
  radio.encrypt(ENCRYPTKEY);

#ifdef ENABLE_ATC
  radio.enableAutoPower(-70);
#endif
  solar.begin();
  battery.begin();
  avgINA();
}

void txData(Payload d) {
  DEBUG("Tx message size ");
  DEBUG(sizeof(d));
  DEBUG(" message ");
  DEBUG(d.msg);
  DEBUGln();
  radio.send(GATEWAYID, (const void *)(&d), sizeof(d));
  delay(300);
}

void prepareData()  {
  Payload packet;
  packet.nodeId = NODEID;
  
  union sensor_data sensorData;
  sensorData.solar.loadVoltage = PVLoadVoltage.getAverage();
  sensorData.solar.currentMa = PVCurrent.getAverage();
  packet.msg = MESSAGE_SOLAR_DATA;
  packet.data = sensorData;
  txData(packet);
  
  sensorData.battery.loadVoltage = BattLoadVoltage.getAverage();
  sensorData.battery.currentMa = BattCurrent.getAverage();
  packet.msg = MESSAGE_BATTERY_DATA;
  packet.data = sensorData;
  txData(packet);

  *** Note: On Node 4 I have added in a system message with voltage reading and uptime - in hopes to detect a 328p reboot *** 
}

void loop() {
  if (sendLoops--<=0 ) {
    sendLoops = SEND_LOOPS-1;
    prepareData();
    Blink(LED,125);
  }
  avgINA();
  radio.sleep();
  LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF);
  DEBUGln("WAKEUP");
  Blink(LED, 10);
}

void avgINA() {
  shuntVoltage = solar.getShuntVoltage_mV();
  busVoltage = solar.getBusVoltage_V();
  currentMa = solar.getCurrent_mA();
  loadVoltage = busVoltage + (shuntVoltage / 1000);

  PVLoadVoltage.addValue(loadVoltage);
  PVCurrent.addValue(currentMa);

  shuntVoltage = battery.getShuntVoltage_mV();
  busVoltage = battery.getBusVoltage_V();
  currentMa = battery.getCurrent_mA();
  loadVoltage = busVoltage + (shuntVoltage / 1000);

  BattLoadVoltage.addValue(loadVoltage);
  BattCurrent.addValue(currentMa);
}

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



Censored config.h example (from a node)

#include <RFM69.h>
#include <RFM69_ATC.h>

//*********************************************************************************************
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NODEID        5    //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
#define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
#define FREQUENCY   RF69_433MHZ
#define ENCRYPTKEY    "[yeahright]" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define SERIAL_EN                //comment out if you don't want any serial output
#define SEND_LOOPS   8 //send data this many sleep loops
#define SLEEP_LONGEST SLEEP_8S
period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h)

//*********************************************************************************************

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#ifdef SERIAL_EN
  #define SERIAL_BAUD   115200
  #define DEBUG(input)   {Serial.print(input);}
  #define DEBUGln(input) {Serial.println(input);Serial.flush();}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

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

Adafruit_INA219 battery(0x42);
Adafruit_INA219 solar(0x41);

RunningAverage BattLoadVoltage(10);
RunningAverage BattCurrent(10);

RunningAverage PVLoadVoltage(10);
RunningAverage PVCurrent(10);


(too long for initial post)

Felix

Looks like your config is OK, you have HWs and IS_RFM69HW is defined, couldn't spot any other issue.
I would try it with ACKs, see if that makes a difference in behavior.
Otherwise as long as the hardware and radios are functional (provided wire antennas work great) everything should just work.
64s gap should in general not cause collisions. Collisions happen only when 2/more radios transmit at the same time.

perky

#3
Can I ask whether the gateway is in permanent receive mode? I assume it is and just receiving packets from the nodes as an when they transmit them, in which case it could be noise triggering the AFC on the receiver, and since that won't generate a payload ready the receiver would then be locked onto an offset frequency and will stop receiving genuine packets. To test this theory you could temporarily set the RSSI threshold of the receiver somewhat higher. It sounds to me like it's set quite low.
Mark.
Edit: I see you use ATC. I think that turns down the transmit power so that the receiver gets just enough signal it needs (-70dB I think in your case). I don't know whether this also adjusts the RSSI threshold or not, but I'm guessing it doesn't as you'd still want to receive packets from distant nodes as well as close nodes.

n8twj

on gateway all that happens in loop() process the received packet

pretty much: 

void loop { 
   if (radio.receiveDone()) {
    ..
   } 
} // repeat


n8twj

Quote from: Felix on September 16, 2016, 02:55:53 PM
64s gap should in general not cause collisions. Collisions happen only when 2/more radios transmit at the same time.

It seems that might be the issue... On Node 5, I increased the transmit interval to 1 second  (1 send loop and a SLEEP_1S)  and almost immediately Node 5 stopped getting heard (right as other nodes decided they needed to transmit, on their 64 sec interval) 


I enabled requesting ack:  radio.send(GATEWAYID, (const void *)(&d), sizeof(d), true);
and the associated if radio ack req, send ack right away on top of loop, inside of the if radio.recieveDone();

However, I didn't notice any behavior changes...  shouldn't I see the Gateway transmit the ACK (via RTL-SDR) ?   

I will play with radio.sendWithRetry() as well... 

Thank you for trying to help.

TomWS

Quote from: perky on September 16, 2016, 04:29:57 PM
Edit: I see you use ATC. I think that turns down the transmit power so that the receiver gets just enough signal it needs (-70dB I think in your case). I don't know whether this also adjusts the RSSI threshold or not, but I'm guessing it doesn't as you'd still want to receive packets from distant nodes as well as close nodes.
ATC shouldn't be doing anything since there are no Acks.  Without an Ack, there can be no feedback on RSSI recvd by the Gateway.

Tom

TomWS

Quote from: n8twj on September 16, 2016, 05:04:28 PM
However, I didn't notice any behavior changes...  shouldn't I see the Gateway transmit the ACK (via RTL-SDR) ?   
The Gateway won't send an Ack if you don't program it to send one.  If all you're doing is receiveDone() but not checking to see if an Ack is requested and sending one if it is, then no Ack will be sent.

As a head's up, if you DO want to send an Ack, save your incoming data in a local buffer before sending the Ack and then do your Serial outputs with the saved data.  This will be important given how quickly each of your nodes are sending to the Gateway.

Tom

perky

My bet is still on AFC, unless the transmitting time is very long or there's some synchronizing going on.
Mark.

n8twj

#9
Quote from: TomWS on September 16, 2016, 06:49:20 PM
The Gateway won't send an Ack if you don't program it to send one.  If all you're doing is receiveDone() but not checking to see if an Ack is requested and sending one if it is, then no Ack will be sent.

As a head's up, if you DO want to send an Ack, save your incoming data in a local buffer before sending the Ack and then do your Serial outputs with the saved data.  This will be important given how quickly each of your nodes are sending to the Gateway.

Tom

Something like this?

void loop() {
  Payload packet;
 
   
  if (radio.receiveDone()) {
    packet = *(Payload*)radio.DATA;
    if (radio.ACKRequested()) {
      radio.sendACK();
    }
   
    Serial.print("Node:");
    Serial.print(packet.nodeId, DEC);
    Serial.print(" ");
   ...


Or allocate a new buffer and memcpy?  (my C skillz are still quite noobish :)


TomWS

Quote from: n8twj on September 17, 2016, 09:41:04 AM
Quote from: TomWS on September 16, 2016, 06:49:20 PM
The Gateway won't send an Ack if you don't program it to send one.  If all you're doing is receiveDone() but not checking to see if an Ack is requested and sending one if it is, then no Ack will be sent.

As a head's up, if you DO want to send an Ack, save your incoming data in a local buffer before sending the Ack and then do your Serial outputs with the saved data.  This will be important given how quickly each of your nodes are sending to the Gateway.

Tom

Something like this?

Depends on what you need to process.  From your original code it appears that you need radio.DATA & radio.RSSI.  It looks like you're copying the Payload so you only need to save radio.RSSI.  I've updated the code below:
Quote

void loop() {
  Payload packet;
  int8_t    recvdRSSI;
   
  if (radio.receiveDone()) {
    packet = *(Payload*)radio.DATA;   //TomWS: This will copy the largest payload you can have.  If you want more control, do the following instead:
    memcpy(&packet, radio.DATA, min(radio.DATALEN, sizeof(Payload)));

    recvdRSSI = radio.RSSI;  //TomWS:  Add this line.

    if (radio.ACKRequested()) {
      radio.sendACK();
    }
   
    Serial.print("Node:");
    Serial.print(packet.nodeId, DEC);
    Serial.print(" ");
   ...


Or allocate a new buffer and memcpy?  (my C skillz are still quite noobish :)

n8twj

Thank you TomWS...  I implemented your recommended changes.   However, I still have two nodes that now refuse to be heard by the gateway.

As a test, I loaded the example "Gateway" and "Node" example scripts on all of my nodes (and gateway)....I experience the same exact behavior.  Nodes 4 and 5 are almost never received...even when i only have a single node is powered up.  I do see a transmission on the RTL-SDR waterfall display), so the RFM69HW does seem to be transmitting "something"  (Here is a slightly older screenshot showing the CubicSDR display http://imgur.com/a/s89w8)

What really blows my mind is I can turn Node 4 (moteino) into the gateway and the gateway (moteino usb) into node 4 and everything starts working perfectly (for over a day) ?!?!?!   Then I switch things back to "normal" (gateway on the Moteino USB) and the node is now not heard :( 

I have a few more RFM69HWs, i'm going to swap them out on the two 'broken' nodes and be really accurate on the length of the antenna, just in case a high SWR has caused some sort of partial failure within the radio. 

n8twj

Here is all of my code, just in case I am doing something very wrong  and/or someone else wants to see how I send/receive binary data using Moetino's and RFM69HW


SensorData.h
#ifndef _SensorData_H
#define _SensorData_H

#define TEST_DATA 0x0000
struct test_sensors {
  int a;
  float b;
};

#define MESSAGE_SYSTEM 0X0001
struct system_data {
  float voltage;
  unsigned long uptime;
};

#define MESSAGE_ENVRIONMENT 0x0002
struct envrionment_data {
  float temp;
  float humidity;
  float pressure;
};

#define MESSAGE_WIND_DATA 0x0003
struct wind_data {
  float speed;
  float direction;
};

#define MESSAGE_RAIN_DATA 0x0004
struct rain_data {
  int amount;
};

#define MESSAGE_BATTERY_DATA 0x0005
#define MESSAGE_SOLAR_DATA 0x0006
#define MESSAGE_LOAD_DATA 0x0007
struct power_sensors {
  float loadVoltage;
  float currentMa;
};

union sensor_data {
  struct test_sensors test;
  struct system_data system;
  struct envrionment_data env;
  struct wind_data wind;
  struct rain_data rain;
  struct power_sensors battery;
  struct power_sensors solar;
  struct power_sensors load;
};

typedef struct {
  int nodeId;
  int msg;
  sensor_data data;
} Payload;

#endif // _SensorData_H


WeatherGateway.ino  [wrote to a Moetino USB]

#include <RFM69.h>
#include <RFM69_ATC.h>
#include <Wire.h>

#include <SensorData.h>
#include "config.h"

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);
  radio.promiscuous(true);
  Blink(LED,50);
}

byte ackCount=0;
uint32_t packetCount = 0;
void loop() {
  Payload packet;
  int8_t recvdRSSI;
  
  if (radio.receiveDone()) {
    packet = *(Payload*)radio.DATA;
    recvdRSSI = radio.RSSI;
    
    if (radio.ACKRequested()) {
      radio.sendACK();
      Serial.print("ACK:1");
    }
   
    Serial.print("Node:");
    Serial.print(packet.nodeId, DEC);
    Serial.print(" ");

    switch(packet.msg)  {
    case MESSAGE_SYSTEM:
      Serial.print("V:");
      Serial.print(packet.data.system.voltage);
      Serial.print(" U:");
      Serial.print(packet.data.system.uptime);
      break;
    case MESSAGE_BATTERY_DATA:
      Serial.print("BATLV:");
      Serial.print(packet.data.battery.loadVoltage);
      Serial.print(" BATC:");
      Serial.print(packet.data.battery.currentMa);
      break;
    case MESSAGE_SOLAR_DATA:
      Serial.print("PVLV:");
      Serial.print(packet.data.solar.loadVoltage);
      Serial.print(" PVC:");
      Serial.print(packet.data.solar.currentMa);
      break;
    case MESSAGE_RAIN_DATA:
      Serial.print("RAIN:");
      Serial.print(abs(packet.data.rain.amount - 1024)); // reverse sense for graphing
      break;
    case MESSAGE_ENVRIONMENT:
      Serial.print("T:");
      Serial.print(packet.data.env.temp);
      Serial.print(" H:");
      Serial.print(packet.data.env.humidity);
      if (packet.data.env.pressure != -1.00) {
        Serial.print(" P:");
        Serial.print(packet.data.env.pressure);
      }
      break;
    case MESSAGE_WIND_DATA:
      Serial.print("WindDir:");
      Serial.print(packet.data.wind.direction);
      Serial.print(" WindSpeed:");
      Serial.print(packet.data.wind.speed);
      break;
    default:
      Serial.print("WTF:1");
    }
    Serial.print(" RSSI:");
    Serial.print(recvdRSSI);
    Serial.println();
  } 
}

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


Weather Gateway's config.h
#include <RFM69.h>
#include <RFM69_ATC.h>
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NODEID        1    //unique for each node on same network (gateway should be 1)
#define NETWORKID     100  //the same on all nodes that talk to each other
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
#define FREQUENCY     RF69_433MHZ
#define ENCRYPTKEY    "--[yeah right]--" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
//*********************************************************************************************

#define SERIAL_BAUD   115200

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

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




n8twj

WeatherNode 5.ino (loaded on to a Moteino)
#include <RFM69.h>
#include <RFM69_ATC.h>
#include <LowPower.h>

#include <Wire.h>
#include <Adafruit_INA219.h>
#include "RunningAverage.h"

#include <SensorData.h>
#include "config.h"

byte sendLoops = 0;

float shuntVoltage = 0;
float busVoltage = 0;
float currentMa = 0;
float loadVoltage = 0;

void setup() {
#ifdef SERIAL_EN
  Serial.begin(SERIAL_BAUD);
#endif
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW
  radio.setHighPower(); //uncomment only for RFM69HW!
#endif
  radio.encrypt(ENCRYPTKEY);

#ifdef ENABLE_ATC
//  radio.enableAutoPower(-40);
#endif
  solar.begin();
  battery.begin();
  avgINA();
  DEBUGln("Weather Node Boot");
  delay(2000);  // RFM69 seems to need a moment to sort itself out (otherwise the first loop'd TX doesn't happen)
 }

void txData(Payload d) {
  DEBUG("Tx message size ");
  DEBUG(sizeof(d));
  DEBUG(" message ");
  DEBUG(d.msg);
  DEBUGln();
  radio.send(GATEWAYID, (const void *)(&d), sizeof(d), true);
  delay(300);
}

void prepareData()  {
  Payload packet;
  packet.nodeId = NODEID;
  
  union sensor_data sensorData;
#if 0
  sensorData.solar.loadVoltage = PVLoadVoltage.getAverage();
  sensorData.solar.currentMa = PVCurrent.getAverage();
  packet.msg = MESSAGE_SOLAR_DATA;
  packet.data = sensorData;
  txData(packet);
  
  sensorData.battery.loadVoltage = BattLoadVoltage.getAverage();
  sensorData.battery.currentMa = BattCurrent.getAverage();
  packet.msg = MESSAGE_BATTERY_DATA;
  packet.data = sensorData;
  txData(packet);
#endif

  sensorData.system.voltage = -1;
  sensorData.system.uptime = millis();
  packet.msg = MESSAGE_SYSTEM;
  packet.data = sensorData;
  txData(packet);
}

void loop() {
  if (sendLoops--<=0 ) {
    sendLoops = SEND_LOOPS-1;
    prepareData();
    Blink(LED,125);
  }
  avgINA();
  //radio.sleep();
  //LowPower.powerDown(sleepTime, ADC_OFF, BOD_OFF);
  delay(1000);
  DEBUGln("WAKEUP");
  Blink(LED, 10);
}

void avgINA() {
  shuntVoltage = solar.getShuntVoltage_mV();
  busVoltage = solar.getBusVoltage_V();
  currentMa = solar.getCurrent_mA();
  loadVoltage = busVoltage + (shuntVoltage / 1000);

  PVLoadVoltage.addValue(loadVoltage);
  PVCurrent.addValue(currentMa);

  shuntVoltage = battery.getShuntVoltage_mV();
  busVoltage = battery.getBusVoltage_V();
  currentMa = battery.getCurrent_mA();
  loadVoltage = busVoltage + (shuntVoltage / 1000);

  BattLoadVoltage.addValue(loadVoltage);
  BattCurrent.addValue(currentMa);
}

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


Weather Node 5's config.h
#include <RFM69.h>
#include <RFM69_ATC.h>

//*********************************************************************************************
//************ IMPORTANT SETTINGS - YOU MUST CHANGE/CONFIGURE TO FIT YOUR HARDWARE *************
//*********************************************************************************************
#define NODEID        5    //must be unique for each node on same network (range up to 254, 255 is used for broadcast)
#define NETWORKID     100  //the same on all nodes that talk to each other (range up to 255)
#define GATEWAYID     1
//Match frequency to the hardware version of the radio on your Moteino (uncomment one):
#define FREQUENCY   RF69_433MHZ
#define ENCRYPTKEY    "--[yeah right]--" //exactly the same 16 characters/bytes on all nodes!
#define IS_RFM69HW    //uncomment only for RFM69HW! Leave out if you have RFM69W!
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define SERIAL_EN                //comment out if you don't want any serial output
#define SEND_LOOPS   1 //send data this many sleep loops
#define SLEEP_LONGEST SLEEP_1S 
period_t sleepTime = SLEEP_LONGEST; //period_t is an enum type defined in the LowPower library (LowPower.h)

//*********************************************************************************************

#ifdef __AVR_ATmega1284P__
  #define LED           15 // Moteino MEGAs have LEDs on D15
  #define FLASH_SS      23 // and FLASH SS on D23
#else
  #define LED           9 // Moteinos have LEDs on D9
  #define FLASH_SS      8 // and FLASH SS on D8
#endif

#ifdef SERIAL_EN
  #define SERIAL_BAUD   115200
  #define DEBUG(input)   {Serial.print(input);}
  #define DEBUGln(input) {Serial.println(input);Serial.flush();}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

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

Adafruit_INA219 battery(0x42);
Adafruit_INA219 solar(0x41);

RunningAverage BattLoadVoltage(10);
RunningAverage BattCurrent(10);

RunningAverage PVLoadVoltage(10);
RunningAverage PVCurrent(10);



Perl script to send data to MQTT
#!/usr/bin/perl                                                                            
use strict;
use warnings;
use Device::SerialPort;
use Net::MQTT::Simple;
use Data::Dumper; 

$| = 1;

my $mqtt = Net::MQTT::Simple->new("mqtt.indie.org");

my $PORT = '/dev/ttyUSB0';
my $ob = Device::SerialPort->new($PORT) || die "Can't Open $PORT: $!";

$ob->baudrate(115200)    || die "failed setting baudrate";
$ob->parity("none")    || die "failed setting parity";
$ob->databits(8)       || die "failed setting databits";
$ob->handshake("none") || die "failed setting handshake";
$ob->write_settings || die "no settings";

open( DEV, "<$PORT" ) || die "Cannot open $PORT: $_";

while ( $_ = <DEV> ) {    # print input device to file 
  my $line = $_; 
  print $line;
  chomp $line;

  my %hash = split /[: ]/, $line;
  if (!$hash{"Node"}) {
   print "No Node ID\n";
   next;  
  }
  my $topic = 'sensors/' . $hash{'Node'};

  $mqtt->publish($topic . '/rssi' => 'value=' . $hash{"RSSI"});
  
  if ($hash{"H"} && $hash{"T"}) {
    my $temp = $hash{"T"} / 100;
    $mqtt->publish($topic . '/humidity' => 'value=' . $hash{"H"});
    $mqtt->publish($topic . '/temperature' => 'value=' . $temp);
  }  
  $mqtt->publish($topic . '/pressure' => 'value=' . $hash{"P"}) if $hash{"P"};
  $mqtt->publish($topic . '/voltage' => 'value=' . $hash{"V"}) if $hash{"V"};
  $mqtt->publish($topic . '/PVLoadVoltage' => 'value=' . $hash{"PVLV"}) if $hash{"PVLV"};
  $mqtt->publish($topic . '/PVCurrent' => 'value=' . $hash{"PVC"}) if $hash{"PVC"};
  $mqtt->publish($topic . '/BatteryLoadVoltage' => 'value=' . $hash{"BATLV"}) if $hash{"BATLV"};
  $mqtt->publish($topic . '/BatteryCurrent' => 'value=' . $hash{"BATC"}) if $hash{"BATC"};
  $mqtt->publish($topic . '/RainAmount' => 'value=' . $hash{"RAIN"}) if $hash{"RAIN"};
}

undef $ob;

TomWS

I see that you now have the sendAck code in your gateway but your node code is using send(), rather than sendWithRetry() so your code is not getting the Ack or checking to see if the transmission was successfully received.  I would recommend using sendWithRetry() with retry count set to 0.  This will send once, wait for the Ack, and return a return code to indicate if the send succeeded or not.

Tom