Same source code, different running code after serial upload and OTA upload

hi all,

So, I went on to find out more about my issue posted at #4307.

I am using NodeMCU-32s board.

As you will see in my code below, it has ThingerIO OTA handler and some code reading PCF8574 data. I did not activate the MQTT handler using compiler directives, therefore the MQTT related codes should have not been compiled.

This is what I did with the code:

  1. Clean compile with PlatformIO button and upload button using serial.
  2. Clean compile with PlatformIO and upload using ThingerIO OTA upload button.
  3. Repeat step 1 above and then Clean compile and upload using ThingerIO OTA upload button.

These are what I found in serial monitor after upload on each step above:
1. After uploading with serial usb cable, this is what I expected and how it is supposed to work:

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8

<> PCF8574 ... ready!
[NETWORK] Starting connection...
[NETWORK] Connecting to network pod_00001
[NETWORK] Connected to WiFi!
[NETWORK] Getting IP Address...
[NETWORK] Got IP Address: 172.19.199.103
[NETWORK] Connected!
[_SOCKET] Connecting to iot.thinger.io:25202...
[_SOCKET] Using secure TLS/SSL connection: yes
[_SOCKET] Connected!
[THINGER] Authenticating. User: iotregenesis Device: NodeMCU_32s_Dev_02
[THINGER] Writing bytes: 59 [OK]
[THINGER] Authenticated
Encoder 1 Value  : 1
Encoder 2 Value  : 1
[THINGER] Available bytes: 26
[THINGER] Writing bytes: 8 [OK]
[THINGER] Writing bytes: 18 [OK]

… next OTA upload was working successfully

2. After OTA upload in step 2, the running code is different – as if I included mqtt related codes in compilation … remember, I did not compile those MQTT codes by using compiler directives. But I saw this:

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
flash read err, 1000
ets_main.c 371 
ets Jun  8 2016 00:22:57

rst:0x10 (RTCWDT_RTC_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8

<> PCF8574 ... ready!
<> MQTT connection ... ready!

… and then the next OTA upload was not working

3. after executing step 3 … the same result with step 2 above:
=== autoreboot after ota ===

ets Jun  8 2016 00:22:57

rst:0xc (SW_CPU_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8

<> PCF8574 ... ready!
<> MQTT connection ... ready!

=== after I press reset button ===

ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8

<> PCF8574 ... ready!
<> MQTT connection ... ready!

… I did not compile the MQTT code lines

Can anyone help me with pointers on how to troubleshoot this?
Below are my codes.

Regards,
Fahmy

#include <Arduino.h>
#include "secrets.h"
#include "ota.h"
#include "encoder.h"
// #include "mqtt.h"

/* MCU directives */
#if !defined(LED_BUILTIN)
#define LED_BUILTIN 2 // Built in LED pin
#endif

#define __APP_DEBUG__
// #define __DEBUG_MQTT__
#define THINGER_SERIAL_DEBUG
// #define THINGER_FREE_RTOS

#include "main.h"

#if defined(__ENCODER_H__)
volatile bool readPcf = false;
void IRAM_ATTR Isr_Pcf8574_Handler()
{
    readPcf = true;
    digitalWrite(LED_BUILTIN, !digitalRead(PCF8574_INTERRUPT_PIN));
}
#endif

void setup()
{
    Serial.begin(115200);
    pinMode(LED_BUILTIN, OUTPUT);

#if defined(__ENCODER_H__)
    /* PCF8574 encoder pins */
    pcf8574.pinMode(ENC1_PIN_A, INPUT_PULLUP);
    pcf8574.pinMode(ENC1_PIN_B, INPUT_PULLUP);
    pcf8574.pinMode(ENC1_PIN_BTN, INPUT_PULLUP);
    pcf8574.pinMode(P3, INPUT_PULLUP);
    pcf8574.pinMode(ENC2_PIN_A, INPUT_PULLUP);
    pcf8574.pinMode(ENC2_PIN_B, INPUT_PULLUP);
    pcf8574.pinMode(ENC2_PIN_BTN, INPUT_PULLUP);
    pcf8574.pinMode(P7, INPUT_PULLUP);

    /* Start PCF8574 library */
    Serial.println();
    Serial.print("<> PCF8574 ... ");
    if (pcf8574.begin())
    {
        Serial.println("ready!");
    }
    else
    {
        Serial.println("timeout!");
        Serial.println("Application halted!");
        Serial.println("Please check your code and restart.");
        while (true)
            ;
    }
#endif

#if defined(__OTA_H__)
    thing.add_wifi(POD_SSID, POD_SSID_PASSWORD);
    thing["LED"] << digitalPin(LED_BUILTIN);     // input resource
    thing["HEARTBEAT"] >> outputValue(millis()); // output resource
#if defined(THINGER_FREE_RTOS)
    thing.start();
#endif
#endif

#if defined(__MQTT_H__)
    /* MQTT connection setup */
    Serial.print("<> MQTT connection ... ");
    unsigned long last_millis = millis();
    bool timeout = true;
    while (millis() - last_millis < 15000)
    {
#if !defined(THINGER_FREE_RTOS)
#if defined(__OTA_H__)
        thing.handle();
#endif
#endif
        MqttClient.loop();
        if (MqttClient.isConnected())
        {
            timeout = false;
            break;
        }
    }
    Serial.println((timeout) ? "timeout!" : "ready!");
    if (timeout)
    {
        Serial.println("Application halted!");
        Serial.println("Please check your code and restart.");
        while (true)
            ;
    }

    /* Optional functionalities of EspMQTTClient */
#if defined(__DEBUG_MQTT__)
    MqttClient.enableDebuggingMessages(); // Enable debugging messages sent to serial output
#endif
    // MqttClient.enableHTTPWebUpdater();                                              // Enable the web updater. User and password default to values of MQTTUsername and MQTTPassword. These can be overridded with enableHTTPWebUpdater("user", "password").
    // MqttClient.enableOTA();                                                         // Enable OTA (Over The Air) updates. Password defaults to MQTTPassword. Port is the default OTA port. Can be overridden with enableOTA("password", port).
    MqttClient.enableLastWillMessage(TOPIC(_PREFIX, _LastWill), LastWillMsg, true); // You can activate the retain flag by setting the third parameter to true
#endif
}

/*****
 * App Loop
 */
#if defined(__ENCODER_H__)
int Enc1_Value = 0, Enc2_Value = 0;
bool Enc_Changed = false;
#endif

void loop()
{

#if defined(__ENCODER_H__)
    PCF8574::DigitalInput enc_data = {0, 0, 1, 0, 0, 0, 1, 0}; // init pinA and pinB with LOW, pinBTN with HIGH
    static PCF8574::DigitalInput last_enc_data = {0, 0, 1, 0, 0, 0, 1, 0};
#endif

#if defined(__OTA_H__)
    thing.handle();
#endif

#if defined(__MQTT_H__)
    MqttClient.loop();
#endif

#if defined(__ENCODER_H__)
    digitalWrite(LED_BUILTIN, !digitalRead(PCF8574_INTERRUPT_PIN));

    if (readPcf)
    {
        enc_data = pcf8574.digitalReadAll();

        /* Encoder 1 */
        if ((last_enc_data.ENC1_BIT_A == LOW) && (enc_data.ENC1_BIT_A == HIGH))
        {
            if (enc_data.ENC1_BIT_B == LOW)
            {
                if (Enc1_Value)
                {
                    Enc1_Value--;
                    Enc_Changed = true;
                }
            }
            else
            {
                if (Enc1_Value < 100)
                {
                    Enc1_Value++;
                    Enc_Changed = true;
                }
            }
#if defined(__APP_DEBUG__)
            Serial.print("Encoder 1 Value  : ");
            Serial.println(Enc1_Value);
#endif
#if defined(__MQTT_H__)
            MqttClient.publish(TOPIC(_PREFIX, _ENC1_VALUE), String(Enc1_Value), true);
#endif
        }
        last_enc_data.ENC1_BIT_A = enc_data.ENC1_BIT_A;

        /* Encoder 1 Button */
        if (last_enc_data.ENC1_BIT_BTN != enc_data.ENC1_BIT_BTN)
        {
            Enc_Changed = true;
            last_enc_data.ENC1_BIT_BTN = enc_data.ENC1_BIT_BTN;
#if defined(__APP_DEBUG__)
            Serial.print("Encoder 1 button : ");
            Serial.println((!enc_data.ENC1_BIT_BTN) ? "Pressed" : "Released");
#endif
#if defined(__MQTT_H__)
            MqttClient.publish(TOPIC(_PREFIX, _ENC1_BTN), (!last_enc_data.ENC1_BIT_BTN) ? "Pressed" : "Released", true);
#endif
        }

        /* Encoder 2 */
        if ((last_enc_data.ENC2_BIT_A == LOW) && (enc_data.ENC2_BIT_A == HIGH))
        {
            if (enc_data.ENC2_BIT_B == LOW)
            {
                if (Enc2_Value)
                {
                    Enc2_Value--;
                    Enc_Changed = true;
                }
            }
            else
            {
                if (Enc2_Value < 100)
                {
                    Enc2_Value++;
                    Enc_Changed = true;
                }
            }
#if defined(__APP_DEBUG__)
            Serial.print("Encoder 2 Value  : ");
            Serial.println(Enc2_Value);
#endif
#if defined(__MQTT_H__)
            MqttClient.publish(TOPIC(_PREFIX, _ENC2_VALUE), String(Enc2_Value), true);
#endif
        }
        last_enc_data.ENC2_BIT_A = enc_data.ENC2_BIT_A;

        /* Encoder 2 Button */
        if (last_enc_data.ENC2_BIT_BTN != enc_data.ENC2_BIT_BTN)
        {
            Enc_Changed = true;
            last_enc_data.ENC2_BIT_BTN = enc_data.ENC2_BIT_BTN;
#if defined(__APP_DEBUG__)
            Serial.print("Encoder 2 button : ");
            Serial.println((!enc_data.ENC2_BIT_BTN) ? "Pressed" : "Released");
#endif
#if defined(__MQTT_H__)
            MqttClient.publish(TOPIC(_PREFIX, _ENC2_BTN), (!last_enc_data.ENC2_BIT_BTN) ? "Pressed" : "Released", true);
#endif
        }
        Enc_Changed = false;
    }
    readPcf = false;
#endif
}

#if defined(__MQTT_H__)
void onConnectionEstablished()
{
    MqttClient.publish(TOPIC(_PREFIX, _MOD_STATUS), "Online");
}
#endif

… I just did the 4th step. Which is:

  1. Clean compile and upload using ThingerIO OTA upload button – which off course the OTA upload would fail. Then I uploaded it using serial cable. The program was running as expected:
ets Jun  8 2016 00:22:57

rst:0x1 (POWERON_RESET),boot:0x13 (SPI_FAST_FLASH_BOOT)
configsip: 0, SPIWP:0xee
clk_drv:0x00,q_drv:0x00,d_drv:0x00,cs0_drv:0x00,hd_drv:0x00,wp_drv:0x00
mode:DIO, clock div:2
load:0x3fff0018,len:4
load:0x3fff001c,len:1044
load:0x40078000,len:10124
load:0x40080400,len:5828
entry 0x400806a8

<> PCF8574 ... ready!
[NETWORK] Starting connection...
[NETWORK] Connecting to network pod_00001
[NETWORK] Connected to WiFi!
[NETWORK] Getting IP Address...
[NETWORK] Got IP Address: 172.19.199.103
[NETWORK] Connected!
[_SOCKET] Connecting to iot.thinger.io:25202...
[_SOCKET] Using secure TLS/SSL connection: yes
[_SOCKET] Connected!
[THINGER] Authenticating. User: iotregenesis Device: NodeMCU_32s_Dev_02
[THINGER] Writing bytes: 59 [OK]
[THINGER] Authenticated
Encoder 1 Value  : 1
Encoder 2 Value  : 1

So, what should I do to fix OTA transfer failure ?

Cheers,
Fahmy