peterhinch / micropython-samples

Assorted code ideas, unofficial MP FAQ, plus index to my other repositories.
MIT License
459 stars 92 forks source link

ESP32 Port (v1.12) ValueError when using ds3231.get_time() with flag set_rtc=True #14

Closed fantasticdonkey closed 4 years ago

fantasticdonkey commented 4 years ago

Hi all.

I encounter the following error with ds3231_port.py when using ds3231.get_time() with flag set_rtc=True.

Example:

import utime
from machine import I2C, Pin
from ds3231_port import DS3231

scl_pin = Pin(15, Pin.IN, Pin.PULL_UP)
sda_pin = Pin(4, Pin.IN, Pin.PULL_UP)
i2c = I2C(scl=scl_pin, sda=sda_pin, freq=400000)
ds3231 = DS3231(i2c)

Result:

At microprocessor power up, retrieve time from external battery-powered DS3231 RTC module and save to local RTC.

ds3231.get_time(set_rtc=True)
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "ds3231_port.py", line 47, in get_time
  File "ds3231_port.py", line 78, in convert
ValueError: requested length 8 but object has length 6
import os
os.uname()
(sysname='esp32', nodename='esp32', release='1.12.0', version='v1.12 on 2019-12-20', machine='ESP32 module with ESP32')

The fact that I'm using the latest MicroPython for ESP32 build (v1.12) may not be significant (if this worked before) since I encounter the identical issue on v1.11 (esp32-20190529-v1.11.bin).

In short, RTC.init() appears to require a 8-value tuple, while line 78 only provides 6. I am able to resolve the issue by changing line 75 in ds3231_port.py to add or sys.platform == 'esp32' which allows the time to be retrieved from the external DS3231 RTC and saved to local RTC using RTC.datetime() instead (same as for pyboard / esp8266).

This can be confirmed afterwards using utime.localtime().

Thanks!

peterhinch commented 4 years ago

Thank you for this.

When I wrote this, the official ESP32 port did not support the RTC (as can be seen in the code comments). The machine.RTC class was quite new, to the point where I avoided using it for Pyboard targets. As you're finding it looks like some or all of the platform detection code can come out. I will revisit this over the next week or two: it will need re-testing with each supported target.

fantasticdonkey commented 4 years ago

Thank you for this.

When I wrote this, the official ESP32 port did not support the RTC (as can be seen in the code comments). The machine.RTC class was quite new, to the point where I avoided using it for Pyboard targets. As you're finding it looks like some or all of the platform detection code can come out. I will revisit this over the next week or two: it will need re-testing with each supported target.

Thanks Peter. If you need any help in testing this against ESP8266 and ESP32 ports, please let me know.

peterhinch commented 4 years ago

Thank you for your offer - I'll take you up on this as I'm rather tied up at the moment. I've posted an update on branch ds3231_port and have tested this on a Pyboard 1.1 and Pyboard D. The test program has a minor fix for the latter. But if you could try the test program on ESP8266 and ESP32 and report back I'd be grateful.

There was evidently an issue with the machine class on ESP32 when I wrote this, however I have every confidence that it's long been fixed.

fantasticdonkey commented 4 years ago

ESP32 test (esp32-idf4-20191220-v1.12.bin)

MicroPython v1.12 on 2019-12-20; ESP32 module with ESP32
Type "help()" for more information.
>>> import utime
>>> import os
>>> from machine import I2C, Pin
>>> from ds3231_port import DS3231
>>>
>>> os.uname()
(sysname='esp32', nodename='esp32', release='1.12.0', version='v1.12 on 2019-12-20', machine='ESP32 module with ESP32')
>>> scl_pin = Pin(15, Pin.IN, Pin.PULL_UP)
>>> sda_pin = Pin(4, Pin.IN, Pin.PULL_UP)
>>> i2c = I2C(scl=scl_pin, sda=sda_pin, freq=400000)
>>> ds3231 = DS3231(i2c)
>>> utime.localtime()
(2000, 1, 1, 0, 2, 16, 5, 1)
>>> ds3231.get_time(set_rtc=True)
(2020, 1, 16, 20, 52, 32, 3, 0)
>>> utime.localtime()
(2020, 1, 16, 20, 52, 33, 3, 16)

ESP8266 test (esp8266-20191220-v1.12.bin)

MicroPython v1.12 on 2019-12-20; ESP module with ESP8266
Type "help()" for more information.
>>> import utime
>>> import os
>>> from machine import I2C, Pin
>>> from ds3231_port import DS3231
>>>
>>> os.uname()
(sysname='esp8266', nodename='esp8266', release='2.2.0-dev(9422289)', version='v1.12 on 2019-12-20', machine='ESP module with ESP8266')
>>> scl_pin = Pin(5, Pin.IN, Pin.PULL_UP)
>>> sda_pin = Pin(4, Pin.IN, Pin.PULL_UP)
>>> i2c = I2C(scl=scl_pin, sda=sda_pin, freq=400000)
>>> ds3231 = DS3231(i2c)
>>> utime.localtime()
(2000, 1, 1, 0, 0, 8, 5, 1)
>>> ds3231.get_time(set_rtc=True)
(2020, 1, 16, 20, 45, 50, 3, 0)
>>> utime.localtime()
(2020, 1, 16, 20, 45, 51, 3, 16)

So in short, it appears to be working correctly on both builds. Thanks for your help.

peterhinch commented 4 years ago

In the course of my Pyboard testing I used a board with firmware dating from May 2019: it failed because machine had no RTC. So the need for Pyboard-specific hacks has gone away relatively recently.

Thank you for testing, I'll merge and push this morning.