OK, here's our first example which uses button presses to wake from sleep.

The MagTag has four buttons on the front. They are wired to the MagTag in such a way that their associated pins read as follows:

  • HIGH = True = not pressed
  • LOW = False = pressed

So we want to configure a pin alarm that triggers when its value is False so it goes off when a button is pressed.

We can actually have more than one alarm. So one idea would be to wake up when any of the buttons are pressed. However, for technical reasons, we are limited to a maximum of two LOW pin alarms. So we just pick any two buttons - like the two on the left.

These are the lines of code that set up the pin alarms:

# set up pin alarms
buttons = (board.BUTTON_A, board.BUTTON_B)  # pick any two
pin_alarms = [alarm.pin.PinAlarm(pin=pin, value=False, pull=True) for pin in buttons]

Sleep Memory

The MagTag's EPD (eInk Display) will always be showing one of two indications. If the current indication is what you want, there's no need to do anything. When a button is pressed and it wakes up, we want the MagTag to show the other indication. But when it wakes up, how does the MagTag know what the current indication is? It doesn't.

To get around this we can use the sleep_memory feature of the alarm module. This is general purpose memory that persists between sleep cycles. So we store a simple toggle value there that we change each time we wake up. Then we base the current indication on this toggle value.

That's what this line of code does:

# toggle saved state
alarm.sleep_memory[0] = not alarm.sleep_memory[0]

More information on sleep memory here:

Code

Here's the code. Download this and save it as code.py into your CIRCUITPY folder so it will run automatically. If you click  Download: Project Zip, you will get a zip file with the bitmap images used in the guide also.

# SPDX-FileCopyrightText: 2021 Carter Nelson for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import board
import alarm
import displayio

# get the display
epd = board.DISPLAY
epd.rotation = 270

# set up pin alarms
buttons = (board.BUTTON_A, board.BUTTON_B)  # pick any two
pin_alarms = [alarm.pin.PinAlarm(pin=pin, value=False, pull=True) for pin in buttons]

# toggle saved state
alarm.sleep_memory[0] = not alarm.sleep_memory[0]

# set bitmap
bmp_file = "/images/clean.bmp" if alarm.sleep_memory[0] else "/images/dirty.bmp"

# show bitmap

# CircuitPython 6 & 7 compatible
with open(bmp_file, "rb") as fp:
    bitmap = displayio.OnDiskBitmap(fp)
    tile_grid = displayio.TileGrid(
        bitmap, pixel_shader=getattr(bitmap, 'pixel_shader', displayio.ColorConverter())
    )
    group = displayio.Group()
    group.append(tile_grid)
    epd.root_group = group
    time.sleep(epd.time_to_refresh + 0.01)
    epd.refresh()
    while epd.busy:
        pass

# # CircuitPython 7+ compatible
# bitmap = displayio.OnDiskBitmap(bmp_file)
# tile_grid = displayio.TileGrid(bitmap, pixel_shader=bitmap.pixel_shader)
# group = displayio.Group()
# group.append(tile_grid)
# epd.root_group = group
# time.sleep(epd.time_to_refresh + 0.01)
# epd.refresh()
# while epd.busy:
#     pass

# go to sleep
alarm.exit_and_deep_sleep_until_alarms(*pin_alarms)

This guide was first published on Jan 12, 2021. It was last updated on Mar 28, 2024.

This page (Wake On Button) was last updated on Mar 28, 2024.

Text editor powered by tinymce.