I can't wirelessly program my Moteinos via OTA anymore [SOLVED]

Started by luisr320, October 19, 2020, 11:23:42 AM

luisr320

Hi!
I have 3 embedded Moteinos that are very difficult to access and OTA is the only practical way to update their firmware.
I have been using the OTA program for Windows successfully for the last years and all was well.
But after updating my LowpowerLab RFM69 library and moteino boards on Arduino IDE I stumbled in a problem and after spending a whole day trying to figure out what's going on I finally gave up.

This is what happens: I mange to successfully upload the new firmware via OTA if the end receiver is connected to a computer (any computer) trough a USB FTDI. When I disconnect the end receiver from that USB FTDI and connect it directly to it's own power supply, the same that used to work well on previous OTA programming, I get this message on the programmer:
Opening COM8 @115200baud...
SET TARGET: TO:4
Moteino: [TO:4:OK]
TARGET SET OK
FLX?
Moteino: [FLX?NOK:NOFLASH]
HANDSHAKE FAIL [HEX IMG refused by target node], reason: FLX?NOK:NOFLASH
HANDSHAKE FAIL [HEX IMG refused by target node], reason: FLX?NOK:NOFLASH
FAIL: Target node refused OTA request


And this happens to every single Moteino that I have around, EXCEPT the one in my car, connected trough a linear power regulator (L7805) to the car battery.
All the other Moteinos will only OTA if they are connected trough the FTDI USB to a computer.

I have already:
- reinstalled the Arduino IDE ver. 1.8.13
- removed Moteino boards 1.6.1 and reinstalled 1.6.0 and back to 1.6.1 now
- removed RFM69 library and reinstalled version 1.4.0 and back to 1.4.1 now
- reinstalled Moteino OTA Programmer ver. 2.0.7461
- reinstalled the FTDI drivers

Any ideas, please?

Felix

I'm afraid this could be a semi bug. If you call flash.sleep() in your sketch, or anywhere before the OTA flash check is made, then the flash is non-responsive unless flash.wakeup() is called before the OTA check.
So I submitted a patch to RFM69_OTA.cpp for this just now. No release made yet, but you can see the changed line, add that to your local file and let me know if this fixes your problem.

luisr320

Hello Felix, and thank you for the prompt response.

The car Moteino also has the same problem. It was appearing to be receiving updates but even reporting all data sent OK, the firmare wans't changing. So I removed the node frome the car and updated the firmware and now it also report a refusal to do the OTA.

Regarding your suggestion, that didn't work. I made the proposed change on the RFM69_OTA.cpp file, compiled and uploaded a new Programmer.ino and a new remote Moteino ino and the same still happens.

The OTA programmer can send all the packets successfully if the remote Moteino is connected to the PC with the USB FTDI. As soon as I remove it and connect it to a power supply, the remote Moteino keep refusing the OTA connection.

After the compilation on the Arduino IDE, the following error messages appeared:
Compiling libraries...
Compiling library "RFM69_LowPowerLab"
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Users\\Luis\\AppData\\Local\\Arduino15\\packages\\Moteino\\hardware\\avr\\1.6.1\\variants\\Moteino" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\libraries\\SPI\\src" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\SPIFlash" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\ClickButton" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\LowPower" "C:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab\\RFM69.cpp" -o "C:\\Users\\Luis\\AppData\\Local\\Temp\\arduino_build_692172\\libraries\\RFM69_LowPowerLab\\RFM69.cpp.o"
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Users\\Luis\\AppData\\Local\\Arduino15\\packages\\Moteino\\hardware\\avr\\1.6.1\\variants\\Moteino" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\libraries\\SPI\\src" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\SPIFlash" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\ClickButton" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\LowPower" "C:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab\\RFM69_ATC.cpp" -o "C:\\Users\\Luis\\AppData\\Local\\Temp\\arduino_build_692172\\libraries\\RFM69_LowPowerLab\\RFM69_ATC.cpp.o"
"C:\\Program Files (x86)\\Arduino\\hardware\\tools\\avr/bin/avr-g++" -c -g -Os -Wall -Wextra -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -Wno-error=narrowing -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10813 -DARDUINO_AVR_ATmega328 -DARDUINO_ARCH_AVR "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\cores\\arduino" "-IC:\\Users\\Luis\\AppData\\Local\\Arduino15\\packages\\Moteino\\hardware\\avr\\1.6.1\\variants\\Moteino" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab" "-IC:\\Program Files (x86)\\Arduino\\hardware\\arduino\\avr\\libraries\\SPI\\src" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\SPIFlash" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\ClickButton" "-IC:\\Users\\Luis\\Documents\\Arduino\\libraries\\LowPower" "C:\\Users\\Luis\\Documents\\Arduino\\libraries\\RFM69_LowPowerLab\\RFM69_OTA.cpp" -o "C:\\Users\\Luis\\AppData\\Local\\Temp\\arduino_build_692172\\libraries\\RFM69_LowPowerLab\\RFM69_OTA.cpp.o"
In file included from C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_ATC.h:31:0,
                 from C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_ATC.cpp:29:
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In constructor 'RFM69::RFM69(uint8_t, uint8_t, bool, uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:199:81: warning: unused parameter 'interruptNum' [-Wunused-parameter]
     RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum) //interruptNum is now deprecated
                                                                                 ^~~~~~~~~~~~
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In member function 'virtual void RFM69::interruptHook(uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:240:40: warning: unused parameter 'CTLbyte' [-Wunused-parameter]
     virtual void interruptHook(uint8_t CTLbyte) {};
                                        ^~~~~~~
In file included from C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.cpp:26:0:
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In constructor 'RFM69::RFM69(uint8_t, uint8_t, bool, uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:199:81: warning: unused parameter 'interruptNum' [-Wunused-parameter]
     RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum) //interruptNum is now deprecated
                                                                                 ^~~~~~~~~~~~
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In member function 'virtual void RFM69::interruptHook(uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:240:40: warning: unused parameter 'CTLbyte' [-Wunused-parameter]
     virtual void interruptHook(uint8_t CTLbyte) {};
                                        ^~~~~~~
In file included from C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_OTA.h:37:0,
                 from C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_OTA.cpp:33:
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In constructor 'RFM69::RFM69(uint8_t, uint8_t, bool, uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:199:81: warning: unused parameter 'interruptNum' [-Wunused-parameter]
     RFM69(uint8_t slaveSelectPin, uint8_t interruptPin, bool isRFM69HW, uint8_t interruptNum) //interruptNum is now deprecated
                                                                                 ^~~~~~~~~~~~
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h: In member function 'virtual void RFM69::interruptHook(uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.h:240:40: warning: unused parameter 'CTLbyte' [-Wunused-parameter]
     virtual void interruptHook(uint8_t CTLbyte) {};
                                        ^~~~~~~
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.cpp: In member function 'bool RFM69::initialize(uint8_t, uint16_t, uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69.cpp:65:21: warning: comparison is always false due to limited range of data type [-Wtype-limits]
   if (_interruptNum == NOT_AN_INTERRUPT) return false;
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_OTA.cpp: In function 'uint8_t sendHEXPacket(RFM69&, uint16_t, uint8_t*, uint8_t, uint16_t, uint16_t, uint16_t, uint8_t)':
C:\Users\Luis\Documents\Arduino\libraries\RFM69_LowPowerLab\RFM69_OTA.cpp:512:59: warning: format '%hu' expects argument of type 'short unsigned int*', but argument 3 has type 'uint16_t* {aka unsigned int*}' [-Wformat=]
         sscanf((const char*)radio.DATA, "FLX:%hu:OK", &tmp);
                                                       ~~~~^


Mot sure if they are related. Theu still appear even before the last proposed change

luisr320

HAHA! Some light!
I tried the Examples Programmer and Receiver and it works!

So, maybe I messed the upload procedures. Let me try again...

luisr320

Some more developments:

If I load the Examples\WirelessProgramming_OTA\Target\Target.ino, I recover the OTA capability.
I disconnect the Target and connect it to a power supply and it retains the OTA capability. Even if I disconnect it several times it still has the OTA available.

I then upload one of my simplest code by OTA and I can do it multiple times without a glitch.

BUT...

if I now disconnect the node and reconnect it, I can't use the OTA again and get the "FAIL: Target node refused OTA request" message.

The code I'm sending is this one:

//********************
// Humidity Sensor
// Ver 2G 1.0
// Node 12
//********************

#include <RFM69.h>
#include <RFM69_ATC.h>
#include <RFM69_OTA.h>
#include <SPIFlash.h>
#include <Adafruit_Sensor.h>
#include <DHT.h>



#define NODEID 12 //unique for each node on same network
#define GATEWAYID 1 //Gateway number on this network
#define NETWORKID 100 //the same on all nodes that talk to each other
#define BLYNKGATEWAY 10
#define FREQUENCY RF69_433MHZ
#define ENCRYPTKEY "XXXXXXXXXXXXXXXX" //exactly the same 16 characters/bytes on all nodes!
#define ATC_RSSI -80
#define ACK_TIME 3000 // max # of ms to wait for an ack
#define DHTPIN 7 //Humidity sensor data pin
#define DHTTYPE DHT11   // DHT 11 Humidity Sensor
#define SERIAL_BAUD 115200
#define SPY false

// Outbound Data Struct
typedef struct
{
  char outData_Type[6];
  uint32_t outData_1; //Output Sensor - 1 = Humidity; 2 = Temp
  uint32_t outData_2; //Humidity
  float outData_3; //Temperature

} Payload;
Payload outData;

//Initialize some variables
unsigned long timeNow = 0;
unsigned long dataTimeNow = 0;
byte newHumid = 0;
byte oldHumid = 0;
float newTemp = 0;
float oldTemp = 0;
word sendDataperiod = 5000;

// Hardware Init
SPIFlash flash(8, 0xEF30);
RFM69_ATC radio;
DHT dht(DHTPIN, DHTTYPE);

void setup()
{
  Serial.begin(SERIAL_BAUD); //Start the Serial port
  pinMode(LED, OUTPUT);

  //Initialize the radio
  radio.initialize(FREQUENCY, NODEID, NETWORKID);
  radio.setHighPower();
  radio.encrypt(ENCRYPTKEY); //Turn encryption ON
  radio.spyMode(SPY);
  radio.enableAutoPower(ATC_RSSI);
  
  dht.begin(); //Initialize the Humidity Sensor
}

void loop()
{
  if (radio.receiveDone())
  {
    CheckForWirelessHEX(radio, flash, true); //Check if data is wirelees programing
  }

  if (millis() - dataTimeNow > sendDataperiod)
  {
    dataTimeNow = millis();
    getHumid();
    getTemp();
  }
}

// Get Humidity and send to gateway
void getHumid()
{
  // Reading temperature or humidity takes about 250 milliseconds!
  // Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
  newHumid = dht.readHumidity();

  // Check if any reads failed and exit early (to try again).
  if (isnan(newHumid))
  {
    return;
  }

  if (newHumid != oldHumid)
  {
    oldHumid = newHumid; //Store the last good percentage
    //fill in the struct with new values
    outData.outData_1 = 1;
    outData.outData_2 = newHumid;
    outData.outData_3 = 0;

    sendData(GATEWAYID);
    sendData(BLYNKGATEWAY);
  }
}

void getTemp()
{
  // Read temperature as Celsius (the default)
  newTemp = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(newTemp))
  {
    return;
  }

  if (newTemp != oldTemp)
  {
    oldTemp = newTemp; //Store the last good percentage
    //fill in the struct with new values
    outData.outData_1 = 2;
    outData.outData_2 = 0;
    outData.outData_3 = newTemp;

    sendData(GATEWAYID);
    sendData(BLYNKGATEWAY);
  }
}

void sendData(byte destinationNode)
{
  strcpy(outData.outData_Type, "HUMID");
  //Send data to Gateway and wait for ACK
  if (radio.sendWithRetry(destinationNode, (const void*)(&outData), sizeof(outData), 3, ACK_TIME))
  {
    Blink(25);//Blink the transmitter led to show the data was successfully sent
  }
}


///////////////////////////////////////////////////////////////////////////////////////////
//                                    Blink Led function                                 //
///////////////////////////////////////////////////////////////////////////////////////////

void Blink(int DELAY_MS)//Local led blinking function
{
  digitalWrite(LED, HIGH);
  delay(DELAY_MS);
  digitalWrite(LED, LOW);
}


Felix

So it sounds like this is something in your sketch? Like missing to call flash.initialize() maybe?  :o

luisr320

Damn! That was it! Thank you very much for your time.

The strange thing is that I have been able to successfully send data to nodes using OTA without having the flash.initilize() on any sketch. And I still do. If the node is attached to a USB port on a computer, I can send data using OTA.

And I have no idea of why I removed that line in all my nodes.

Anyway, all is fixed now.
Thank you.