When the PyGamer's power is turned on, the code.py module first imports all the required libraries. That includes the thermal_cam_converters and index_to_rgb helper files that we'll review later.

import time
import board
import busio
import gc
import ulab
import displayio
import neopixel
from analogio import AnalogIn
from digitalio import DigitalInOut
from simpleio import map_range, tone
from adafruit_display_text.label import Label
from adafruit_bitmap_font import bitmap_font
from adafruit_display_shapes.rect import Rect
import adafruit_amg88xx
from gamepadshift import GamePadShift
from index_to_rgb.iron_spectrum import index_to_rgb
from thermal_cam_converters import celsius_to_fahrenheit, fahrenheit_to_celsius
from thermal_cam_config import ALARM_F, MIN_RANGE_F, MAX_RANGE_F, SELFIE

After importing libraries, the display and default font are instantiated, the speaker is enabled, and the on-board NeoPixels are defined.

If the PyGamer's joystick is present, the has_joystick flag is set to True. If not, then the host device is probably a PyBadge or EdgeBadge. This allows the code to work for those devices in addition to the PyGamer, interpreting the Badge D-Pad buttons like the Gamer's joystick.

# Instantiate display, joystick, speaker, and neopixels
display = board.DISPLAY
# Load the text font from the fonts folder
font_0 = bitmap_font.load_font("/fonts/OpenSans-9.bdf")

if hasattr(board, "JOYSTICK_X"):
    has_joystick = True  # PyGamer with joystick
    joystick_x = AnalogIn(board.JOYSTICK_X)
    joystick_y = AnalogIn(board.JOYSTICK_Y)
else:
    has_joystick = False  # PyBadge with buttons

speaker_enable = DigitalInOut(board.SPEAKER_ENABLE)
speaker_enable.switch_to_output(value=True)

pixels = neopixel.NeoPixel(board.NEOPIXEL, 5, pixel_order=neopixel.GRB)
pixels.brightness = 0.25  # Set NeoPixel brightness
pixels.fill(0x000000)  # Clear all NeoPixels

The PyGamer and PyBadge control buttons are connected to a hardware shift register chip that is controlled by the GamePadShift class. This section of the code defines each button's bit position within the shift register. The local GamePadShift class, panel, will be used to read the buttons in the primary process loop and setup helper.

# Define and instantiate front panel buttons
BUTTON_LEFT = 0b10000000
BUTTON_UP = 0b01000000
BUTTON_DOWN = 0b00100000
BUTTON_RIGHT = 0b00010000
BUTTON_SELECT = 0b00001000
BUTTON_START = 0b00000100
BUTTON_A = 0b00000010
BUTTON_B = 0b00000001

panel = GamePadShift(
    DigitalInOut(board.BUTTON_CLOCK),
    DigitalInOut(board.BUTTON_OUT),
    DigitalInOut(board.BUTTON_LATCH),
)

Now it's time to connect to and instantiate the AMG8833 thermal camera FeatherWing using the I2C bus connection. The I2C serial bus speed is increased from the default 100K to 400K bits per second to improve data acquisition speed and ultimately the display frame rate.

This section of the code will also work if the AMG8833 thermal camera STEMMA breakout is used in place of the FeatherWing version. STEMMA cable length may impact sensor performance, so if you encounter issues with the breakout version, try reducing the I2C bus speed to the default 100K bits per second rate.

# Establish I2C interface for the AMG8833 Thermal Camera
i2c = busio.I2C(board.SCL, board.SDA, frequency=400000)
amg8833 = adafruit_amg88xx.AMG88XX(i2c)

Next, the welcome graphics screen, thermal_cam_splash.bmp is displayed. The size of the image is scaled to fit the size of the PyGamer's display.

# Display splash graphics
splash = displayio.Group(scale=display.width // 160)
bitmap = displayio.OnDiskBitmap("/thermal_cam_splash.bmp")
splash.append(displayio.TileGrid(bitmap, pixel_shader=bitmap.pixel_shader))
board.DISPLAY.show(splash)
time.sleep(0.1)  # Allow the splash to display

Finally, the ulab (micro lab) arrays needed to hold the normalized 8x8 sensor index and the transformed 15x15 display grid index are defined. In addition, an array to hold histogram statistical data is established.

An array defined for ulab use is an narray type; a format different than other CircuitPython arrays. The special narray array type (named after a close cousin, the numpy array) is designed to support rapid array calculation and transformation.

# Set up ulab arrays
n = 8  # Thermal sensor grid axis size; AMG8833 sensor is 8x8
sensor_data = ulab.numpy.array(range(n * n)).reshape((n, n))  # Color index narray
grid_data = ulab.numpy.zeros(((2 * n) - 1, (2 * n) - 1))  # 15x15 color index narray
histogram = ulab.numpy.zeros((2 * n) - 1)  # Histogram accumulation narray

A series of numerical constants are needed to set boundaries and limits for thermal camera calculations. We'll talk about those next.

This guide was first published on Jun 09, 2021. It was last updated on 2021-06-09 17:11:13 -0400.

This page (Import and Initialize) was last updated on Apr 23, 2022.

Text editor powered by tinymce.