esp8266 / Arduino

ESP8266 core for Arduino
GNU Lesser General Public License v2.1
16.05k stars 13.33k forks source link

Using MQTT (PubSubClient.h) with timed function crash: Fatal exception 9 #2472

Closed odilonafonso closed 8 years ago

odilonafonso commented 8 years ago

Basic Infos

Hardware

Hardware: ESP-12 V1 Core Version: 2.3

Description

After I include the use of OTA in my application, after some time the system falls with this message:

Fatal exception 9 (LoadStoreAlignmentCause):
EPC1 = 0x40105c64, EPC2 = 0x00000000, 0x00000000 = epc3, excvaddr = 0x00000003, 0x00000000 = DEPC

Exception (9):
EPC1 = 0x40105c64 EPC2 = 0x00000000 0x00000000 excvaddr epc3 = = 0x00000003 0x00000000 = DEPC

ctx: sys
sp: 3ffffbf0 end: 3fffffb0 offset: 01a0

Settings in IDE

Module: NodeMCU 1.0 (ESP-12e module) Flash Size: 4MB/3MB CPU Frequency: 80Mhz Flash Mode: dio Flash Frequency: ?40Mhz? Upload Using: SERIAL Reset Method: nodemcu

Sketch

Not relevant - OTA included with Basic OTA sample from ArduinoOTA library

Debug Messages

(I used Debug Level: "OTA + Updater")

Booting OTA server at: esp8266-02580f.local:8266 OTA Ready IP address: 192.168.2.103 Station macAddress:5C:CF:7F:02:58:0F

odilonafonso commented 8 years ago

Correction

The problem is not the use of OTA, but with MQTT. I'm using a function controlled by timer - os_timer_t. I based myself in this example:

(Http://www.switchdoc.com/2015/10/iot-esp8266-timer-tutorial-arduino-ide/)

The function is quite simple, works perfectly fine without the call to MQTT; when I place a call to MQTT to publish some information on the reading of a SoilSensor, the system fails.

Is there any impediment in the use of MQTT with os_timer_t?

I found this review from @igrr:

This project is not based on FreeRTOS, so you have to use Espressif's SDK
calls to start the task. Make sure you do not call any blocking functions from
this new task it is the cooperatively scheduled. The task has to function
return to avoid blocking execution of other tasks. Calling Certain Arduino
functions (delay, Serial IO, IO WiFiClient) may also cause unexpected
behavior.

Obtained in reading issue #399 - Starting additional Tasks

I'm unable to find a solution. Does anyone know what can be done, please? Thanks

krzychb commented 8 years ago

Hi @odilonafonso,

In example you refer to, the timer periodically sets a flag that is then used inside the loop() to conditionally run another process.

If you do the same and "place a call to MQTT" inside the loop() (not inside timerCallback), then you will not be blocking the callback.

Krzysztof

odilonafonso commented 8 years ago

Hi @krzychb,

Well, I think I understand how to use the os_timer functions. But I appreciate your interest in helping.

If you can, please help me understand what's going on.

I did a little class (attached, if you want to examine), using the functions:

os_timer_arm and os_timer_setfn

Used a granularity 1000, or 1 second. Called "boom".

Then defined a table with various functions to be triggered with "timers" distinct, they all bound to the same granularity - each function has its trigger associated with the same boom - a function is triggered every 5 "booms", that is, each 5 seconds. Another function every 10 seconds. Etc..

For example, a function reads a soil moisture sensor every 10 "booms".

Another, triggers a status LED every 30 "booms". And so on.

This is very comfortable because it does not need to put any code inside the loop () function.

However, the application fails after some time, sometimes faster, sometimes takes a little longer.

And it is difficult to identify the problem, but when I eliminate the drive to MQTT - where I publish the result of the reading of the sensor, for example, or some other activity - the application can also be triggered by MQTT callback which is subscribed to meet clients requests (browser, smartphone, etc..) - there then the application no longer crash.

Now, to solve this problem crash, I made a small change in TimerMultiTask library, simulating the interruption of os_timer_arm through a similar mechanism, using millis ().

But it is not the same. And it's not very elegant. It is not falling, but I would like to find out - and run - through os_timer functions.

TimerMultiTask.zip

MillisMultiTask.zip

One more thing, I did some tests using this TimerMultiTask library without MQTT without OTA. Run for hours, triggering up to 5 functions with different purposes and driving times. Of course, features simpler instead of to send and receive messages MQTT. But its mechanism is approved.

igrr commented 8 years ago

Using os_timer functions essentially achieves the same as built-in Ticker library. It is mentioned in the documentation that one can not call blocking functions (in particular, network functions) from Ticker callbacks. Same holds true for os_timer callbacks.

odilonafonso commented 8 years ago

Hi @igrr, thank you for help ! Please, can you send me a link to the documentation ? This is the library that you mentioned - ticker ?

igrr commented 8 years ago

https://github.com/esp8266/Arduino/blob/master/doc/libraries.md#ticker

odilonafonso commented 8 years ago

Thanks !!! I spent a good little time making a needlessly class. TickerScheduler have what I need. Well, then I will use the feature on / off flag. I was happy in need do not code in the loop (). Can you tell me if GPIO operations can be done or I will need also do it out of the callback? In particular, I need to read a pin being used to activate a relay. Define this pin as INPUT_PULLUP. Some problem ?

igrr commented 8 years ago

Yes, GPIO operations are okay in Ticker callbacks.

odilonafonso commented 8 years ago

Thanks guys...

odilonafonso commented 8 years ago

Now it is working perfect !!! No Millis ()