🎁📬❄️📦 Holiday Shipping Deadlines are approaching! International customers and domestic ground - get your orders in 12/9/2020 📦❄️📬🎁
0

Matrix Portal M4 crashes with 3231 Real time clock
Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.

Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Wed Nov 18, 2020 9:46 am

Have the Adabox 016 running the latest circuit_python. Replaced the temperature with time and installed the DS3231 Real Time Clock on Stemma QT. Always boots on startup but halts a few hours later with the "reload" message.

Code added to code.py

import adafruit_ds3231
...
myI2C = busio.I2C(board.SCL, board.SDA)
rtc = adafruit_ds3231.DS3231(myI2C)
network.get_local_time()
rtc.datetime = time.struct_time(time.localtime(time.time()))
...
in while True: loop
# every hour
network.get_local_time()
rtc.datetime = time.struct_time(time.localtime(time.time()))

# every minute
t = rtc.datetime
gfx.display_time(t.tm_hour, t.tm_min) # displays time instead of temperature on matrix

When the ds3231 code is removed and just use system time it appears to work fine. Any ideas?

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by mikeysklar on Thu Nov 19, 2020 6:36 pm

@petitnoel,

Just looking at your code and noticing that you are also doing a network time call every hour. Does it make a difference if you omit the network.get_local_time()? Also what is the specific reload message?

https://github.com/adafruit/Adafruit_Ci ... pletest.py

mikeysklar
 
Posts: 2398
Joined: Mon Aug 01, 2016 8:10 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Thu Nov 19, 2020 7:02 pm

I set the get_network_time to 10 hours and it still froze eventually. I don't know what the error message may be as I am running the M4 stand alone. Today it ran from 7 AM to 3:37 PM and froze with no more scrolling. If I can get this not to freeze, I can run just on the real-time-clock for days, but that too freezes.

I find now that even without the real time clock connected the system runs for from 5 to 25 hours and freezes. I will have to connect a system with MU on it to let it run until it creates an error message.

Here is my entire code for weather_display.py (code.py)

# Matrix Weather display
# For Metro M4 Airlift with RGB Matrix shield, 64 x 32 RGB LED Matrix display

"""
This example queries the Open Weather Maps site API to find out the current
weather for your location... and display it on a screen!
if you can find something that spits out JSON data, we can display it
"""
import time
import board
import microcontroller
import busio
# removed real time clock to see if that stops the system
# import adafruit_ds3231
# from digitalio import DigitalInOut, Direction, Pull
from adafruit_matrixportal.network import Network
from adafruit_matrixportal.matrix import Matrix
import openweather_graphics # pylint: disable=wrong-import-position

# Get wifi details and more from a secrets.py file
try:
from secrets import secrets
except ImportError:
print("WiFi secrets are kept in secrets.py, please add them there!")
raise

# removed button selection for metric/imperial units, set to imperial

UNITS = "imperial"
# removed rtc since it crashes trying to update something
# myI2C = busio.I2C(board.SCL, board.SDA)
# rtc = adafruit_ds3231.DS3231(myI2C)
# Use cityname, country code where countrycode is ISO3166 format.
# E.g. "New York, US" or "London, GB"
LOCATION = "Harris, US"
print("Getting weather for {}".format(LOCATION))
# Set up from where we'll be fetching data
DATA_SOURCE = (
"http://api.openweathermap.org/data/2.5/weather?q=" + LOCATION + "&units=" + UNITS
)
DATA_SOURCE += "&appid=" + secrets["openweather_token"]
# You'll need to get a token from openweather.org, looks like 'b6907d289e10d714a6e88b30761fae22'
# it goes in your secrets.py file on a line such as:
# 'openweather_token' : 'your_big_humongous_gigantor_token',
DATA_LOCATION = []
SCROLL_HOLD_TIME = 0 # set this to hold each line before finishing scroll

# --- Display setup ---
matrix = Matrix()
network = Network(status_neopixel=board.NEOPIXEL, debug=True)
if UNITS == "imperial" or UNITS == "metric":
gfx = openweather_graphics.OpenWeather_Graphics(
matrix.display, am_pm=True, units=UNITS
)

print("gfx loaded")
time_refresh = None
localtime_refresh = None
weather_refresh = None
network.get_local_time() # set the local time for now
# rtc.datetime = time.struct_time(time.localtime(time.time()))
while True:
# update the real time clock every 1 hours (and on first run)
# real time clock not used
if (not localtime_refresh) or (time.monotonic() - localtime_refresh) > 3600:
try:
print("Getting time from internet!")
network.get_local_time()
# removed real time clock setting for test (stops every few hours)
# rtc.datetime = time.struct_time(time.localtime(time.time()))
localtime_refresh = time.monotonic()
except RuntimeError as e:
print("Some error occured, retrying! -", e)
continue

# only query the weather every 10 minutes (and on first run)
if (not weather_refresh) or (time.monotonic() - weather_refresh) > 600:
try:
value = network.fetch_data(DATA_SOURCE, json_path=(DATA_LOCATION,))
print("Response is", value)
gfx.display_weather(value)
weather_refresh = time.monotonic()
except RuntimeError as e:
print("Some error occured, retrying! -", e)
continue

if (not time_refresh) or (time.monotonic() - time_refresh) >= 60:
try:
# every minute update the minute display
# t = rtc.datetime
t = time.struct_time(time.localtime(time.time()))
gfx.display_time(t.tm_hour, t.tm_min)
time_refresh = time.monotonic()
except RuntimeError as e:
print("Some error occured, retrying! -", e)
continue

gfx.scroll_next_label()
# Pause between labels
time.sleep(SCROLL_HOLD_TIME)

And here is the code for openweather_graphics.py

import time
import displayio
from adafruit_display_text.label import Label
from adafruit_bitmap_font import bitmap_font

TEMP_COLOR = 0xFFA800
MAIN_COLOR = 0x9000FF # weather condition
DESCRIPTION_COLOR = 0x00D3FF
CITY_COLOR = 0x9000FF
HUMIDITY_COLOR = 0x0000AA
WIND_COLOR = 0xCCCCCC

cwd = ("/" + __file__).rsplit("/", 1)[
0
] # the current working directory (where this file is)

small_font = cwd + "/fonts/Arial-12.bdf"
medium_font = cwd + "/fonts/Arial-14.bdf"

icon_spritesheet = cwd + "/weather-icons.bmp"
icon_width = 16
icon_height = 16
scrolling_text_height = 24
scroll_delay = 0.03


class OpenWeather_Graphics(displayio.Group):
def __init__(
self,
display,
*,
am_pm=True,
units="imperial"
):
super().__init__(max_size=3)
self.am_pm = am_pm
if units == "metric":
self.celsius = True
self.meters_speed = True
else:
self.celsius = False
self.meters_speed = False
self.display = display

splash = displayio.Group(max_size=1)
background = displayio.OnDiskBitmap(open("loading.bmp", "rb"))
bg_sprite = displayio.TileGrid(
background,
pixel_shader=displayio.ColorConverter(),
)
splash.append(bg_sprite)
display.show(splash)

self.root_group = displayio.Group(max_size=15)
self.root_group.append(self)
self._icon_group = displayio.Group(max_size=1)
self.append(self._icon_group)
self._text_group = displayio.Group(max_size=5)
self.append(self._text_group)
self._scrolling_group = displayio.Group(max_size=1)
self.append(self._scrolling_group)

# The label index we're currently scrolling
self._current_label = None

# Load the icon sprite sheet
icons = displayio.OnDiskBitmap(open(icon_spritesheet, "rb"))
self._icon_sprite = displayio.TileGrid(
icons,
pixel_shader=displayio.ColorConverter(),
width=1,
height=1,
tile_width=icon_width,
tile_height=icon_height,
default_tile=0,
x=0,
y=0,
)
self.set_icon(None)
self._scrolling_texts = []

self.small_font = bitmap_font.load_font(small_font)
self.medium_font = bitmap_font.load_font(medium_font)
glyphs = b"0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ-,.: "
self.small_font.load_glyphs(glyphs)
self.medium_font.load_glyphs(glyphs)
self.medium_font.load_glyphs(("°",)) # a non-ascii character we need for sure

self.city_text = None
self.time_text = Label(self.small_font, max_glyphs=6)
self.time_text.x = 20
self.time_text.y = 7
self.time_text.color = TEMP_COLOR
self.time_text.text = "00:00" # put something here so there is something to pop off
self._text_group.append(self.time_text)

self.temp_text = Label(self.small_font, max_glyphs=6)
self.temp_text.color = TEMP_COLOR
self._scrolling_texts.append(self.temp_text)

self.description_text = Label(self.small_font, max_glyphs=60)
self.description_text.color = DESCRIPTION_COLOR
self._scrolling_texts.append(self.description_text)

self.humidity_text = Label(self.small_font, max_glyphs=14)
self.humidity_text.color = TEMP_COLOR #
self._scrolling_texts.append(self.humidity_text)

self.wind_text = Label(self.small_font, max_glyphs=10)
self.wind_text.color = WIND_COLOR
self._scrolling_texts.append(self.wind_text)

self.winddir_text = Label(self.small_font, max_glyphs=10)
self.winddir_text.color = WIND_COLOR
self._scrolling_texts.append(self.winddir_text)

def display_weather(self, weather):
# set the icon
self.set_icon(weather["weather"][0]["icon"])

city_name = weather["name"] + ", " + weather["sys"]["country"]
print(city_name)
if not self.city_text:
self.city_text = Label(self.small_font, text="Harris, MN")
self.city_text.color = CITY_COLOR
self._scrolling_texts.append(self.city_text)

temperature = weather["main"]["temp"]
print(temperature)
if self.celsius:
self.temp_text.text = "%d°C" % temperature
else:
self.temp_text.text = "%d°F" % temperature

description = weather["weather"][0]["description"]
description = description[0].upper() + description[1:]
print(description)
self.description_text.text = description
# "thunderstorm with heavy drizzle"

humidity = weather["main"]["humidity"]
dewpoint = int(temperature) - (100 - int(humidity))*0.36
self.humidity_text.text = "%d°F dewpoint" % dewpoint

wind = weather["wind"]["speed"]
print(wind)
if self.meters_speed:
self.wind_text.text = "%d m/s" % wind
else:
self.wind_text.text = "%d mph" % wind

winddir = weather["wind"]["deg"]
print(winddir)
arr=["N","NNE","NE","ENE","E","ESE", "SE", "SSE","S","SSW","SW","WSW","W","WNW","NW","NNW"]
wdir = int(winddir/22.5 + 0.5)
self.winddir_text.text = arr[(wdir%16)]

self.display.show(self.root_group)


def display_time(self,hrs,mins):
self.time_text = Label(self.small_font, max_glyphs=6)
self.time_text.x = 20
self.time_text.y = 7
self.time_text.color = TEMP_COLOR
time_txt = "{hr:.2d}:{min:02d}"
if (hrs > 12):
hrs = hrs - 12
self.time_text.text = time_txt.format(hr=hrs,min=mins)
self._text_group.pop()
self._text_group.append(self.time_text)
self.display.show(self.root_group)

def set_icon(self, icon_name):
"""Use icon_name to get the position of the sprite and update
the current icon.

:param icon_name: The icon name returned by openweathermap

Format is always 2 numbers followed by 'd' or 'n' as the 3rd character
"""

icon_map = ("01", "02", "03", "04", "09", "10", "11", "13", "50")

print("Set icon to", icon_name)
if self._icon_group:
self._icon_group.pop()
if icon_name is not None:
row = None
for index, icon in enumerate(icon_map):
if icon == icon_name[0:2]:
row = index
break
column = 0
if icon_name[2] == "n":
column = 1
if row is not None:
self._icon_sprite[0] = (row * 2) + column
self._icon_group.append(self._icon_sprite)

def scroll_next_label(self):
# Start by scrolling current label off if not set to None
if self._current_label is not None and self._scrolling_group:
current_text = self._scrolling_texts[self._current_label]
text_width = current_text.bounding_box[2]
for _ in range(text_width + 1):
self._scrolling_group.x = self._scrolling_group.x - 1
time.sleep(scroll_delay)

if self._current_label is not None:
self._current_label += 1
if self._current_label is None or self._current_label >= len(
self._scrolling_texts
):
self._current_label = 0

# Setup the scrolling group by removing any existing
if self._scrolling_group:
self._scrolling_group.pop()
# Then add the current label
current_text = self._scrolling_texts[self._current_label]
self._scrolling_group.append(current_text)

# Set the position of the group to just off screen and centered vertically for lower half
self._scrolling_group.x = self.display.width
self._scrolling_group.y = 23

# Run a loop until the label is offscreen again and leave function
for _ in range(self.display.width):
self._scrolling_group.x = self._scrolling_group.x - 1
time.sleep(scroll_delay)
# By blocking other code we will never leave the label half way scrolled

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by mikeysklar on Fri Nov 20, 2020 4:24 pm

@petitnoel,

Please use the CODE tag button for pasting in your example.

Can you try just running the real-time-clock portion of the code with no other code or connected hardware?

mikeysklar
 
Posts: 2398
Joined: Mon Aug 01, 2016 8:10 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Fri Nov 20, 2020 6:54 pm

Sorry I didn't put the code in correctly. The Matrix M4 continues to halt after a few hours with the Real-Time-Clock connected and software disabled. So for now I have disconnected the STEMMA QT connector for the Real Time Clock. and let the system run for a while. Since the halts may take hours I will just keep an eye on it over the weekend and see what happens.

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by mikeysklar on Mon Nov 23, 2020 4:34 pm

@petitnoel,

How did your weekend testing go?

I take it this DS3231 RTC you are using is not ours? We sell FeatherWings and breakout boards for it, but not one with a STEMMA connector. Which one are you using?

I'm not sure if it makes a difference, but I think it might be worth trying our ds3231_simpletest.py and see if that code hangs without any other code specifically time.localtime you are pulling off the network.

https://learn.adafruit.com/adafruit-ds3 ... cuitpython
Code: Select all | TOGGLE FULL SIZE
# Simple demo of reading and writing the time for the DS3231 real-time clock.
# Change the if False to if True below to set the time, otherwise it will just
# print the current date and time every second.  Notice also comments to adjust
# for working with hardware vs. software I2C.

import time
import board

# For hardware I2C (M0 boards) use this line:
import busio as io

# Or for software I2C (ESP8266) use this line instead:
# import bitbangio as io

import adafruit_ds3231


i2c = io.I2C(board.SCL, board.SDA)  # Change to the appropriate I2C clock & data
# pins here!

# Create the RTC instance:
rtc = adafruit_ds3231.DS3231(i2c)

# Lookup table for names of days (nicer printing).
days = ("Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday")


# pylint: disable-msg=using-constant-test
if False:  # change to True if you want to set the time!
    #                     year, mon, date, hour, min, sec, wday, yday, isdst
    t = time.struct_time((2017, 10, 29, 15, 14, 15, 0, -1, -1))
    # you must set year, mon, date, hour, min, sec and weekday
    # yearday is not supported, isdst can be set but we don't do anything with it at this time
    print("Setting time to:", t)  # uncomment for debugging
    rtc.datetime = t
    print()
# pylint: enable-msg=using-constant-test

# Main loop:
while True:
    t = rtc.datetime
    # print(t)     # uncomment for debugging
    print(
        "The date is {} {}/{}/{}".format(
            days[int(t.tm_wday)], t.tm_mday, t.tm_mon, t.tm_year
        )
    )
    print("The time is {}:{:02}:{:02}".format(t.tm_hour, t.tm_min, t.tm_sec))
    time.sleep(1)  # wait a second

mikeysklar
 
Posts: 2398
Joined: Mon Aug 01, 2016 8:10 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Sun Nov 29, 2020 11:57 am

My challenge continues. I have installed the Adafruit DS3231 Real Time Clock on the Matrix Portal M4 and restored the code that uses the real time clock for a time display. It runs for about 3 hours and then halts with the "reload" image on the LED. The NeoPixel is flashing: red, green, purple, 6 green, 8 blue and repeat.

On startup, I get (some shortened):

Auto-reload is on: Simply save files over USB to run them or enter REPL to disable.
code.py output:
Getting weather for Harris, US
Set icon to None
gfx load
Getting time from internet!
Connecting to AP CrownLinkModem
Getting time for timezone America/Chicago
Socket missing recv-into. Using more memory to be compatible
Time request: https?//io.adafruit.com/......
Time reply: 2020-11-29 09:42:52.145 334 7 -0600 CST
Free mem: 17760
Retrieving data...Socket missing recv-into. Using more memory to be compatible
Headers:.....
Reply is OK!
{weather data...}
Response is {weather data...}
Set icon to 04d
Harris, US
34.92
Overcast Clouds
6.93
310

... and then the LED matrix runs correctly for about 3 - 5 hours ...

thanks,
Attachments
weather _display.py.with_rtc.10.txt
used for code.py
(3.54 KiB) Not downloaded yet
openweather_graphics.py.with_rtc_and_dp.8.10.txt
(8.33 KiB) Not downloaded yet

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Sun Nov 29, 2020 12:46 pm

I just updated Circuit Python to M4-en_US-6.0.0 and the libraries to 6.x-mpy-20201126 versions. I will see if that helps.

Thanks,

Noel Petit

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Tue Dec 01, 2020 11:29 am

After updating to the latest Circuit Python for the M4 and libraries (11/26/20) it ran for about 24 hours then halted with the "press control D to reload" message on the LED and same Neo message on the M4. It is within 10 feet of the Wifi access point so that shouldn't be the problem. There is still some code that is crashing when using the real time clock with the M4 Circuit Python.

Thanks,
Noel Petit
Augsburg University

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by mikeysklar on Tue Dec 01, 2020 7:27 pm

Noel,

What code was run for 24 hours before it halted?

I assume this did not have any real time clock calls in it and the RTC was disconnected?

When the code hung did you get an indication of where the code bailed out? Was it on "get_network_time()" or something else?

mikeysklar
 
Posts: 2398
Joined: Mon Aug 01, 2016 8:10 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Tue Dec 01, 2020 8:42 pm

I did not get any indication as I don't have a computer connected to "serial". I just restarted and commented out the block of code that calls for an update of the network time every hour or so. I will run it and see if that is where it hangs. I have the real time clock connected via Stemma QT and it was set earlier so it should run on its own and not be too far off as the DS3231 should only lose a second every 23 days or a minute every 5 years.

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by mikeysklar on Wed Dec 02, 2020 3:05 pm

Noel,

Thank you for repeating "the hang test" experiment.

Please try to minimize changes so maybe a protocol such as:

1) Connected to serial to look for console output indicators

2) Remove RTC Stemma device from connected chain (repeat experiment)

3) Remove all get_network_time() references (repeat experiment)

mikeysklar
 
Posts: 2398
Joined: Mon Aug 01, 2016 8:10 pm

Re: Matrix Portal M4 crashes with 3231 Real time clock

by petitnoel on Wed Dec 02, 2020 3:09 pm

Thanks, for the first test I did #3 -- remove reference to get network time. So far it has worked for 24 hours.

petitnoel
 
Posts: 14
Joined: Fri Jul 11, 2014 12:26 pm

Please be positive and constructive with your questions and comments.