Page 1 of 1

Use WDT using ESP8266

Posted: Mon Oct 22, 2018 5:12 pm
by guyd
Hi,
I try to use WDT as noted in http://docs.micropython.org/en/v1.9.3/w ... e.WDT.html, where it specifically instruct to input a apatmeter called `timeout` to define max time until next feed. BUT when I write same code as noted I get an error says :

Code: Select all

from machine import WDT
>>> wdt=WDT(timeout=2)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: function does not take keyword arguments
why is that ?

Re: Use WDT using ESP8266

Posted: Mon Oct 22, 2018 6:07 pm
by jickster
Firstly your link is not for the ESP8266 but for the WiPy; in this it doesn't matter but be careful cause sometimes there's differences.

Secondly do not expect the documentation to be up to date. Example: I switched to the ESP8266 version http://docs.micropython.org/en/v1.9.4/e ... hlight=wdt yet it has this text
Availability of this class: pyboard, WiPy.
Why put it in the ESP8266 docs if it's not accessible in that module? #shrugemoji

Refer to:
Secondly do not expect the documentation to be up to date.

Re: Use WDT using ESP8266

Posted: Mon Oct 22, 2018 6:22 pm
by jickster
But wait there's more!

WDT does exist for ESP8266. How do I know? By looking at the C-code (and by the fact that when you attempted to use it, you were able to get SOME response).

I also looked at the the file machine_wdt.c and I do not see how you can set a timeout at all.

The only argument allowed to the constructor is 0 (which is also the default if you leave it blank).
There are two functions: feed, deinit
but I don't see how to set the timeout.

It ?appears? the watchdog is meant for the system's use and not your own use but there should be some way to set the timeout.

Code: Select all

#include <string.h>

#include "py/runtime.h"
#include "user_interface.h"
#include "etshal.h"
#include "ets_alt_task.h"

const mp_obj_type_t esp_wdt_type;

typedef struct _machine_wdt_obj_t {
    mp_obj_base_t base;
} machine_wdt_obj_t;

STATIC machine_wdt_obj_t wdt_default = {{&esp_wdt_type}};

STATIC mp_obj_t machine_wdt_make_new(const mp_obj_type_t *type_in, size_t n_args, size_t n_kw, const mp_obj_t *args) {
    mp_arg_check_num(n_args, n_kw, 0, 1, false);

    mp_int_t id = 0;
    if (n_args > 0) {
        id = mp_obj_get_int(args[0]);
    }

    switch (id) {
    case 0:
        ets_loop_dont_feed_sw_wdt = 1;
        system_soft_wdt_feed();
        return &wdt_default;
    default:
        mp_raise_ValueError(NULL);
    }
}

STATIC mp_obj_t machine_wdt_feed(mp_obj_t self_in) {
    (void)self_in;
    system_soft_wdt_feed();
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_feed_obj, machine_wdt_feed);

STATIC mp_obj_t machine_wdt_deinit(mp_obj_t self_in) {
    (void)self_in;
    ets_wdt_disable();
    return mp_const_none;
}
STATIC MP_DEFINE_CONST_FUN_OBJ_1(machine_wdt_deinit_obj, machine_wdt_deinit);

STATIC const mp_rom_map_elem_t machine_wdt_locals_dict_table[] = {
    { MP_ROM_QSTR(MP_QSTR_feed), MP_ROM_PTR(&machine_wdt_feed_obj) },
    { MP_ROM_QSTR(MP_QSTR_deinit), MP_ROM_PTR(&machine_wdt_deinit_obj) },
};
STATIC MP_DEFINE_CONST_DICT(machine_wdt_locals_dict, machine_wdt_locals_dict_table);

const mp_obj_type_t esp_wdt_type = {
    { &mp_type_type },
    .name = MP_QSTR_WDT,
    .make_new = machine_wdt_make_new,
    .locals_dict = (mp_obj_dict_t*)&machine_wdt_locals_dict,
};

Re: Use WDT using ESP8266

Posted: Mon Oct 22, 2018 6:49 pm
by kevinkk525
I'm using a software watchdog on the esp8266 using interrupts and uasyncio. Maybe you find it useful:

Code: Select all

import gc
import uasyncio as asyncio
import machine
from pysmartnode.utils import sys_vars
from sys import platform

gc.collect()
from pysmartnode import logging


class WDT:
    def __init__(self, id=0, timeout=120, use_rtc_memory=True):
        self._timeout = timeout / 10
        self._counter = 0
        self._timer = machine.Timer(id)
        self._use_rtc_memory = use_rtc_memory
        self.init()
        asyncio.get_event_loop().create_task(self._resetCounter())
        if sys_vars.hasFilesystem():
            try:
                with open("watchdog.txt", "r") as f:
                    if f.read() == "True":
                        logging.getLogger("WDT").warn("Reset reason: Watchdog")
            except Exception as e:
                print(e)  # file probably just does not exist
            try:
                with open("watchdog.txt", "w") as f:
                    f.write("False")
            except Exception as e:
                logging.getLogger("WDT").error("Error saving to file: {!s}".format(e))
        elif use_rtc_memory and platform == "esp8266":
            rtc = machine.RTC()
            if rtc.memory() == b"WDT reset":
                logging.getLogger("WDT").warn("Reset reason: Watchdog")
            rtc.memory(b"")

    def _wdt(self, t):
        self._counter += self._timeout
        if self._counter >= self._timeout * 10:
            if sys_vars.hasFilesystem():
                try:
                    with open("watchdog.txt", "w") as f:
                        f.write("True")
                except Exception as e:
                    print("Error saving to file: {!s}".format(e))
            elif self._use_rtc_memory and platform == "esp8266":
                rtc = machine.RTC()
                rtc.memory(b"WDT reset")
            machine.reset()

    def feed(self):
        self._counter = 0

    def init(self, timeout=None):
        timeout = timeout or self._timeout
        self._timeout = timeout
        self._timer.init(period=int(self._timeout * 1000), mode=machine.Timer.PERIODIC, callback=self._wdt)

    def deinit(self):  # will not stop coroutine
        self._timer.deinit()

    async def _resetCounter(self):
        while True:
            await asyncio.sleep(self._timeout)
            self.feed()
def hasFilesystem():
return not os.statvfs("")[0] == 0

Re: Use WDT using ESP8266

Posted: Thu Sep 09, 2021 5:04 pm
by ihornehrutsa
Add WDT.deinit() method #7766
https://github.com/micropython/micropython/issues/7766

ESP32/machine_wdt.c: Add WDT.deinit() method. #6631
https://github.com/micropython/micropython/pull/6631