Skip to content

ESP32-S2: Crash into the HardFault_Handler #6793

@ctmorrison

Description

@ctmorrison

CircuitPython version

Adafruit CircuitPython 7.3.2 on 2022-07-20; Adafruit QT Py ESP32S2 with ESP32S2

Code/REPL

# Garage Vehicle Space Detection

import alarm
import time
import board
import adafruit_vl53l1x
import neopixel
from digitalio import DigitalInOut, Direction, Pull
from analogio import AnalogIn

# This is the latching relay
unoccupied = DigitalInOut(board.A0)
unoccupied.direction = Direction.OUTPUT
occupied = DigitalInOut(board.A1)
occupied.direction = Direction.OUTPUT

# This is the button used to put the device into setup mode
setup = DigitalInOut(board.A2)
setup.direction = Direction.INPUT
setup.pull = Pull.DOWN
# read value with setup.value, knowing it has a pullup
# We'll use this to know the state of the relay
occupiedStatus = DigitalInOut(board.SDA)
occupiedStatus.direction = Direction.INPUT

# This is the potentiometer input
pot = AnalogIn(board.A3)
tripPoint = pot.value * 400 / 65536

# Length of time in seconds to sleep between checks
sleepPeriod = 15
# Length of time in seconds to turn on neopixel to indicate if space is occupied or not
spaceStatusPeriod = 0.5
# Amount of time to energize the relay (in seconds)
energizeTime = 0.25

# We're using the Stemma interface to connect to the sensor
i2c = board.STEMMA_I2C()

# This code works with the VL53L1CX ToF sensor
vl53 = adafruit_vl53l1x.VL53L1X(i2c)

# The onboard neopixel will be used for visual signalling
pixels = neopixel.NeoPixel(board.NEOPIXEL, 1, brightness=0.1)

# OPTIONAL: can set non-default values
vl53.distance_mode = 2
vl53.timing_budget = 100

print("Garage Space Detection")
print("Version 20220812.1")
print("--------------------")
model_id, module_type, mask_rev = vl53.model_info
print("Model ID: 0x{:0X}".format(model_id))
print("Module Type: 0x{:0X}".format(module_type))
print("Mask Revision: 0x{:0X}".format(mask_rev))
print("Distance Mode: ", end="")
if vl53.distance_mode == 1:
    print("SHORT")
elif vl53.distance_mode == 2:
    print("LONG")
else:
    print("UNKNOWN")
print("Timing Budget: {}".format(vl53.timing_budget))
print("Sleep period: {}".format(sleepPeriod))
print("Trip point: {}".format(tripPoint))
print("Space status period: {}".format(spaceStatusPeriod))
print("--------------------")
vl53.start_ranging()

# Attempt to read a distance
while vl53.data_ready is not True:
    print("not ready")
    time.sleep(0.5)
print("Sensor is ready to read")

# Let's get a distance
distance = vl53.distance
while distance is None:
    distance = vl53.distance
    pixels.fill((0, 0, 255))
    time.sleep(0.1)

while setup.value is True:
    # the Setup button is being pressed and we need to set the  occupied distance
    # the occupied distance should be just above the floor
    # this assumes the space is EMPTY!
    print("In setup mode")
    tripPoint = pot.value * 400 / 65536
    # check to see if sensed distance is
    print("Floor: {}".format(distance))
    print("tripPoint: {}".format(tripPoint))
    if tripPoint > distance:
        print("tripPoint is beyond floor - adjust to lower value")
        pixels.fill((255, 0, 0))
    else:
        print("tripPoint is above floor - make sure it's close to floor")
        pixels.fill((0, 255, 0))
    time.sleep(1)
print("Setup finished")

try:
    pixels.fill((0, 0, 0))
except RuntimeError:
    print("10***************************************************pixels.fill failed")

# Read the distance to the nearest object
distance = vl53.distance

# test for no distance read to avoid error
while distance is None:
    distance = vl53.distance
    pixels.fill((0, 0, 255))
    time.sleep(0.1)
try:
    pixels.fill((0, 0, 0))
except RuntimeError:
    print("20***************************************************pixels.fill failed")


# here's where we check to see if there's a vehicle detected above the threshold
if distance < tripPoint:
    print("Distance: {} cm -> vehicle sensed".format(distance))
    try:
        pixels.fill((255, 0, 0))
    except RuntimeError:
        print("30***************************************************pixels.fill failed")
    if occupiedStatus.value is False:
        # we only energize if we need to -- it was previously unoccupied
        occupied.value = True
        time.sleep(energizeTime)
        occupied.value = False
    time.sleep(spaceStatusPeriod)
else:
    print("Distance: {} cm -> no vehicle sensed".format(distance))
    try:
        pixels.fill((0, 255, 0))
    except RuntimeError:
        print("40***************************************************pixels.fill failed")
    if occupiedStatus.value is True:
        # we only energize if we need to -- it was previously occupied
        unoccupied.value = True
        time.sleep(energizeTime)
        occupied.value = False
    time.sleep(spaceStatusPeriod)
vl53.clear_interrupt()

# Set up the sleep period for the amount of time specified in sleepPeriod
time_alarm = alarm.time.TimeAlarm(monotonic_time=time.monotonic() + sleepPeriod)
# Exit the program and then deep sleep until the alarm wakes usage
print("Going into Deep Sleep")
alarm.exit_and_deep_sleep_until_alarms(time_alarm)
# Does not get here...program starts at the beginning after sleep

Behavior

This does not always happen. Sometimes, it runs just fine.
Here's the error I got:
You are in safe mode because:
CircuitPython core code crashed hard. Whoops!
Crash into the HardFault_Handler.
Please file an issue with the contents of your CIRCUITPY drive at
https://github.com/adafruit/circuitpython/issues

Description

No response

Additional information

The only error I seem to get often, but not always is when the program executes a call to pixels.fill((255, 0, 0)) or some other color combination

Metadata

Metadata

Assignees

Type

No type
No fields configured for issues without a type.

Projects

No projects

Milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions