Author Topic: Getting Random Results from sendWithRetry()  (Read 4173 times)

handyguy

  • NewMember
  • *
  • Posts: 27
Getting Random Results from sendWithRetry()
« on: January 11, 2019, 08:32:25 PM »
I've been working on an issue that's been driving me crazy, so I'm hoping someone here can help solve my puzzle. Basically, when I use sendWithRetry() in my code I get random results, meaning sometime it works, sometimes it doesn't.

Equipment:
"Node": Moteino USB, RFM69HCW - 868/915Mhz, 4mb flash
"Gateway": RPi 3B+, with Moteino USB attached

I'm using the PIGateway code found at https://github.com/LowPowerLab/RaspberryPi-Gateway. The code on the Gateway Moteino is (almost) stock from the web site.:

Code: [Select]
// **********************************************************************************************************
// Moteino gateway/base sketch that works with Moteinos equipped with RFM69W/RFM69HW/RFM69CW/RFM69HCW
// This is a basic gateway sketch that receives packets from end node Moteinos, formats them as ASCII strings
//      with the end node [ID] and passes them to Pi/host computer via serial port
//     (ex: "messageFromNode" from node 123 gets passed to serial as "[123] messageFromNode")
// It also listens to serial messages that should be sent to listening end nodes
//     (ex: "123:messageToNode" sends "messageToNode" to node 123)
// Make sure to adjust the settings to match your transceiver settings (frequency, HW etc).
// **********************************************************************************
// Copyright Felix Rusu 2016, http://www.LowPowerLab.com/contact
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU General   
// Public License as published by the Free Software       
// Foundation; either version 3 of the License, or       
// (at your option) any later version.                   
//                                                       
// This program is distributed in the hope that it will   
// be useful, but WITHOUT ANY WARRANTY; without even the 
// implied warranty of MERCHANTABILITY or FITNESS FOR A   
// PARTICULAR PURPOSE. See the GNU General Public       
// License for more details.                             
//                                                 
// Licence can be viewed at                               
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************
#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)

//****************************************************************************************************************
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
//****************************************************************************************************************
#define NODEID          1 //the ID of this node
#define NETWORKID     200 //the network ID of all nodes this node listens/talks to
#define FREQUENCY     RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY    "XXXXXXXXXXXXXXXX" //identical 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW_HCW  //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
#define ACK_TIME       30  // # of ms to wait for an ack packet
//*****************************************************************************************************************************
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI      -75  //target RSSI for RFM69_ATC (recommended > -80)
//*****************************************************************************************************************************
// Serial baud rate must match your Pi/host computer serial port baud rate!
#define SERIAL_EN     //comment out if you don't want any serial verbose output
#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 SERIAL_EN
  #define DEBUG(input)   {Serial.print(input); delay(1);}
  #define DEBUGln(input) {Serial.println(input); delay(1);}
//  #define DEBUG(input)   {Serial.print(input);}
//  #define DEBUGln(input) {Serial.println(input);}
#else
  #define DEBUG(input);
  #define DEBUGln(input);
#endif

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

SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond FlashMEM chip

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW_HCW
  radio.setHighPower(); //must include this only for RFM69HW/HCW!
#endif
  radio.encrypt(ENCRYPTKEY);
 
#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif
 
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", radio.getFrequency()/1000000);
  DEBUGln(buff);

  if (flash.initialize())
  {
    DEBUGln("SPI Flash Init OK!");
  }
  else
  {
    DEBUGln("SPI FlashMEM not found (is chip onboard?)");
  }
}

byte ackCount=0;
byte inputLen=0;
char input[64];
byte buff[61];
String inputstr;

void loop() {
  inputLen = readSerialLine(input);
  inputstr = String(input);
  inputstr.toUpperCase();
 
  if (inputLen > 0)
  {
    if (inputstr.equals("KEY?"))
    {
      DEBUG("ENCRYPTKEY:");
      DEBUG(ENCRYPTKEY);
    }
   
    byte targetId = inputstr.toInt(); //extract ID if any
    byte colonIndex = inputstr.indexOf(":"); //find position of first colon

    if (targetId > 0)
    {
      inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any
    }

    if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0)
    {
      inputstr.getBytes(buff, 61);
      //DEBUGln((char*)buff);
      //DEBUGln(targetId);
      //DEBUGln(colonIndex);
      if (radio.sendWithRetry(targetId, buff, inputstr.length()))
      {
        DEBUGln("ACK:OK");
      }
      else
        DEBUGln("ACK:NOK");
    }
  }

  if (radio.receiveDone())
  {
    int rssi = radio.RSSI;
    DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
    if (radio.DATALEN > 0)
    {
      for (byte i = 0; i < radio.DATALEN; i++)
        DEBUG((char)radio.DATA[i]);
      DEBUG("   [RSSI:");DEBUG(rssi);DEBUG("]");
    }

    CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG

    if (radio.ACKRequested())
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      DEBUG("[ACK-sent]");
    }
    DEBUGln();
    Blink(LED,3);
  }
}

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

On the "node" side, I'm again using the stock example code from John's web site. The only changes I've made are to capture the result from sendWithRetry() and add MAXRETRIES and MAXTIMEOUT to lengthen those options (the default options weren't working):

Code: [Select]
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
//   1. It will flash the onboard LED located at pin D9
//   2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
//   3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
//     Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
//      NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h>         //get it here: http://github.com/lowpowerlab/rfm69
#include <SPIFlash.h>      //get it here: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //get it here: https://github.com/LowPowerLab/WirelessProgramming
#include <SPI.h>           //comes with Arduino IDE (www.arduino.cc)

#define SERIAL_EN          //comment out if you don't want any serial output

//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID   1    // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID      44   // must be unique to each sensor node
#define NETWORKID   200  // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY       RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY      "XXXXXXXXXXXXXXXX" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW      //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************

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

// Define our pins
#define onboardLED     9   // Moteino onboard LED is on digital pin 9
#define photoResistor   A5
#define photoResistorPower  A2   // The photoresistor will be hooked to pins A2 and A5
#define externalLED   3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
              // For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!

// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000;  // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;

// The next variable defines how often to check the photoresistor's light level
//const long photoResistorCheckTime = 30000;  // 10000 milliseconds is 10 seconds
const long photoResistorCheckTime = 5000;  // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;

// We don't need to define how often to check commands to turn on/off the external LED.  That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus; 

char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";   //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)

#define MAXRETRIES     5
#define MAXTIMEOUT  50

void setup() {
  #ifdef SERIAL_EN
    Serial.begin(SERIAL_BAUD);
  #endif

  // Tell Moteino if our pins are inputs or outputs
  pinMode(onboardLED, OUTPUT);
  pinMode(photoResistor, INPUT);
  pinMode(photoResistorPower, OUTPUT);
  pinMode(externalLED, OUTPUT);

  // Initialize our onboard and external LEDs to start up turned off (set to low)
  digitalWrite(onboardLED, LOW);
  digitalWrite(externalLED, LOW);
 
  // Turn on power to the photoresistor
  digitalWrite(photoResistorPower, HIGH);
 
  // Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
  lastBlinkTime = millis();
  lastPhotoResistorReport = millis();
 
  char buff[20];  // create a variable called buff (short for "buffer") that can hold up to 20 characters
 
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
     radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);
 
  if (flash.initialize()){
    DEBUGln("EEPROM flash chip found, and is OK ...");
  }
  else
    DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
 
 
  sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
  DEBUGln(payload);  // check what we are transmitting to the gateway receiver
  byte buffLen=strlen(payload);
  if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
  {
    DEBUGln("Init: ACK Success!");
  }
  else
  {
    DEBUGln("Init: ACK Fail!");
  }
 
  // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
  if (radio.sendWithRetry(GATEWAYID, "9900:0", 6, MAXRETRIES, MAXTIMEOUT))
  {
    DEBUGln("Startup: ACK Success!");
  }
  else
  {
    DEBUGln("Startup: ACK Fail!");
  }
  delay(5000);
}

void loop() {
   // wireless programming token check
   // DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
   //CheckForWirelessHEX(radio, flash, true);

  // check for messages from the home automation gateway or other Moteino nodes 
    if (radio.receiveDone()){
      DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
      for (byte i = 0; i < radio.DATALEN; i++)
          DEBUG((char)radio.DATA[i]);
      DEBUGln();
      //first send any ACK to request
      DEBUG("   [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
      DEBUG("   Payload length = ");
      DEBUGln(radio.DATALEN); 
   
      if (radio.DATALEN==3){
          //check for a web page request from Pi Gateway to turn on or off the external LED
          //we will receive from the Pi Gateway either a message of "LOF" or LON"
          if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){    // "LOF" is short for "LED off", keep radio messages short for best results
            digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
            ledStatus = 0;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
                              // We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
                              // to a lot of sensor nodes in our house.  Each sensor node gets its own set of 4-digit codes.
                              // Any time we transmit an LED status, we will always identify it with sensor code "9900"
          }
          else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){  // "LON" is short for "LED on"
            digitalWrite(externalLED, HIGH);  // Tell our external LED to turn ON
            ledStatus = 1;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off
          }
      }
    }

    if (radio.ACKRequested())
    {
      radio.sendACK();
      DEBUGln("ACK sent.");
    }

  // check if the onboard LED should be turned on or off
  if ((millis() - lastBlinkTime) >= blinkLEDtime) {
      lastBlinkTime = millis();  // update current time for the next time through the loop
      digitalWrite(onboardLED, !digitalRead(onboardLED));  // this says in one simple line to flip-flop the status of the pin
  }

  // check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
  if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
      lastPhotoResistorReport = millis();   // update current time for the next time through the loop
      int lightLevel = analogRead(photoResistor);  // we read in the photoResistor level here (value can be 0 to 4095)
     
      // publish the actual value of the light level.  We will call this sensor ID data code "9912"
      transmitStatus(9905, lightLevel);
  }
}  // this is the end of the loop


// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){ 
    sprintf(payload, "%d:%d", item, status);
    byte buffLen=strlen(payload);
    if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
    {
      DEBUGln("XMit ACK - Success!");
    }
    else
    {
      DEBUGln("XMit ACK - Fail!");
    }

    DEBUG("Transmitted payload: ");
    DEBUGln(payload);
    delay(10);
}

When I run the sketch on the node, here's what I see on the serial monitor:

Code: [Select]
18:30:37.115 -> EEPROM flash chip found, and is OK ...
18:30:37.115 -> Moteino Example : 915 Mhz...
18:30:37.419 -> Init: ACK Fail!
18:30:37.748 -> Startup: ACK Fail!
18:30:42.756 -> Msg received from sender ID [1]
18:30:42.756 ->    [RX_RSSI:-31]
18:30:42.756 ->    Payload length = 0
18:30:42.931 -> XMit ACK - Success!
18:30:42.931 -> Transmitted payload: 9905:751
18:30:47.934 -> XMit ACK - Success!
18:30:47.934 -> Transmitted payload: 9905:752
18:30:52.978 -> XMit ACK - Success!
18:30:52.978 -> Transmitted payload: 9905:746
18:30:57.992 -> XMit ACK - Success!
18:30:57.992 -> Transmitted payload: 9905:746
18:31:03.005 -> XMit ACK - Success!
18:31:03.005 -> Transmitted payload: 9905:751
18:31:08.006 -> XMit ACK - Fail!
18:31:08.006 -> Transmitted payload: 9905:756
18:31:08.006 -> Msg received from sender ID [1]
18:31:08.006 ->    [RX_RSSI:-32]
18:31:08.041 ->    Payload length = 0
18:31:12.998 -> XMit ACK - Fail!
18:31:12.998 -> Transmitted payload: 9905:749
18:31:13.043 -> Msg received from sender ID [1]
18:31:13.043 ->    [RX_RSSI:-31]
18:31:13.043 ->    Payload length = 0
18:31:17.993 -> XMit ACK - Fail!
18:31:17.993 -> Transmitted payload: 9905:745
18:31:18.031 -> Msg received from sender ID [1]
18:31:18.031 ->    [RX_RSSI:-32]
18:31:18.066 ->    Payload length = 0
18:31:22.999 -> XMit ACK - Fail!
18:31:22.999 -> Transmitted payload: 9905:746
18:31:23.037 -> Msg received from sender ID [1]
18:31:23.037 ->    [RX_RSSI:-32]
18:31:23.037 ->    Payload length = 0

Lots of failed ACKs. So, I figure that maybe the transmissions aren't getting to the gateway. But when I look at the logs from the gateway, I see:

Code: [Select]
6:31:33 PM : {"_id":44,"updated":1547253092959,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547253092959,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:28 PM : {"_id":44,"updated":1547253087949,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547253087949,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:23 PM : {"_id":44,"updated":1547253082939,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253082939,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:18 PM : {"_id":44,"updated":1547253077915,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":745,"unit":" level","updated":1547253077915,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:13 PM : {"_id":44,"updated":1547253072907,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":749,"unit":" level","updated":1547253072907,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:08 PM : {"_id":44,"updated":1547253067897,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547253067897,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:31:03 PM : {"_id":44,"updated":1547253062889,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547253062889,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:58 PM : {"_id":44,"updated":1547253057879,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253057879,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:53 PM : {"_id":44,"updated":1547253052870,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253052870,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:47 PM : {"_id":44,"updated":1547253047811,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547253047811,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:42 PM : {"_id":44,"updated":1547253042802,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547253042802,"pin":0},"LED Status":{"label":"LED Status","value":"OFF","updated":1547252961598}}}
6:30:37 PM : {"_id":44,"updated":1547253037790,"type":"JohnsDIYexample","label":"Johns DIY Example","descr":"[44]","metrics":{"Light Level":{"label":"Light Level","value":746,"unit":" level","updated":1547253031760,"pin":0},"LED Status":{"label":"LED

The initial "startup" transmissions aren't getting there, but the "light level" transmissions are. Hmmm.


[Continued in next post]

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #1 on: January 11, 2019, 08:33:06 PM »
[Continued from previous post]

So then I changed the "node" code to move the initial startup transmissions out of startup() and into loop() (which was a problem with other arduino projects I've done):

Code: [Select]
if (flash.initialize()){
    DEBUGln("EEPROM flash chip found, and is OK ...");
  }
  else
    DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");
 
 
}

bool started = false;

void loop() {

    if (!started) // only do first time through loop
    {
      sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
      DEBUGln(payload);  // check what we are transmitting to the gateway receiver
      byte buffLen=strlen(payload);
      if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
      {
        DEBUGln("Init: ACK Success!");
      }
      else
      {
        DEBUGln("Init: ACK Fail!");
      }
     
      // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
      if (radio.sendWithRetry(GATEWAYID, "9900:0", 6, MAXRETRIES, MAXTIMEOUT))
      {
        DEBUGln("Startup: ACK Success!");
      }
      else
      {
        DEBUGln("Startup: ACK Fail!");
      }
      delay(5000);
      started = true;
    }

   // wireless programming token check
   // DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
   //CheckForWirelessHEX(radio, flash, true);

  // check for messages from the home automation gateway or other Moteino nodes 
    if (radio.receiveDone()){

(For brevity, I only showed the changed code here). I get similar results from the serial monitor:

Code: [Select]
18:33:37.587 -> EEPROM flash chip found, and is OK …
18:33:37.587 -> Moteino Example : 915 Mhz...
18:33:37.868 -> Init: ACK Fail!
18:33:38.198 -> Startup: ACK Fail!
18:33:43.210 -> Msg received from sender ID [1]
18:33:43.210 ->    [RX_RSSI:-31]
18:33:43.210 ->    Payload length = 0
18:33:43.339 -> XMit ACK - Success!
18:33:43.339 -> Transmitted payload: 9905:757
18:33:48.381 -> XMit ACK - Success!
18:33:48.381 -> Transmitted payload: 9905:750
18:33:53.381 -> XMit ACK - Success!
18:33:53.381 -> Transmitted payload: 9905:746
18:33:58.393 -> XMit ACK - Success!
18:33:58.393 -> Transmitted payload: 9905:747
18:34:03.398 -> XMit ACK - Success!
18:34:03.398 -> Transmitted payload: 9905:753
18:34:08.422 -> XMit ACK - Success!
18:34:08.422 -> Transmitted payload: 9905:757
18:34:13.435 -> XMit ACK - Success!
18:34:13.435 -> Transmitted payload: 9905:748
18:34:18.442 -> XMit ACK - Success!
18:34:18.442 -> Transmitted payload: 9905:745
18:34:23.434 -> XMit ACK - Success!
18:34:23.434 -> Transmitted payload: 9905:750
18:34:28.407 -> XMit ACK - Fail!
18:34:28.454 -> Transmitted payload: 9905:757
18:34:28.454 -> Msg received from sender ID [1]
18:34:28.454 ->    [RX_RSSI:-31]
18:34:28.454 ->    Payload length = 0
18:34:33.399 -> XMit ACK - Fail!
18:34:33.399 -> Transmitted payload: 9905:754
18:34:33.470 -> Msg received from sender ID [1]
18:34:33.470 ->    [RX_RSSI:-30]
18:34:33.470 ->    Payload length = 0
18:34:38.430 -> XMit ACK - Fail!
18:34:38.430 -> Transmitted payload: 9905:747
18:34:38.466 -> Msg received from sender ID [1]
18:34:38.466 ->    [RX_RSSI:-30]
18:34:38.466 ->    Payload length = 0
18:34:43.402 -> XMit ACK - Fail!
18:34:43.402 -> Transmitted payload: 9905:745
18:34:43.489 -> Msg received from sender ID [1]
18:34:43.489 ->    [RX_RSSI:-31]
18:34:43.489 ->    Payload length = 0

Finally, I take notice of several posts on this forum complaining of not immediately sending the ACK reply before trying to manipulate incoming data, so I altered the "gateway" code to do just that:

Code: [Select]
// **********************************************************************************************************
// Moteino gateway/base sketch that works with Moteinos equipped with RFM69W/RFM69HW/RFM69CW/RFM69HCW
// This is a basic gateway sketch that receives packets from end node Moteinos, formats them as ASCII strings
//      with the end node [ID] and passes them to Pi/host computer via serial port
//     (ex: "messageFromNode" from node 123 gets passed to serial as "[123] messageFromNode")
// It also listens to serial messages that should be sent to listening end nodes
//     (ex: "123:messageToNode" sends "messageToNode" to node 123)
// Make sure to adjust the settings to match your transceiver settings (frequency, HW etc).
// **********************************************************************************
// Copyright Felix Rusu 2016, http://www.LowPowerLab.com/contact
// **********************************************************************************
// License
// **********************************************************************************
// This program is free software; you can redistribute it
// and/or modify it under the terms of the GNU General   
// Public License as published by the Free Software       
// Foundation; either version 3 of the License, or       
// (at your option) any later version.                   
//                                                       
// This program is distributed in the hope that it will   
// be useful, but WITHOUT ANY WARRANTY; without even the 
// implied warranty of MERCHANTABILITY or FITNESS FOR A   
// PARTICULAR PURPOSE. See the GNU General Public       
// License for more details.                             
//                                                 
// Licence can be viewed at                               
// http://www.gnu.org/licenses/gpl-3.0.txt
//
// Please maintain this license information along with authorship
// and copyright notices in any redistribution of this code
// **********************************************************************************
#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)

//****************************************************************************************************************
//**** IMPORTANT RADIO SETTINGS - YOU MUST CHANGE/CONFIGURE TO MATCH YOUR HARDWARE TRANSCEIVER CONFIGURATION! ****
//****************************************************************************************************************
#define NODEID          1 //the ID of this node
#define NETWORKID     200 //the network ID of all nodes this node listens/talks to
#define FREQUENCY     RF69_915MHZ //Match this with the version of your Moteino! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY    "XXXXXXXXXXXXXXXX" //identical 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW_HCW  //uncomment only for RFM69HW/HCW! Leave out if you have RFM69W/CW!
#define ACK_TIME       30  // # of ms to wait for an ack packet
//*****************************************************************************************************************************
#define ENABLE_ATC    //comment out this line to disable AUTO TRANSMISSION CONTROL
#define ATC_RSSI      -75  //target RSSI for RFM69_ATC (recommended > -80)
//*****************************************************************************************************************************
// Serial baud rate must match your Pi/host computer serial port baud rate!
#define SERIAL_EN     //comment out if you don't want any serial verbose output
#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 SERIAL_EN
  #define DEBUG(input)   Serial.print(input)
  #define DEBUGln(input) Serial.println(input)
  #define SERIALFLUSH()  Serial.flush()
#else
  #define DEBUG(input);
  #define DEBUGln(input);
  #define SERIALFLUSH();
#endif

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

SPIFlash flash(FLASH_SS, 0xEF30); //EF30 for 4mbit Windbond FlashMEM chip

void setup() {
  Serial.begin(SERIAL_BAUD);
  delay(10);
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
#ifdef IS_RFM69HW_HCW
  radio.setHighPower(); //must include this only for RFM69HW/HCW!
#endif
  radio.encrypt(ENCRYPTKEY);
 
#ifdef ENABLE_ATC
  radio.enableAutoPower(ATC_RSSI);
#endif
 
  char buff[50];
  sprintf(buff, "\nTransmitting at %d Mhz...", radio.getFrequency()/1000000);
  DEBUGln(buff);

  if (flash.initialize())
  {
    DEBUGln("SPI Flash Init OK!");
  }
  else
  {
    DEBUGln("SPI FlashMEM not found (is chip onboard?)");
  }
}

byte ackCount=0;
byte inputLen=0;
char input[64];
byte buff[61];
String inputstr;

void loop() {
  inputLen = readSerialLine(input);
  inputstr = String(input);
  inputstr.toUpperCase();
 
  if (inputLen > 0)
  {
    if (inputstr.equals("KEY?"))
    {
      DEBUG("ENCRYPTKEY:");
      DEBUG(ENCRYPTKEY);
    }
   
    byte targetId = inputstr.toInt(); //extract ID if any
    byte colonIndex = inputstr.indexOf(":"); //find position of first colon

    if (targetId > 0)
    {
      inputstr = inputstr.substring(colonIndex+1); //trim "ID:" if any
    }

    if (targetId > 0 && targetId != NODEID && targetId != RF69_BROADCAST_ADDR && colonIndex>0 && colonIndex<4 && inputstr.length()>0)
    {
      inputstr.getBytes(buff, 61);
      //DEBUGln((char*)buff);
      //DEBUGln(targetId);
      //DEBUGln(colonIndex);
      if (radio.sendWithRetry(targetId, buff, inputstr.length()))
      {
        DEBUGln("ACK:OK");
      }
      else
        DEBUGln("ACK:NOK");
    }
  }

  if (radio.receiveDone())
  {
    int rssi = radio.RSSI;
    int senderId = radio.SENDERID;
    int dataLen = radio.DATALEN;
    strncpy((char *)buff, (const char *)radio.DATA, dataLen);
    buff[dataLen] = '\0';
    bool ackSent = false;

    CheckForWirelessHEX(radio, flash, false); //non verbose DEBUG

    if (radio.ACKRequested())
    {
      byte theNodeID = radio.SENDERID;
      radio.sendACK();
      ackSent = true;
    }

    if (dataLen > 0)
    {
      DEBUG('[');DEBUG(senderId);DEBUG("] ");
      DEBUG((char *)buff);
      DEBUG("   [RSSI:");DEBUG(rssi);DEBUG("]");
    }
    if (ackSent)
      DEBUG("[ACK-sent]");

    DEBUGln();
    Blink(LED,3);
    SERIALFLUSH();
  }
}

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

The results are a bit better, but still inconsistent:

Code: [Select]
18:39:43.995 -> EEPROM flash chip found, and is OK ...
18:39:43.995 -> Moteino Example : 915 Mhz...
18:39:44.312 -> Init: ACK Fail!
18:39:44.641 -> Startup: ACK Fail!
18:39:49.638 -> Msg received from sender ID [1]
18:39:49.638 ->    [RX_RSSI:-30]
18:39:49.685 ->    Payload length = 0
18:39:49.954 -> XMit ACK - Success!
18:39:49.954 -> Transmitted payload: 9905:757
18:39:54.924 -> XMit ACK - Success!
18:39:54.924 -> Transmitted payload: 9905:747
18:39:59.935 -> XMit ACK - Success!
18:39:59.935 -> Transmitted payload: 9905:746
18:40:04.916 -> XMit ACK - Success!
18:40:04.916 -> Transmitted payload: 9905:752
18:40:09.933 -> XMit ACK - Success!
18:40:09.933 -> Transmitted payload: 9905:757
18:40:14.912 -> XMit ACK - Fail!
18:40:14.912 -> Transmitted payload: 9905:756
18:40:14.946 -> Msg received from sender ID [1]
18:40:14.946 ->    [RX_RSSI:-30]
18:40:14.946 ->    Payload length = 0
18:40:19.907 -> XMit ACK - Fail!
18:40:19.907 -> Transmitted payload: 9905:746
18:40:19.942 -> Msg received from sender ID [1]
18:40:19.942 ->    [RX_RSSI:-31]
18:40:19.942 ->    Payload length = 0
18:40:24.897 -> XMit ACK - Fail!
18:40:24.897 -> Transmitted payload: 9905:746
18:40:24.932 -> Msg received from sender ID [1]
18:40:24.932 ->    [RX_RSSI:-30]
18:40:24.932 ->    Payload length = 0
18:40:29.881 -> XMit ACK - Fail!
18:40:29.881 -> Transmitted payload: 9905:750
18:40:29.916 -> Msg received from sender ID [1]
18:40:29.916 ->    [RX_RSSI:-31]
18:40:29.916 ->    Payload length = 0
18:40:34.887 -> XMit ACK - Fail!
18:40:34.887 -> Transmitted payload: 9905:757
18:40:34.887 -> Msg received from sender ID [1]
18:40:34.887 ->    [RX_RSSI:-29]
18:40:34.887 ->    Payload length = 0

So, clearly there is a problem somewhere with sendWithRetry() and/or the gateway code. Either (1) there is a bug in the code (possible), or (2) I'm doing something wrong (highly likely).

To anticipate questions you may have:
  • Node and Gateway are aproximately 6 ft. (~2 meters) apart
  • Pure gateway out-of-the-box demo "blinky" code seems to work fine. LEDs blink, light sensor levels get passed, etc. But the stock example code does not check the result of sendWithRetry(), so it's hard to tell if the problem is on the gateway side or the node side.
  • I also have another program (the actual project I am working on) that sends packets back & forth between 2 Motes (using sendWithRetry()) and they seem to work just fine. I've also swapped out different moteinos during my tests, so all that indicates it's probably not a bad radio
  • OTA programming of the gateway Mote also works flawlessly, giving more indication that the radios are OK.
  • Yes, I scoured the forum for an answer to this. Found a lot of really useful info and tried some of the suggestions I found, but nothing that pointed to solving this problem. If it's there, it was too far over my head to understand.
So I'm totally at a loss (and a standstill) here. The actual utility code for what I am trying to do (not shown here so as to not confuse things) works well, even the sendWithRetry() parts. It's just when I try to communicate with the gateway that things go off the deep end.

I'm open to any suggestions anyone may have. Desperate, really. :-[

I've been working on this for days. I'm going off to have a drink and relax for a while. Hopefully someone can point me in the right direction, even if the solution makes me look a bit dense.

Thanks in advance.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Getting Random Results from sendWithRetry()
« Reply #2 on: January 12, 2019, 10:38:47 AM »
Lots of code to go through. It's a dauting task to figure out what you changed in the stock sketches by looking at 300 lines of code in a single sketch.
Can you please edit your posts and only include the differences, not the entire sketches? (ie help us help you).

The stock sketches are verified to work, used by many. Before we start digging there, I would recommend starting from stock sketch (just change your radio settings, ***correctly***), once you get that working, build upon it and see where it stops working, thats a good learning path too.

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #3 on: January 12, 2019, 12:36:05 PM »
Hi Felix, thanks for the quick response.

I tried doing as you suggested. I guess my long-winded post obscured my methodology.

I started with the unmodified gateway code and node sketch ("John's DIY Example") straight from the web site/GitHub. All of that worked just fine. The node registered itself the gateway, the light sensor sent readings to the gateway, clicking the "Turn LED On/Off" button had the appropriate effect, etc. From that standpoint, everything is working according to design.

The problem stems from the fact that John's example code does not check the result from the sendWithRetry() call:

Lines 123-129:
Code: [Select]
  sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
  DEBUGln(payload);  // check what we are transmitting to the gateway receiver
  byte buffLen=strlen(payload);
  radio.sendWithRetry(GATEWAYID, payload, buffLen);
  // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
  radio.sendWithRetry(GATEWAYID, "9900:0", 6);
  delay(5000);
and lines 193-200:
Code: [Select]
void transmitStatus(int item, int status){  
    sprintf(payload, "%d:%d", item, status);
    byte buffLen=strlen(payload);
    radio.sendWithRetry(GATEWAYID, payload, buffLen);
    DEBUG("Transmitted payload: ");
    DEBUGln(payload);
    delay(10);
}
So, all I did was add some additional code to capture the result of sendWithRetry():
Code: [Select]
  sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
  DEBUGln(payload);  // check what we are transmitting to the gateway receiver
  byte buffLen=strlen(payload);
  if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
  {
    DEBUGln("Init: ACK Success!");
  }
  else
  {
    DEBUGln("Init: ACK Fail!");
  }
 
  // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
  if (radio.sendWithRetry(GATEWAYID, "9900:0", 6))
  {
    DEBUGln("Startup: ACK Success!");
  }
  else
  {
    DEBUGln("Startup: ACK Fail!");
  }
  delay(5000);
and
Code: [Select]
void transmitStatus(int item, int status){  
    sprintf(payload, "%d:%d", item, status);
    byte buffLen=strlen(payload);
    if (radio.sendWithRetry(GATEWAYID, payload, buffLen, MAXRETRIES, MAXTIMEOUT))
    {
      DEBUGln("XMit ACK - Success!");
    }
    else
    {
      DEBUGln("XMit ACK - Fail!");
    }

    DEBUG("Transmitted payload: ");
    DEBUGln(payload);
    delay(10);
}

That's when I saw that sendWithRetry() was returning inconsistent results. According to the gateway logs, some (but not all) messages would be received by the gateway yet the the node would receive a "false" result. In other cases the gateway never receives the messages.

The rest of my message/examples are just variations on a theme trying to see if I could find root cause. Not only did they not work, but they seemed to just confuse the issue.  :(

I've been a software developer for a long time, have a couple of years experience with Arduino, but brand new to Moteino, so I'm willing to admit I'm missing something basic, I just can't seem to find what that is. I'm also very familiar with the "start from known good and work backward" debugging method, but that didn't seem to work here. Apologies again for obscuring the basic methodology I used.

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Getting Random Results from sendWithRetry()
« Reply #4 on: January 15, 2019, 02:52:34 PM »
Looks like there was a problem with the pin defines for MoteinoM0.
I updated these examples (Gateway, Node, Struct examples). These may be problems in your sketch as well.

And I tried latest library release (v1.2).
I tried the Gateway with Node then RandomNumbers examples, everything works perfectly, no ACKs lost or anything.

The rest is a matter of your specific code changes not behaving the way you expect.

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #5 on: January 15, 2019, 02:55:12 PM »
Got it, thanks! I'll give them a try tonight.

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #6 on: January 16, 2019, 09:15:01 PM »
Ran some more tests tonight and still no luck.  :(

To be sure I wasn't using any bit of old code, I wiped out everything related to this code from my computer. Then, I reinstalled fresh gateway code (from https://github.com/LowPowerLab/RFM69/tree/master/Examples/PiGateway) and fresh node code (from https://github.com/johnsdiyplayground/moteino-3-part-series-sample-code).

Test 1: Stock code for gateway & node (No changes, except for radio node and encryption key)

Code: [Select]
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
//   1. It will flash the onboard LED located at pin D9
//   2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
//   3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
//     Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
//      NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h>         //get it here: http://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: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //Replaced by rfm69_ota.h
#include <SPI.h>           //comes with Arduino IDE (www.arduino.cc)

#define SERIAL_EN          //comment out if you don't want any serial output

//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID   1    // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID      44   // must be unique to each sensor node
#define NETWORKID   200  // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY       RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY      "XXXXXXXXXXXXXXXX" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW      //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************

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

// Define our pins
#define onboardLED     9   // Moteino onboard LED is on digital pin 9
#define photoResistor   A5
#define photoResistorPower  A2   // The photoresistor will be hooked to pins A2 and A5
#define externalLED   3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
              // For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!

// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000;  // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;

// The next variable defines how often to check the photoresistor's light level
const long photoResistorCheckTime = 30000;  // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;

// We don't need to define how often to check commands to turn on/off the external LED.  That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus; 

char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";   //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)

void setup() {
  #ifdef SERIAL_EN
    Serial.begin(SERIAL_BAUD);
  #endif

  // Tell Moteino if our pins are inputs or outputs
  pinMode(onboardLED, OUTPUT);
  pinMode(photoResistor, INPUT);
  pinMode(photoResistorPower, OUTPUT);
  pinMode(externalLED, OUTPUT);

  // Initialize our onboard and external LEDs to start up turned off (set to low)
  digitalWrite(onboardLED, LOW);
  digitalWrite(externalLED, LOW);
 
  // Turn on power to the photoresistor
  digitalWrite(photoResistorPower, HIGH);
 
  // Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
  lastBlinkTime = millis();
  lastPhotoResistorReport = millis();
 
  char buff[20];  // create a variable called buff (short for "buffer") that can hold up to 20 characters
 
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
     radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);
 
  if (flash.initialize()){
    DEBUGln("EEPROM flash chip found, and is OK ...");
  }
  else
    DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");

  sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
  DEBUGln(payload);  // check what we are transmitting to the gateway receiver
  byte buffLen=strlen(payload);
  radio.sendWithRetry(GATEWAYID, payload, buffLen);
  // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
  radio.sendWithRetry(GATEWAYID, "9900:0", 6);
  delay(5000);
}

void loop() {
   // wireless programming token check
   // DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
   CheckForWirelessHEX(radio, flash, true);

  // check for messages from the home automation gateway or other Moteino nodes 
    if (radio.receiveDone()){
      DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
      for (byte i = 0; i < radio.DATALEN; i++)
          DEBUG((char)radio.DATA[i]);
      DEBUGln();
      //first send any ACK to request
      DEBUG("   [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
      DEBUG("   Payload length = ");
      DEBUGln(radio.DATALEN); 
   
      if (radio.DATALEN==3){
          //check for a web page request from Pi Gateway to turn on or off the external LED
          //we will receive from the Pi Gateway either a message of "LOF" or LON"
          if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){    // "LOF" is short for "LED off", keep radio messages short for best results
            digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
            ledStatus = 0;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
                              // We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
                              // to a lot of sensor nodes in our house.  Each sensor node gets its own set of 4-digit codes.
                              // Any time we transmit an LED status, we will always identify it with sensor code "9900"
          }
          else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){  // "LON" is short for "LED on"
            digitalWrite(externalLED, HIGH);  // Tell our external LED to turn ON
            ledStatus = 1;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off
          }
      }
    }

    if (radio.ACKRequested())
    {
      radio.sendACK();
      DEBUGln("ACK sent.");
    }

  // check if the onboard LED should be turned on or off
  if ((millis() - lastBlinkTime) >= blinkLEDtime) {
      lastBlinkTime = millis();  // update current time for the next time through the loop
      digitalWrite(onboardLED, !digitalRead(onboardLED));  // this says in one simple line to flip-flop the status of the pin
  }

  // check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
  if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
      lastPhotoResistorReport = millis();   // update current time for the next time through the loop
      int lightLevel = analogRead(photoResistor);  // we read in the photoResistor level here (value can be 0 to 4095)
     
      // publish the actual value of the light level.  We will call this sensor ID data code "9912"
      transmitStatus(9905, lightLevel);
  }
}  // this is the end of the loop


// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){ 
    sprintf(payload, "%d:%d", item, status);
    byte buffLen=strlen(payload);
    radio.sendWithRetry(GATEWAYID, payload, buffLen);
    DEBUG("Transmitted payload: ");
    DEBUGln(payload);
    delay(10);
}
Test 1 Node Serial Output:
Code: [Select]
19:45:04.993 -> EEPROM flash chip found, and is OK ...
19:45:04.993 -> Moteino Example : 915 Mhz...
19:45:35.049 -> Transmitted payload: 9905:752
19:45:35.177 -> Msg received from sender ID [1]
19:45:35.177 ->    [RX_RSSI:-29]
19:45:35.177 ->    Payload length = 0
19:45:56.174 -> Msg received from sender ID [1] LON
19:45:56.174 ->    [RX_RSSI:-32]
19:45:56.174 ->    Payload length = 3
19:45:56.382 -> Transmitted payload: 9900:1
19:45:57.324 -> Msg received from sender ID [1]
19:45:57.324 ->    [RX_RSSI:-32]
19:45:57.324 ->    Payload length = 0
19:46:03.679 -> Msg received from sender ID [1] LOF
19:46:03.725 ->    [RX_RSSI:-31]
19:46:03.725 ->    Payload length = 3
19:46:03.889 -> Transmitted payload: 9900:0
19:46:04.805 -> Msg received from sender ID [1]
19:46:04.805 ->    [RX_RSSI:-31]
19:46:04.805 ->    Payload length = 0
19:46:05.007 -> Transmitted payload: 9905:753
19:46:12.271 -> Msg received from sender ID [1] LON
19:46:12.271 ->    [RX_RSSI:-32]
19:46:12.271 ->    Payload length = 3
19:46:12.458 -> Transmitted payload: 9900:1
19:46:13.413 -> Msg received from sender ID [1]
19:46:13.413 ->    [RX_RSSI:-32]
19:46:13.413 ->    Payload length = 0
19:46:18.040 -> Msg received from sender ID [1] LOF
19:46:18.040 ->    [RX_RSSI:-32]
19:46:18.040 ->    Payload length = 3
19:46:18.174 -> Transmitted payload: 9900:0
19:46:19.150 -> Msg received from sender ID [1]
19:46:19.150 ->    [RX_RSSI:-31]
19:46:19.150 ->    Payload length = 0
19:46:27.484 -> Msg received from sender ID [1] LON
19:46:27.484 ->    [RX_RSSI:-32]
19:46:27.484 ->    Payload length = 3
19:46:27.660 -> Transmitted payload: 9900:1
19:46:28.607 -> Msg received from sender ID [1]
19:46:28.641 ->    [RX_RSSI:-31]
19:46:28.641 ->    Payload length = 0
19:46:30.601 -> Msg received from sender ID [1] LOF
19:46:30.635 ->    [RX_RSSI:-32]
19:46:30.635 ->    Payload length = 3
19:46:30.822 -> Transmitted payload: 9900:0
19:46:31.729 -> Msg received from sender ID [1]
19:46:31.764 ->    [RX_RSSI:-32]
19:46:31.764 ->    Payload length = 0
19:46:34.912 -> Transmitted payload: 9905:763
19:46:35.775 -> Msg received from sender ID [1]
19:46:35.775 ->    [RX_RSSI:-30]
19:46:35.775 ->    Payload length = 0
19:47:04.856 -> Transmitted payload: 9905:761
19:47:05.702 -> Msg received from sender ID [1]
19:47:05.702 ->    [RX_RSSI:-31]
19:47:05.702 ->    Payload length = 0
19:47:34.803 -> Transmitted payload: 9905:756
19:47:35.650 -> Msg received from sender ID [1]
19:47:35.650 ->    [RX_RSSI:-31]
19:47:35.650 ->    Payload length = 0
19:48:04.735 -> Transmitted payload: 9905:759
19:48:05.588 -> Msg received from sender ID [1]
19:48:05.588 ->    [RX_RSSI:-32]
19:48:05.588 ->    Payload length = 0
Test 1 Gateway Log:
Code: [Select]
7:48:35 PM : {"_id":44,"updated":1547689715421,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":754,"unit":" level","updated":1547689715421},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:48:05 PM : {"_id":44,"updated":1547689685480,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":759,"unit":" level","updated":1547689685480},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:47:35 PM : {"_id":44,"updated":1547689655540,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547689655540},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:47:05 PM : {"_id":44,"updated":1547689625597,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689625597},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:35 PM : {"_id":44,"updated":1547689595656,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":763,"unit":" level","updated":1547689595656},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:31 PM : {"_id":44,"updated":1547689591639,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:46:28 PM : {"_id":44,"updated":1547689588519,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689588519}}}
7:46:25 PM : {"_id":44,"updated":1547689579028,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689579028}}}
7:46:19 PM : {"_id":44,"updated":1547689579028,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689579028}}}
7:46:13 PM : {"_id":44,"updated":1547689573299,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689573299}}}
7:46:04 PM : {"_id":44,"updated":1547689564689,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689564689}}}
7:45:57 PM : {"_id":44,"updated":1547689557216,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"ON","updated":1547689557216}}}
7:45:35 PM : {"_id":44,"updated":1547689535066,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":752,"unit":" level","updated":1547689535066},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:45:04 PM : {"_id":44,"updated":1547689504116,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689486129},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:44:46 PM : {"_id":44,"updated":1547689486129,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689486129},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:44:16 PM : {"_id":44,"updated":1547689456187,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689456187},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:46 PM : {"_id":44,"updated":1547689426245,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":761,"unit":" level","updated":1547689426245},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:33 PM : {"_id":44,"updated":1547689413234,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689413234}}}
7:43:26 PM : {"_id":44,"updated":1547689406769,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663},"LED Status":{"label":"LED Status","value":"ON","updated":1547689406769}}}
7:43:15 PM : {"_id":44,"updated":1547689395663,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":751,"unit":" level","updated":1547689395663}}}
7:43:06 PM : {"_id":44,"updated":1547689365722,"label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547689365722}}}
7:42:45 PM : {"_id":44,"updated":1547689365722,"metrics":{"Light Level":{"label":"Light Level","value":753,"unit":" level","updated":1547689365722}}}
7:41:39 PM : SERVERTIME OFFSET: 195ms
7:41:39 PM : Connected!
7:41:34 PM : Disconnected!
7:35:12 PM : SERVERTIME OFFSET: 172ms
7:35:12 PM : Connected!
7:35:06 PM : Disconnected!
7:29:50 PM : SERVERTIME OFFSET: 230ms
7:29:50 PM : Connected!
7:29:47 PM : Disconnected!

[Continued in next post]

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #7 on: January 16, 2019, 09:24:26 PM »
Test 2: Change node code only to capture sendWithRetry() result:
Code: [Select]
/* ***************************************************************************************************
// Example sketch from John's DIY Playground
// to demonstrate the Moteino IoT device using an RFM69 transceiver attached to it.
// Visit http://www.lowpowerlab.com/ to purchase a Moteino of your own
//
// This sketch will demonstrate a few basic features of the Moteino:
//   1. It will flash the onboard LED located at pin D9
//   2. It will report sensor light levels from a photoresistor on pin A5 to the Home Automation gateway
//   3. It will allow us to control an LED connected to pin D3 remotely
//
// Demonstration of this code can be found on my YouTube channel, called John's DIY Playground
// The channel's URL is http://www.youtube.com/c/johnsdiyplayground
// Software code examples can be found on my GitHub page at
// https://github.com/johnsdiyplayground
//
// Hardware Required:
// 1. Moteino or Moteino USB with RFM69 transceiver (http://www.lowpowerlab.com/)
// 2. LED
// 3. 2 quantity of 220 ohm resistor for the external LED and photoresistor circuits
//     Put the resistors in series; the LED to ground and the other from photoresistor A5 to ground
// 4. Photoresistor
// 5. USB to micro USB cable for powering the Moteino
// 6. Another USB Moteino with the Pi Gateway code loaded on it and connected to a Raspberry Pi
//      NOTE: this second Moteino must have the same frequency RFM69 transceiver attached to it
// 7. FTDI USB to Moteino programming interface (Not needed if you are using Moteino USB devices)
******************************************************************************************************
*/
#include <RFM69.h>         //get it here: http://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: http://github.com/lowpowerlab/spiflash
//#include <WirelessHEX69.h> //Replaced by rfm69_ota.h
#include <SPI.h>           //comes with Arduino IDE (www.arduino.cc)

#define SERIAL_EN          //comment out if you don't want any serial output

//*****************************************************************************************************************************
// ADJUST THE SETTINGS BELOW DEPENDING ON YOUR HARDWARE/TRANSCEIVER SETTINGS/REQUIREMENTS
//*****************************************************************************************************************************
#define GATEWAYID   1    // this is the node ID of your gateway (which is probably tied to a Raspberry Pi)
#define NODEID      44   // must be unique to each sensor node
#define NETWORKID   200  // every node must match the same network ID to hear messages from each other and take actions directly
//#define FREQUENCY     RF69_433MHZ
//#define FREQUENCY     RF69_868MHZ
#define FREQUENCY       RF69_915MHZ //Match this with the version of your Moteino's transceiver! (others: RF69_433MHZ, RF69_868MHZ)
#define ENCRYPTKEY      "$d4N1BO99l2G.()[" //has to be same 16 characters/bytes on all nodes, not more not less!
#define IS_RFM69HW      //uncomment only for RFM69HW! Leave out if you have RFM69W!
//*****************************************************************************************************************************

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

// Define our pins
#define onboardLED     9   // Moteino onboard LED is on digital pin 9
#define photoResistor   A5
#define photoResistorPower  A2   // The photoresistor will be hooked to pins A2 and A5
#define externalLED   3 // careful about which pins are already in use by Moteino's RFM69 transceiver!
              // For example, on Moteino you CANNOT use D2, D8, D10, D11, D12, D13!!

// Now we will define how often to flash our onboard LED
const long blinkLEDtime = 1000;  // 1000 is milliseconds so this means blink on/off in 1 second intervals
// and we need a way to record the last time we turned the LED on or off
unsigned long lastBlinkTime;

// The next variable defines how often to check the photoresistor's light level
const long photoResistorCheckTime = 30000;  // 10000 milliseconds is 10 seconds
// and we also record the time we report the photoresistor status with this
unsigned long lastPhotoResistorReport;

// We don't need to define how often to check commands to turn on/off the external LED.  That's because
// our Moteino will respond to commands to request it come on or off from the Raspberry Pi / Moteino gateway device.
// The only thing we do track is the external LED's current status as on (1) or off (0)
int ledStatus; 

char payload[] = "123 ABCDEFGHIJKLMNOPQRSTUVWXYZ";   //this is for transmitting to the Pi Gateway
byte STATUS;
RFM69 radio;
SPIFlash flash(8, 0xEF30); //WINDBOND 4MBIT flash chip on CS pin D8 (default for Moteino)

void setup() {
  #ifdef SERIAL_EN
    Serial.begin(SERIAL_BAUD);
  #endif

  // Tell Moteino if our pins are inputs or outputs
  pinMode(onboardLED, OUTPUT);
  pinMode(photoResistor, INPUT);
  pinMode(photoResistorPower, OUTPUT);
  pinMode(externalLED, OUTPUT);

  // Initialize our onboard and external LEDs to start up turned off (set to low)
  digitalWrite(onboardLED, LOW);
  digitalWrite(externalLED, LOW);
 
  // Turn on power to the photoresistor
  digitalWrite(photoResistorPower, HIGH);
 
  // Initialize our timers for the onboard LED and photoresistor using millis which is the Photon's internal clock
  lastBlinkTime = millis();
  lastPhotoResistorReport = millis();
 
  char buff[20];  // create a variable called buff (short for "buffer") that can hold up to 20 characters
 
  radio.initialize(FREQUENCY,NODEID,NETWORKID);
  #ifdef IS_RFM69HW
     radio.setHighPower(); //uncomment only for RFM69HW!
  #endif
  radio.encrypt(ENCRYPTKEY);
 
  if (flash.initialize()){
    DEBUGln("EEPROM flash chip found, and is OK ...");
  }
  else
    DEBUGln("EEPROM flash chip failed to initialize! (is chip present on the Moteino?)");

  sprintf(payload, "Moteino Example : %d Mhz...", FREQUENCY==RF69_433MHZ ? 433 : FREQUENCY==RF69_868MHZ ? 868 : 915);  // sprintf command creates a string to put in the buff variable
  DEBUGln(payload);  // check what we are transmitting to the gateway receiver
  byte buffLen=strlen(payload);
  if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
  {
    DEBUGln("Init: ACK Success!");
  }
  else
  {
    DEBUGln("Init: ACK Fail!");
  }

 // We need to send the next line to the gateway to let it know we have an external LED with condition "off" to start with
  if (radio.sendWithRetry(GATEWAYID, "9900:0", 6))
  {
    DEBUGln("Startup: ACK Success!");
  }
  else
  {
    DEBUGln("Startup: ACK Fail!");
  }

 
  delay(5000);
}

void loop() {
   // wireless programming token check
   // DO NOT REMOVE, or this sensor node will not be wirelessly programmable any more!
   CheckForWirelessHEX(radio, flash, true);

  // check for messages from the home automation gateway or other Moteino nodes 
    if (radio.receiveDone()){
      DEBUG("Msg received from sender ID ");DEBUG('[');DEBUG(radio.SENDERID);DEBUG("] ");
      for (byte i = 0; i < radio.DATALEN; i++)
          DEBUG((char)radio.DATA[i]);
      DEBUGln();
      //first send any ACK to request
      DEBUG("   [RX_RSSI:");DEBUG(radio.RSSI);DEBUGln("]");
      DEBUG("   Payload length = ");
      DEBUGln(radio.DATALEN); 
   
      if (radio.DATALEN==3){
          //check for a web page request from Pi Gateway to turn on or off the external LED
          //we will receive from the Pi Gateway either a message of "LOF" or LON"
          if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='F'){    // "LOF" is short for "LED off", keep radio messages short for best results
            digitalWrite(externalLED, LOW); // Tell our external LED to turn OFF
            ledStatus = 0;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off using transmitStatus subroutine
                              // We are passing a unique 4-digit number to identify a unique data type for our Pi Gateway, since it listens
                              // to a lot of sensor nodes in our house.  Each sensor node gets its own set of 4-digit codes.
                              // Any time we transmit an LED status, we will always identify it with sensor code "9900"
          }
          else if (radio.DATA[0]=='L' && radio.DATA[1]=='O' && radio.DATA[2]=='N'){  // "LON" is short for "LED on"
            digitalWrite(externalLED, HIGH);  // Tell our external LED to turn ON
            ledStatus = 1;          // this sets our LED status variable
            delay(50);
            transmitStatus(9900, ledStatus);   // now we transmit LED status back to the Pi Gateway that we turned the LED off
          }
      }
    }

    if (radio.ACKRequested())
    {
      radio.sendACK();
      DEBUGln("ACK sent.");
    }

  // check if the onboard LED should be turned on or off
  if ((millis() - lastBlinkTime) >= blinkLEDtime) {
      lastBlinkTime = millis();  // update current time for the next time through the loop
      digitalWrite(onboardLED, !digitalRead(onboardLED));  // this says in one simple line to flip-flop the status of the pin
  }

  // check if it is time to report the photoresistor's value to the Moteino USB gateway (receives data for the Raspberry Pi)
  if ((millis() - lastPhotoResistorReport) >= photoResistorCheckTime) {
      lastPhotoResistorReport = millis();   // update current time for the next time through the loop
      int lightLevel = analogRead(photoResistor);  // we read in the photoResistor level here (value can be 0 to 4095)
     
      // publish the actual value of the light level.  We will call this sensor ID data code "9912"
      transmitStatus(9905, lightLevel);
  }
}  // this is the end of the loop


// The function below will transmit the LED status to our Moteino USB / Pi Gateway
void transmitStatus(int item, int status){ 
    sprintf(payload, "%d:%d", item, status);
    byte buffLen=strlen(payload);
    if (radio.sendWithRetry(GATEWAYID, payload, buffLen))
    {
      DEBUGln("XMit ACK - Success!");
    }
    else
    {
      DEBUGln("XMit ACK - Fail!");
    }

    DEBUG("Transmitted payload: ");
    DEBUGln(payload);
    delay(10);
}
Test 2 node serial output:
Code: [Select]
19:55:15.024 -> EEPROM flash chip found, and is OK ...
19:55:15.024 -> Moteino Example : 915 Mhz...
19:55:15.159 -> Init: ACK Fail!
19:55:15.289 -> Startup: ACK Fail!
19:55:20.266 -> Msg received from sender ID [1]
19:55:20.266 ->    [RX_RSSI:-31]
19:55:20.266 ->    Payload length = 0
19:55:40.838 -> Msg received from sender ID [1] LON
19:55:40.838 ->    [RX_RSSI:-29]
19:55:40.838 ->    Payload length = 3
19:55:41.025 -> XMit ACK - Fail!
19:55:41.025 -> Transmitted payload: 9900:1
19:55:41.948 -> Msg received from sender ID [1]
19:55:41.948 ->    [RX_RSSI:-29]
19:55:41.981 ->    Payload length = 0
19:55:44.394 -> Msg received from sender ID [1] LOF
19:55:44.394 ->    [RX_RSSI:-29]
19:55:44.394 ->    Payload length = 3
19:55:44.580 -> XMit ACK - Fail!
19:55:44.580 -> Transmitted payload: 9900:0
19:55:45.055 -> XMit ACK - Fail!
19:55:45.055 -> Transmitted payload: 9905:761
19:55:45.548 -> Msg received from sender ID [1]
19:55:45.548 ->    [RX_RSSI:-29]
19:55:45.548 ->    Payload length = 0
19:56:14.994 -> XMit ACK - Fail!
19:56:14.994 -> Transmitted payload: 9905:756
19:56:15.468 -> Msg received from sender ID [1]
19:56:15.503 ->    [RX_RSSI:-29]
19:56:15.503 ->    Payload length = 0
19:56:35.161 -> Msg received from sender ID [1] LON
19:56:35.161 ->    [RX_RSSI:-30]
19:56:35.161 ->    Payload length = 3
19:56:35.335 -> XMit ACK - Fail!
19:56:35.335 -> Transmitted payload: 9900:1
19:56:36.282 -> Msg received from sender ID [1]
19:56:36.282 ->    [RX_RSSI:-31]
19:56:36.282 ->    Payload length = 0
19:56:39.950 -> Msg received from sender ID [1] LOF
19:56:39.987 ->    [RX_RSSI:-31]
19:56:39.987 ->    Payload length = 3
19:56:40.148 -> XMit ACK - Fail!
19:56:40.148 -> Transmitted payload: 9900:0
19:56:41.085 -> Msg received from sender ID [1]
19:56:41.085 ->    [RX_RSSI:-30]
19:56:41.120 ->    Payload length = 0
19:56:44.953 -> XMit ACK - Fail!
19:56:44.953 -> Transmitted payload: 9905:763
19:56:45.117 -> Msg received from sender ID [1]
19:56:45.117 ->    [RX_RSSI:-31]
19:56:45.117 ->    Payload length = 0
19:57:14.863 -> XMit ACK - Fail!
19:57:14.863 -> Transmitted payload: 9905:762
19:57:15.039 -> Msg received from sender ID [1]
19:57:15.039 ->    [RX_RSSI:-29]
19:57:15.039 ->    Payload length = 0
Test 2 gateway Log:
Code: [Select]
7:57:15 PM : {"_id":44,"updated":1547690234950,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690234950},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:45 PM : {"_id":44,"updated":1547690205004,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":763,"unit":" level","updated":1547690205004},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:41 PM : {"_id":44,"updated":1547690200986,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690200986}}}
7:56:36 PM : {"_id":44,"updated":1547690196170,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"ON","updated":1547690196170}}}
7:56:15 PM : {"_id":44,"updated":1547690175366,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":756,"unit":" level","updated":1547690175366},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690145425}}}
7:55:45 PM : {"_id":44,"updated":1547690145425,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547690145425}}}
7:55:41 PM : {"_id":44,"updated":1547690141857,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"ON","updated":1547690141857}}}
7:55:15 PM : {"_id":44,"updated":1547690115739,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}
7:55:13 PM : {"_id":44,"updated":1547690113691,"type":"JohnsDIYexample","label":"John's DIY Example","descr":"John's DIY Example","metrics":{"Light Level":{"label":"Light Level","value":762,"unit":" level","updated":1547690073763},"LED Status":{"label":"LED Status","value":"OFF","updated":1547689591639}}}

Messages are clearly getting sent to/from the gateway, but sendWithRetry() is consistently failing on the return code. So, I'm a loss at this point. I can't say where the issue is, but I'm using only the example code (except for a couple of extra Serial.print() lines) so it doesn't appear that I'm introducing the problem with custom code. I'm using the latest Arduino IDE (on Windows 10), could it be a problem with one of their libraries or the IDE compiler? Grasping at straws at this point.  ;)

If I get a chance this weekend I'll try to trace through the library code to see if I can determine exactly why I keep getting fails on sendWithRetry(), but quite frankly I'm really new to Moteino so I'm kind of feeling my way around in the dark. I'll let you know if I find anything.

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry() [SOLVED]
« Reply #8 on: January 20, 2019, 09:23:03 PM »
Felix,

After testing most of the day today, I have finally figured out the "problem" with the example sketches. The original sketches had the gateway's serial baud rate set at 19200. At the very beginning of my process I set the gateway to 115200, thinking that faster would be better. After setting the baud rate back to 19200 on the gateway, the packets started flowing back & forth and sendWithRetry() was returning the proper results. I'm not sure why a faster baud rate would interfere with packet timing, but's working now so I'm not going to ask a lot of questions~  ;)

I have also traced the original sendWithRetry() fail problem in my sketches to a bad interaction with listen mode (listenModeStart() and listenModeEnd()). With the listen mode calls in the code, sendWithRetry() always fails. Take those calls out and it works just fine. I'll keep researching that issue and post separately if I can't figure it out (unless you know what the issue may be).

I've marked this thread as "[SOLVED]". Thanks for all your help with this.

HG

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #9 on: January 23, 2019, 12:02:46 AM »
....and we're back.  :-[

Fired up the node code again to do some more work and we're back to getting fail responses from sendWithRetry(). Exact same gateway & node code that worked perfectly yesterday. So I'm back to square one, and not sure where to go from here. *But*, since I got a good run yesterday there's hope that there is a solution, I just haven't found it yet. More to come as this develops....

Felix

  • Administrator
  • Hero Member
  • *****
  • Posts: 6866
  • Country: us
    • LowPowerLab
Re: Getting Random Results from sendWithRetry()
« Reply #10 on: January 23, 2019, 11:24:10 AM »
Weird, thanks for the updates though, not sure what to say  :-\
The examples should run serial at 115200. That's for debugging, etc. There's no point to run serial if nothing is attached and nothing is monitoring that serial port. On the gateway it's different, assuming the serial is the path between the wireless gateway/network and host+internet.

leo

  • NewMember
  • *
  • Posts: 1
Re: Getting Random Results from sendWithRetry()
« Reply #11 on: August 19, 2019, 03:41:49 AM »
Hi, I got the same issues where the returned value is false even though I can see the messages arriving just once as expected.

did you find out what's wrong yet?

I can post my snippets but not sure it would help

edit, I think it's this issue https://lowpowerlab.com/forum/coding-questions/no-ack-received-by-sender-with-esp8266/

edit2: actually it still doesn't work
« Last Edit: August 19, 2019, 07:57:00 AM by leo »

handyguy

  • NewMember
  • *
  • Posts: 27
Re: Getting Random Results from sendWithRetry()
« Reply #12 on: August 19, 2019, 09:30:15 PM »
Hi leo,

I never got it to work completely. I was able to route around the problem by reconfiguring the message flow in my code and moved on to other problems. I hope someone will eventually figure out what the true cause of the problem is.

HG

jimmys01

  • NewMember
  • *
  • Posts: 1
Re: Getting Random Results from sendWithRetry()
« Reply #13 on: October 09, 2019, 05:35:26 AM »
When I send with sendwithretry() I get the message in the other end but with DATALEN=0
When I send with send() and request ACK the same thing.
When I send with send() and do not request ACK all is OK and the DATALEN is correct.

Hope this narrows it down, I have spent literaly 20 hours on this..