Strange behavior of time on ESP8266

All ESP8266 boards running MicroPython.
Official boards are the Adafruit Huzzah and Feather boards.
Target audience: MicroPython users with an ESP8266 board.
lazarvgd
Posts: 39
Joined: Sun May 20, 2018 8:57 am

Re: Strange behavior of time on ESP8266

Post by lazarvgd » Sat Nov 03, 2018 1:50 pm

Update:

I just got the exception, which is tied to NTP library. Probably should add a few try catch blocks to handle it.

Code: Select all

(2018, 11, 3, 13, 30, 1, 5, 307)
Traceback (most recent call last):
  File "main.py", line 41, in <module>
  File "ntptime.py", line 30, in settime
  File "ntptime.py", line 22, in time
OSError: [Errno 110] ETIMEDOUT

deonis
Posts: 11
Joined: Wed Aug 08, 2018 3:02 am

Re: Strange behavior of time on ESP8266

Post by deonis » Sat Nov 03, 2018 4:12 pm

Your design looks good but I had some problem with NodeMCU-like boards. They are very peaky on the power supply because of AMS1117 voltage regulator. I also use a mobile phone power supply for all my application with
esp8266.

Some tips:

If you have access point enabled on your esp8266 disable it. It is better to run the board in one mode only, in your case station mode. In my experience, it was causing the board to freeze and sometimes reboot.

What is the current of your power supply? Check the voltage dropout on your barebone esp8266 chip during relay startup.

Check this video for more details about the power problem of esp8266:
https://www.youtube.com/watch?v=wf_msvWv1jk

good luck

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: Strange behavior of time on ESP8266

Post by kevinkk525 » Sat Nov 03, 2018 5:06 pm

I use 5 esp8266 lolin nodemcu all the time with different power supplies (mostly phone chargers) and have not have a single problem (except occasional freezes that my software watchdog takes care of). So I wouldn't concentrate too much on power supply. try to debug it a little more by logging stuff and just switch the power supply just in case.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

lazarvgd
Posts: 39
Joined: Sun May 20, 2018 8:57 am

Re: Strange behavior of time on ESP8266

Post by lazarvgd » Sun Nov 04, 2018 9:38 am

Last night everything was fine. Heater was started at 0000h and turned off at 0800h (GMT+1). Looks like my code is working as expected. :mrgreen: :mrgreen: :mrgreen: :mrgreen: :mrgreen:

I have updated the code in order to check if pin needs to be turned off/on depending on time interval and pin status. This has been added to avoid constant putting pin in the same status.

I would really appreciate if you can review my code and tell me if I made some logic mistake.
Thanks

the code:

Code: Select all

import machine
import network
import time
import ntptime
import utime

OFF = 1
ON = 0

sta_if = network.WLAN(network.STA_IF)
led = machine.Pin(2, machine.Pin.OUT)
led.on()
is_updated = False

################################################
#Methods

def write_to_file(status, time):
    file = open('log.txt','w')
    file.write(status)
    file.write(str(time))
    file.close()

#setup network
def connect_on_network():
    # sta_if = network.WLAN(network.STA_IF)
    if not sta_if.isconnected():
        sta_if.active(True)
        sta_if.connect('SSID', 'PASSWD')
        while not sta_if.isconnected():
            pass
        print('net cfg:',sta_if.ifconfig())
        time.sleep(10)
        print(ntptime.settime())

def check_if_time_is_to_turn_on_heater(t):
    print(t)
    print("LED: " + str(led.value()))
    if t[3]>=23 or t[3]<7 and led.value() == OFF:
    # if t[3] % 2 == 0:
        write_to_file("ON", utime.localtime())
        led.off()
        print("ON")
        utime.localtime()
    elif t[3]>=7 and t[3]<23 and led.value() == ON:
        led.on()
        print("OFF")
        utime.localtime()
        write_to_file("OFF", utime.localtime())


def update_time_from_server():
    if utime.localtime()[4]%15==0 and not is_updated:
        try:
            ntptime.settime()
        except:
            print(EOFError)
        isupdated = True
        time.sleep(0.5)
        print("time update...")
    elif utime.localtime()[3]%15 != 0 and is_updated:
        isupdated = False

#######################################################################
#application
connect_on_network()
time.sleep(2)


while True:
    check_if_time_is_to_turn_on_heater(utime.localtime())
    time.sleep(1)
    
    if not sta_if.isconnected():
        connect_on_network()
    
    update_time_from_server()

P.S. You have probably seen that I have used variable name LED, the reason for that is the pin is tied to on board LED so I can track the status visually.

Once again,
Thanks

L

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: Strange behavior of time on ESP8266

Post by kevinkk525 » Sun Nov 04, 2018 3:19 pm

Looks good to me. Good that it worked tonight.
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Strange behavior of time on ESP8266

Post by pythoncoder » Mon Nov 05, 2018 6:29 am

You can't argue with code that works ;)

But the (correct) logic looks wrong: you have defined OFF = 1 and ON = 0. So when you issue led.off() the Pin instance produces a value of 0 which you define as ON. This had me foxed for a moment.

You might like to look at the Signal class which is intended to deal with cases like this.

Another small point: when using files it's worth using a Python context manager. This ensures that the file is closed even if the program fails or you interrupt it with ctrl-c while the file is open.

Code: Select all

def write_to_file(status, time):
    with open('log.txt','w') as file:
        file.write(status)
        file.write(str(time))
But this is nitpicking. Well done for getting it to work :D
Peter Hinch
Index to my micropython libraries.

lazarvgd
Posts: 39
Joined: Sun May 20, 2018 8:57 am

Re: Strange behavior of time on ESP8266

Post by lazarvgd » Mon Nov 05, 2018 7:36 am

pythoncoder wrote:
Mon Nov 05, 2018 6:29 am
You can't argue with code that works ;)

But the (correct) logic looks wrong: you have defined OFF = 1 and ON = 0. So when you issue led.off() the Pin instance produces a value of 0 which you define as ON. This had me foxed for a moment.

You might like to look at the Signal class which is intended to deal with cases like this.

Another small point: when using files it's worth using a Python context manager. This ensures that the file is closed even if the program fails or you interrupt it with ctrl-c while the file is open.

Code: Select all

def write_to_file(status, time):
    with open('log.txt','w') as file:
        file.write(status)
        file.write(str(time))
But this is nitpicking. Well done for getting it to work :D
Thanks :)
I really like when someone comment my code, in that way I learn a bunch of things that I did not think of :)

The logic is inverted because pin 4 on board is tied to on board led and works with inverted logic.

The another thing that I found in writing a file is that I cannot append to the file, only the last line is there, the old lines are deleted, I have googled but did not find anything related to micropython. Does anybody know how doing that?

Also, my board was frozen last night, and did not trigger the heater, then I remembered watchdog timer. The documentation http://docs.micropython.org/en/v1.9.3/e ... e.WDT.html is pretty short and without examples. Does anybody know how to restart the board if something crashes or the board freezes?

Thanks for the tip for opening and closing the file, this is good hint. :)

User avatar
pythoncoder
Posts: 5956
Joined: Fri Jul 18, 2014 8:01 am
Location: UK
Contact:

Re: Strange behavior of time on ESP8266

Post by pythoncoder » Mon Nov 05, 2018 7:59 am

An alternative to using the Signal class for inverted logic would be to write led.value(OFF) which would look clearer (to my eyes at least).

Appending to a file: see this link. The 'w' mode always overwrites a file, 'a' appends.

As far as I know the ESP8266 does not have a hardware WDT. The doc you cite says "Availability of this class: pyboard, WiPy.". If you have the hardware skills it would be possible to implement a hardware WDT which issues a reset pulse to the board if not repeatedly triggered by a pulse generated in code.

But my first approach would be to try to determine what happens when it "freezes". Has it completely crashed or is the code getting stuck somewhere? Perhaps you need more extensive logging - you only need to look at the very end of your long log file to figure out how it died. Did it lose WiFi connectivity and fail to recover, for example? Have you tested by deliberately downing the WiFi or the internet connection?

Making these things work is easy, Making them resilient can be more of a challenge...
Peter Hinch
Index to my micropython libraries.

kevinkk525
Posts: 969
Joined: Sat Feb 03, 2018 7:02 pm

Re: Strange behavior of time on ESP8266

Post by kevinkk525 » Mon Nov 05, 2018 9:10 am

Considering that my boards freeze about once a day and get reset by my software watchdog using interrupts, it is quite possible that some vendor code of the esp8266 is the reason for the freeze as I could not find any other reason when I tried to debug that.
Of course you could try to debug your code even more but considering that your code is extremely short and the only socket operation is the time update, I'm not convinced it's really a code problem. But make sure that the board really is frozen and can't be interrupted by CTRL-C.

Here's a wdt class without uasyncio and all other stuff specific to my smarthome framework, just call wdt.feed() every time you check the time:

Code: Select all

import gc
import machine
from sys import platform
gc.collect()


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()
        try:
            with open("watchdog.txt", "r") as f:
                if f.read() == "True":
                    print("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:
            print("Error saving to file: {!s}".format(e))
            if use_rtc_memory and platform == "esp8266":
                rtc = machine.RTC()
                if rtc.memory() == b"WDT reset":
                    print("Reset reason: Watchdog")
                rtc.memory(b"")

    def _wdt(self, t):
        self._counter += self._timeout
        if self._counter >= self._timeout * 10:
            try:
                with open("watchdog.txt", "w") as f:
                    f.write("True")
            except Exception as e:
                print("Error saving to file: {!s}".format(e))
                if 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()
Use it like:

Code: Select all

wdt=WDT()
while True:
    time.sleep(1)
    check_time()
    wdt.feed()
Kevin Köck
Micropython Smarthome Firmware (with Home-Assistant integration): https://github.com/kevinkk525/pysmartnode

lazarvgd
Posts: 39
Joined: Sun May 20, 2018 8:57 am

Re: Strange behavior of time on ESP8266

Post by lazarvgd » Mon Nov 05, 2018 10:49 am

@pythoncoder You are right, clean code must follow the best standard. I wrote this code while I was commuting, I did not thought about that. Another thing regarding the board, it is hard to debug, because I do not have debugger and have to log files. Since I am Android and iOS developer, I used to use debugger. Will try to log more and find what is going on. Thanks for hint to append the file, I have missed it, sometimes the hardest thing is to google it in right way. It is easier for me to add arduino board as WTD instead of implementing it to ESP board.

@kevinkk525 Thanks for wtd class, I assume that I need just tu push the file to the board, and make the call in my code?
What I am assuming that the problem is regarding my ntptime class, since I am running local NTP server on my raspberry pi, in case internet is dead.

Unfortunately, it is hard to make code to be reliant and I do not like defensive programming, but with open source projects it is almost always like that. But, hey I am happy that people were willing to share knowledge and effort with the rest of th world :)

P.S. I will add WTD class, also will debug little bit more my code and observe how it behaves.
Must solve this problem, winter is coming :D
Thanks for your time and effort, I really appreciate that.
Will update you.

Post Reply