How can I reset ESP8266 MicroPython after main.py crashes?
Asked Answered
I

4

6

I have a NodeMCU ESP8266 board running MicroPython. I'm running a web server on my ESP8266. This is my first IoT project based on one of these boards.

The below is a snippet of the code.

This is being executed within main.py. Every now and then, something causes the code to crash (perhaps timing and request based). When main.py exits, for whatever reason, I'm dropped back at the python CLI.

I'd like for the board to reset when this happens (if there isn't a better way).

What is the best method of restarting/reseting the ESP8266?

addr = socket.getaddrinfo('0.0.0.0', 80)[0][-1]

s = socket.socket()
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind(addr)
s.listen(5)
print('listening on', addr)

while True:
    cl, addr = s.accept()
    print('client connected from', addr)
    cl_file = cl.makefile('rwb', 0)
    print("Request:")
    while True:
        line = cl_file.readline()
        print("Line:" , line)
        if not line or line == b'\r\n':
            print("breaking")
            break
        if line == b'GET /active HTTP/1.1\r\n':
Insentient answered 5/3, 2017 at 7:29 Comment(2)
This is the error that is reported when the webserver exits. OSError: [Errno 104] ECONNRESETInsentient
Although the docs say the machine.WDT watchdog timer is not available for the esp8266, this forum post implies it is now implemented in basic form. That would probably be the first thing to try. (The zeroth thing to try would be to figure out how to stop your code crashing, of course). This thread also has some discussion about creating a watchdog on the ESP.Scarabaeid
C
-1

You could execute your code (which should be outside of the main.py -> other file) from the boot or the main.py. if it drops out it should execute the following code, which could trigger a reset.

You may have to catch the error first.

I hope I helped

Chore answered 3/4, 2017 at 14:50 Comment(2)
Perhaps a code snippet would help clarify your responsePurse
This is the approach that I took. I moved my main code to boot.py and then within main.py I include a call to reset the ESP8266. If anything caused the web service loop to terminate, boot.py would exit and main.py would execute, reseting the device. I found better reliability though in shifting to lua and mqtt on the ESP8266 and moving the web service component to an actual apache webserver running on another host.Insentient
I
10

MicroPython has machine.reset() function to reset a board.

Python (not just MicroPython) uses exception handling to handle errors.

Combining the two, you can easily achieve what you want. For example:

a = 4
b = 2
try:
    a / b
except:
    machine.reset()

If in the code above you replace value of b with 0, your board will reset. If you think about it for a bit, you probably will find out that it doesn't make much sense - you don't want your board suddenly reset if you just divide by 0 by mistake or otherwise. There're got to be better ways to handle errors! Likewise, you may want to think about your own case and see if resetting the board is really the best choice. If you think that yes, that's fine, just always keep in mind that you programmed your board to suddenly reset. Otherwise, your next question here may be "My board suddenly resets! Why???" ;-)

Isolt answered 29/6, 2017 at 18:58 Comment(1)
This is a nice response, an efficient way to accomplish what was requested AND some thoughts on better practices or paths to solving the underlying problem.Harmonia
B
6

It may be late for the original question, but the answer I am going to share might help other people. Consider it is not a final solution, but in many scenarios, it may save a day. You can explore your case.

The solution is using the internal scheduling function of MicroPython. since its execution is guaranteed, then its behavior can be used as a tool to mimic a functional watchdog.

Following code will run with given timers and threshold which can be customized in your case, and if the timer reaches its threshold, and the value of wd_buffer is not updated for that time, then the function might be called, and we repeat the process again. So in order to prevent the ESP getting restarted in this case after 12 sec, you have to in someplace in your code, periodically (shorter than 12 sec or adjust the timer and threshold according to your need) update the value of the Global wd_buffer variable. Hope it helps.

# Simple WD - Global Variable
wd_feeder = 0 
wd_buffer = 0
wd_counter = 0
wd_threshold = 4

def wd_checker(calledvalue):
    print('watchdog is checking... feeder= {} buffer= {}'.format(wd_feeder, wd_buffer))
    global wd_counter
    global wd_buffer
    global wd_feeder
    if wd_feeder == wd_buffer:
        print('state is suspicious ... counter is {} incrementing the counter'.format(wd_counter))
        wd_counter += 1
    else:
        wd_counter = 0
        wd_feeder = wd_buffer
    if wd_counter == wd_threshold:
        print('Counter is reached its threshold, following function will be called')
        wd_feeder = wd_buffer = wd_counter = 0
        machine.reset()


if __name__ == '__main__':
    scheduler_wd = machine.Timer(-1)
    scheduler_wd.init(period=3000, mode=machine.Timer.PERIODIC, callback=wd_checker)
Blackthorn answered 12/1, 2018 at 12:44 Comment(0)
L
1

you could add a while loop checking for the Flash Button (GPIO pin 0) like this:

import machine
pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)                                                                 
while pin.value():
    print('Put your code here...')
    print('..this will looping until the Flash button is pressed...')

print('...and then it continues here.')
Laguna answered 5/10, 2017 at 22:2 Comment(0)
C
-1

You could execute your code (which should be outside of the main.py -> other file) from the boot or the main.py. if it drops out it should execute the following code, which could trigger a reset.

You may have to catch the error first.

I hope I helped

Chore answered 3/4, 2017 at 14:50 Comment(2)
Perhaps a code snippet would help clarify your responsePurse
This is the approach that I took. I moved my main code to boot.py and then within main.py I include a call to reset the ESP8266. If anything caused the web service loop to terminate, boot.py would exit and main.py would execute, reseting the device. I found better reliability though in shifting to lua and mqtt on the ESP8266 and moving the web service component to an actual apache webserver running on another host.Insentient

© 2022 - 2025 — McMap. All rights reserved.