jpraus / arduino-opentherm

Arduino library and hardware shield to send and receive data from Opentherm devices
Other
169 stars 43 forks source link

With ESP32 OTA updates fails on this library #38

Open Polderdijk opened 2 years ago

Polderdijk commented 2 years ago

Hi,

Thanks for this project! It runs very smooth!

Only one thing I noticed is that I can't use OTA updates when including this library.

The problem is in the __timerISR but have no clue to solve this issue.

I use the standard Arduino OTA script:

esp_task_wdt_deinit(); noInterrupts(); HTTPUpload& upload = server.upload(); if (upload.status == UPLOAD_FILE_START) { Serial.printf("Update: %s\n", upload.filename.c_str()); -- the script will crash here

The debug info: 16:52:56.016 -> Update: 1_mcuthermostaat.ino.esp32.bin 16:52:56.496 -> Guru Meditation Error: Core 1 panic'ed (Cache disabled but cached memory region accessed) 16:52:56.496 -> Core 1 register dump: 16:52:56.496 -> PC : 0x400d3ff4 PS : 0x00060034 A0 : 0x80082140 A1 : 0x3ffbffd0 16:52:56.496 -> A2 : 0x3ffbdc20 A3 : 0x3ffc2670 A4 : 0xfffffffb A5 : 0x3ffc2668 16:52:56.496 -> A6 : 0x3ffc0018 A7 : 0x00000001 A8 : 0x800813bb A9 : 0x3ffbffb0 16:52:56.496 -> A10 : 0x00000001 A11 : 0x3ffb1a10 A12 : 0x8009130b A13 : 0x3ffbffa0 16:52:56.496 -> A14 : 0x00000008 A15 : 0x00000001 SAR : 0x00000003 EXCCAUSE: 0x00000007 16:52:56.496 -> EXCVADDR: 0x00000000 LBEG : 0x4008cc44 LEND : 0x4008cc60 LCOUNT : 0x00000000 16:52:56.496 -> Core 1 was running in ISR context: 16:52:56.496 -> EPC1 : 0x40062230 EPC2 : 0x00000000 EPC3 : 0x00000000 EPC4 : 0x400d3ff4 16:52:56.496 -> 16:52:56.496 -> ELF file SHA256: 0000000000000000 16:52:56.496 -> 16:52:56.496 -> Backtrace: 0x400d3ff4:0x3ffbffd0 0x4008213d:0x3ffbfff0 0x4008a941:0x3ffc0010 0x4006222d:0x3ffb1950 0x40094deb:0x3ffb1970 0x40094e26:0x3ffb19a0 0x40094eb2:0x3ffb19d0 0x40095321:0x3ffb19f0 0x4008b448:0x3ffb1a10 0x4014f086:0x3ffb1a30 0x400dbc6d:0x3ffb1a50 0x400da2fc:0x3ffb1a70 0x400da4cd:0x3ffb1a90 0x400d1550:0x3ffb1ab0 0x400d8f22:0x3ffb1ad0 0x400d8f62:0x3ffb1af0 0x400d6196:0x3ffb1b20 0x400d6e29:0x3ffb1b50 0x400d7d09:0x3ffb1d50 0x400d919d:0x3ffb1f10 0x400d349e:0x3ffb1f60 0x400d3cb6:0x3ffb1f80 0x400dd33d:0x3ffb1fb0 0x4008fb3e:0x3ffb1fd0 16:52:56.496 -> 16:52:56.496 -> Rebooting...

And if I run the Exception Decoder it gave a hint to:

` C: 0x400d3ff4: OPENTHERM::_read() at \server\Maarten\Projecten\Arduino\Projecten\libraries\arduino-opentherm-master\src\opentherm.cpp line 92 EXCVADDR: 0x00000000

Decoding stack results 0x400d3ff4: OPENTHERM::_read() at \server\Maarten\Projecten\Arduino\Projecten\libraries\arduino-opentherm-master\src\opentherm.cpp line 92 0x4008213d: __timerISR at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\esp32-hal-timer.c line 88 0x40094deb: esp_rom_spiflash_read_status at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 262 0x40094e26: esp_rom_spiflash_wait_idle at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 35 0x40094eb2: esp_rom_spiflash_erase_sector_internal at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 122 0x40095321: esp_rom_spiflash_erase_sector at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/spi_flash_rom_patch.c line 452 0x4008b448: spi_flash_erase_range at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/flash_ops.c line 247 0x4014f086: esp_partition_erase_range at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/spi_flash/partition.c line 294 0x400dbc6d: EspClass::partitionEraseRange(esp_partition_t const, unsigned int, unsigned int) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\Esp.cpp line 341 0x400da2fc: UpdateClass::_writeBuffer() at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\Update\src\Updater.cpp line 200 0x400da4cd: UpdateClass::write(unsigned char, unsigned int) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\Update\src\Updater.cpp line 308 0x400d1550: std::_Function_handler >::_M_invoke(const std::_Any_data &) at \server\Maarten\Projecten\Arduino\Projecten\mcuthermostaat\1_mcuthermostaat/9_Webserver.ino line 95 0x400d8f22: std::function ::operator()() const at c:\users\maarten\appdata\local\arduino15\packages\esp32\tools\xtensa-esp32-elf-gcc\1.22.0-97-gc752ad5-5.2.0\xtensa-esp32-elf\include\c++\5.2.0/functional line 2271 0x400d8f62: FunctionRequestHandler::upload(WebServer&, String, HTTPUpload&) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src\detail/RequestHandlersImpl.h line 53 0x400d6196: WebServer::_uploadWriteByte(unsigned char) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src\Parsing.cpp line 306 0x400d6e29: WebServer::_parseForm(WiFiClient&, String, unsigned int) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src\Parsing.cpp line 445 0x400d7d09: WebServer::_parseRequest(WiFiClient&) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src\Parsing.cpp line 207 0x400d919d: WebServer::handleClient() at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\libraries\WebServer\src\WebServer.cpp line 310 0x400d349e: WiFiTasks() at \server\Maarten\Projecten\Arduino\Projecten\mcuthermostaat\1_mcuthermostaat/3_Setup.ino line 435 0x400d3cb6: loop() at \server\Maarten\Projecten\Arduino\Projecten\mcuthermostaat\1_mcuthermostaat/3_Setup.ino line 422 0x400dd33d: loopTask(void*) at C:\Users\Maarten\AppData\Local\Arduino15\packages\esp32\hardware\esp32\1.0.6\cores\esp32\main.cpp line 23 0x4008fb3e: vPortTaskWrapper at /home/runner/work/esp32-arduino-lib-builder/esp32-arduino-lib-builder/esp-idf/components/freertos/port.c line 143 `

jpraus commented 2 years ago

Thanks for the report, Can you provide me with your full code including the steps how to reproduce? Thanks!

jpraus commented 2 years ago

Hi,

I am not sure at the moment, I believe there was successful usage of the OT shield on the ESP32 but I don't remember if I done that as well. I have the board home so I will check that soon. Feel free to add support :)

-- Jiří Praus Maker of everblooming flowers www.floower.io

On Mon, 24 Jan 2022 at 19:34, rbamberg @.***> wrote:

Hi, i've tried compiling the Code from https://github.com/jpraus/arduino-opentherm/blob/master/examples/gateway/gateway.ino with ESP32 Dev Module selected in Arduino IDE and it fails with the following message. Is your library supposed to work with an ESP32?

WARNING: library Opentherm claims to run on avr, esp8266 architecture(s) and may be incompatible with your current board which runs on esp32 architecture(s).

C:\Users\xxxx\Documents\Arduino\libraries\Opentherm\src\opentherm.cpp:101:27: error: no 'void OPENTHERM::_timerISR()' member function declared in class 'OPENTHERM' void OPENTHERM::_timerISR() {

                   ^

exit status 1 Error compiling for board ESP32 Dev Module.

— Reply to this email directly, view it on GitHub https://github.com/jpraus/arduino-opentherm/issues/38#issuecomment-1020415476, or unsubscribe https://github.com/notifications/unsubscribe-auth/AAVGP4ARHTP4U2KGPHQHLH3UXWLRZANCNFSM5MSE2GRA . Triage notifications on the go with GitHub Mobile for iOS https://apps.apple.com/app/apple-store/id1477376905?ct=notification-email&mt=8&pt=524675 or Android https://play.google.com/store/apps/details?id=com.github.android&referrer=utm_campaign%3Dnotification-email%26utm_medium%3Demail%26utm_source%3Dgithub.

You are receiving this because you commented.Message ID: @.***>

halecivo commented 2 years ago

I have the same issue after I tried to update my HW from ESP8266 to ESP32. I use ESPHome integration of home assistant and my code is:

#include <esphome.h>
#include "opentherm.h"

using namespace esphome;
using namespace esphome::sensor;

class OpenthermBoiler : public Component {
public:
    //OpenthermBoiler() : Component(50){}
    Sensor * modulation = new Sensor();
    Sensor * ch_temperature = new Sensor();
    Sensor * ch_target = new Sensor();
    bool initialized = false;
    void setup() override {
        // This will be called once to set up the component
        // think of it as the setup() call in Arduino
    }
    void loop() override {
        if (initialized) {
            static endpoint listen_from = endpoint::MASTER;
            static OpenthermData message;
            if (listen_from == endpoint::MASTER) {
                if (OPENTHERM::isSent() || OPENTHERM::isIdle() || OPENTHERM::isError()) {
                    OPENTHERM::listen(THERMOSTAT_IN);
                } else if (OPENTHERM::getMessage(message)) {
                    OPENTHERM::send(BOILER_OUT, message); // forward message to boiler
                    listen_from = endpoint::SLAVE;
                }
            } else if (listen_from == endpoint::SLAVE) {
                if (OPENTHERM::isSent()) {
                    OPENTHERM::listen(BOILER_IN, 800); // response need to be send back by boiler within 800ms
                } else if (OPENTHERM::getMessage(message)) {
                    opentherm_handle_slave_message(message);
                    OPENTHERM::send(THERMOSTAT_OUT, message); // send message back to thermostat
                    listen_from = endpoint::MASTER;
                } else if (OPENTHERM::isError()) {
                    listen_from = endpoint::MASTER;
                }
            }
        }
        else
        {
            if (millis() > 30000)
            {
                pinMode(THERMOSTAT_IN, INPUT);
                digitalWrite(THERMOSTAT_IN, HIGH); // pull up
                digitalWrite(THERMOSTAT_OUT, HIGH);
                pinMode(THERMOSTAT_OUT, OUTPUT); // low output = high current, high output = low current
                pinMode(BOILER_IN, INPUT);
                digitalWrite(BOILER_IN, HIGH); // pull up
                digitalWrite(BOILER_OUT, LOW);
                pinMode(BOILER_OUT, OUTPUT); // low output = high voltage, high output = low voltage
                initialized = true;
                ESP_LOGD("custom", "Initialized.");
            }
        }
    }
private:
    void opentherm_handle_slave_message(OpenthermData &data)
    {
            if ((data.type == OT_MSGTYPE_WRITE_ACK)
                || (data.type == OT_MSGTYPE_READ_ACK))
            {
                switch (data.id)
                {
                    case OT_MSGID_FEED_TEMP:
                    {
                        ch_temperature->publish_state(data.f88());
                        break;
                    }
                    case OT_MSGID_CH_SETPOINT:
                    {
                        ch_target->publish_state(data.f88());
                        break;
                    }
                    case OT_MSGID_MODULATION_LEVEL:
                    {
                        modulation->publish_state(data.f88());
                        break;
                    }
                    case OT_MSGID_STATUS:
                    {
                        //flame_on->publish_state(data.valueLB & (1u << 3u));
                        //service->publish_state(data.valueLB & (1u << 6u));
                        //fault->publish_state(data.valueLB & 1u);
                        break;
                    }
                    case OT_MSGID_REMOTE:
                    default:
                        break;
                }

            }
    }
    enum class endpoint
    {
        MASTER,
        SLAVE
    };
    static constexpr uint8_t THERMOSTAT_IN = 14;
    static constexpr uint8_t THERMOSTAT_OUT = 17;
    static constexpr uint8_t BOILER_IN = 25;
    static constexpr uint8_t BOILER_OUT = 16;
};

and esphome configuration

esphome:
  name: thermos
  includes:
    - thermos_climate.h
  libraries:
    - "jpraus/Opentherm@^1.1.0"

esp32:
  board: nodemcu-32s

# Enable logging
logger:

# Enable Home Assistant API
api:

sensor:
- platform: custom
  lambda: |-
    auto ot_component = new OpenthermBoiler();
    App.register_component(ot_component);
    return {ot_component->modulation};

  sensors:
  - name: "Boiler modulation"
    unit_of_measurement: '%'
    accuracy_decimals: 0

ota:
  password: "xxxxxxx"

wifi:
  ssid: xxxxx
  password: xxxxx

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Thermos Fallback Hotspot"
    password: "xxxxxxx"

captive_portal:

Can I help in some way?

halecivo commented 2 years ago

In the end, I came across this following ESPHome config https://github.com/piio/esphome-opentherm, mentioning compatibility with JPraus's shield and it seems work fine (although it uses different opentherm library).

jpraus commented 2 years ago

That is great! Thank you for letting me know!

bvweerd commented 1 year ago

You will have to disable the timer interrupt when starting the OTA, like this:

void ICACHE_FLASH_ATTR hw_timer_disable(void) {
  timer1_disable();
}

ArduinoOTA.onStart([]() {
  Serial.println("Start");
  hw_timer_disable();
});