Created
March 21, 2021 18:42
-
-
Save recantha/a4a893e1e5b7ec48d234f2409b1996b8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# AMG8833 thermal camera on an ILI9341 320x240 screen | |
# Michael Horne, based on Jan Goolsbey's code for Adafruit | |
# https://learn.adafruit.com/pygamer-thermal-camera-amg8833?view=all | |
import time | |
import board | |
import displayio | |
import busio | |
from simpleio import map_range | |
from adafruit_display_text.label import Label | |
from adafruit_display_shapes.rect import Rect | |
import adafruit_amg88xx | |
import adafruit_ili9341 | |
# Helper functions | |
def celsius_to_fahrenheit(deg_c=None): # convert C to F; round to 1 degree C | |
return round(((9 / 5) * deg_c) + 32) | |
def fahrenheit_to_celsius(deg_f=None): # convert F to C; round to 1 degree F | |
return round((deg_f - 32) * (5 / 9)) | |
def element_grid(col0, row0): # Determine display coordinates for column, row | |
x = int(ELEMENT_SIZE * col0 + 30) # x coord + margin | |
y = int(ELEMENT_SIZE * row0 + 1) # y coord + margin | |
return x, y # Return display coordinates | |
def update_image_frame(): # Get camera data and display | |
minimum = MAX_SENSOR_C # Set minimum to sensor's maximum C value | |
maximum = MIN_SENSOR_C # Set maximum to sensor's minimum C value | |
sum_bucket = 0 # Clear bucket for building average value | |
for row1 in range(0, 8): # Parse camera data list and update display | |
for col1 in range(0, 8): | |
value = map_range(image[7 - row1][7 - col1], | |
MIN_SENSOR_C, MAX_SENSOR_C, | |
MIN_SENSOR_C, MAX_SENSOR_C) | |
color_index = int(map_range(value, MIN_RANGE_C, MAX_RANGE_C, 0, 7)) | |
image_group[((row1 * 8) + col1) + 1].fill = element_color[color_index] | |
sum_bucket = sum_bucket + value # Calculate sum for average | |
minimum = min(value, minimum) | |
maximum = max(value, maximum) | |
return minimum, maximum, sum_bucket | |
# Establish I2C interface for the AMG8833 Thermal Camera | |
i2c_scl = board.GP1 | |
i2c_sda = board.GP0 | |
i2c = busio.I2C(i2c_scl, i2c_sda) | |
amg8833 = adafruit_amg88xx.AMG88XX(i2c) | |
# The image sensor's design-limited temperature range | |
MIN_SENSOR_C = 0 | |
MAX_SENSOR_C = 80 | |
MIN_SENSOR_F = celsius_to_fahrenheit(MIN_SENSOR_C) | |
MAX_SENSOR_F = celsius_to_fahrenheit(MAX_SENSOR_C) | |
# Convert default alarm and min/max range values from config file | |
MIN_RANGE_F = 60 | |
MAX_RANGE_F = 120 | |
MIN_RANGE_C = fahrenheit_to_celsius(MIN_RANGE_F) | |
MAX_RANGE_C = fahrenheit_to_celsius(MAX_RANGE_F) | |
# The board's integral display size (as informed by product page adafru.it/1770) | |
WIDTH = 320 | |
HEIGHT = 240 | |
ELEMENT_SIZE = WIDTH // 10 # Size of element_grid blocks in pixels | |
# Define colors | |
BLACK = 0x000000 | |
RED = 0xFF0000 | |
ORANGE = 0xFF8811 | |
YELLOW = 0xFFFF00 | |
GREEN = 0x00FF00 | |
CYAN = 0x00FFFF | |
BLUE = 0x0000FF | |
VIOLET = 0x9900FF | |
WHITE = 0xFFFFFF | |
GRAY = 0x444455 | |
# Block colors for the thermal image grid | |
element_color = [GRAY, BLUE, GREEN, YELLOW, ORANGE, RED, VIOLET, WHITE] | |
# Tell displayio to clean up after any previous usage | |
displayio.release_displays() | |
# Define ILI9341 screen as an SPI-interfaced display | |
tft_cs = board.GP17 | |
tft_dc = board.GP21 | |
tft_res = board.GP20 | |
spi_mosi = board.GP19 | |
spi_clk = board.GP18 | |
spi_miso = board.GP16 | |
spi = busio.SPI(clock=spi_clk, MOSI=spi_mosi, MISO=spi_miso) | |
display_bus = displayio.FourWire(spi, command=tft_dc, chip_select=tft_cs) | |
display = adafruit_ili9341.ILI9341(display_bus, width=WIDTH, height=HEIGHT) | |
# Initially, just show a bright green background to prove the display is working | |
splash = displayio.Group(max_size=10) | |
display.show(splash) | |
color_bitmap = displayio.Bitmap(320, 240, 1) | |
color_palette = displayio.Palette(1) | |
color_palette[0] = 0x00FF00 # Bright Green | |
bg_sprite = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0) | |
splash.append(bg_sprite) | |
# Draw a smaller inner rectangle | |
inner_bitmap = displayio.Bitmap(280, 200, 1) | |
inner_palette = displayio.Palette(1) | |
inner_palette[0] = 0xAA0088 # Purple | |
inner_sprite = displayio.TileGrid(inner_bitmap, pixel_shader=inner_palette, x=20, y=20) | |
splash.append(inner_sprite) | |
# Wait so it doesn't immediately get overwritten | |
time.sleep(1) | |
# Define the group for the thermal display | |
image_group = displayio.Group(max_size=77) | |
display.show(image_group) | |
# Create a black background color fill layer; image_group[0] | |
color_bitmap = displayio.Bitmap(WIDTH, HEIGHT, 1) | |
color_palette = displayio.Palette(1) | |
color_palette[0] = BLACK | |
background = displayio.TileGrid(color_bitmap, pixel_shader=color_palette, x=0, y=0) | |
image_group.append(background) | |
# Define the foundational thermal image element layers; image_group[1:64] | |
# image_group[#]=(row * 8) + column | |
for row in range(0, 8): | |
for col in range(0, 8): | |
pos_x, pos_y = element_grid(col, row) | |
# outline is normally None and stroke is 0 | |
element = Rect(x=pos_x, y=pos_y, width=ELEMENT_SIZE, height=ELEMENT_SIZE, fill=None, outline=None, stroke=0) | |
image_group.append(element) | |
# Main loop | |
while True: | |
image = amg8833.pixels # Get camera data list | |
v_min, v_max, v_sum = update_image_frame() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment