adding battery monitor project code
Adding code and assets for the Feather battery monitor project guide
This commit is contained in:
parent
99e514db0f
commit
56c9b775fd
4 changed files with 19715 additions and 0 deletions
BIN
Feather_TFT_Battery_Monitor/bat_bg.bmp
Normal file
BIN
Feather_TFT_Battery_Monitor/bat_bg.bmp
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 32 KiB |
168
Feather_TFT_Battery_Monitor/code.py
Normal file
168
Feather_TFT_Battery_Monitor/code.py
Normal file
|
|
@ -0,0 +1,168 @@
|
||||||
|
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
|
||||||
|
# SPDX-License-Identifier: MIT
|
||||||
|
|
||||||
|
import ssl
|
||||||
|
import os
|
||||||
|
import socketpool
|
||||||
|
import wifi
|
||||||
|
import board
|
||||||
|
import digitalio
|
||||||
|
import displayio
|
||||||
|
import vectorio
|
||||||
|
from adafruit_bitmap_font import bitmap_font
|
||||||
|
from adafruit_display_text import bitmap_label
|
||||||
|
import adafruit_imageload
|
||||||
|
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
|
||||||
|
import adafruit_max1704x
|
||||||
|
import adafruit_requests
|
||||||
|
from simpleio import map_range
|
||||||
|
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
|
||||||
|
|
||||||
|
# states
|
||||||
|
send_io = True
|
||||||
|
bat_clock = ticks_ms()
|
||||||
|
bat_timer = 60 * 1000
|
||||||
|
first_run = True
|
||||||
|
# settings.toml imports
|
||||||
|
aio_username = os.getenv('AIO_USERNAME')
|
||||||
|
aio_key = os.getenv('AIO_KEY')
|
||||||
|
# connect to wifi
|
||||||
|
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
|
||||||
|
pool = socketpool.SocketPool(wifi.radio)
|
||||||
|
requests = adafruit_requests.Session(pool, ssl.create_default_context())
|
||||||
|
io = IO_HTTP(aio_username, aio_key, requests)
|
||||||
|
try:
|
||||||
|
# get feed
|
||||||
|
battery_feed = io.get_feed("battery-monitor")
|
||||||
|
except AdafruitIO_RequestError:
|
||||||
|
# if no feed exists, create one
|
||||||
|
battery_feed = io.create_new_feed("battery-monitor")
|
||||||
|
# default group
|
||||||
|
group = displayio.Group()
|
||||||
|
# text only group
|
||||||
|
textOnly_group = displayio.Group()
|
||||||
|
board.DISPLAY.root_group = group
|
||||||
|
# palette for vector graphics
|
||||||
|
palette = displayio.Palette(5)
|
||||||
|
palette[0] = 0xFF0000
|
||||||
|
palette[1] = 0xFFFF00
|
||||||
|
palette[2] = 0x00FF00
|
||||||
|
palette[3] = 0x0000FF
|
||||||
|
palette[4] = 0x000000
|
||||||
|
# battery rectangle
|
||||||
|
rect = vectorio.Rectangle(pixel_shader=palette, width=72, height=45, x=140, y=70, color_index = 0)
|
||||||
|
group.append(rect)
|
||||||
|
text_bg = vectorio.Rectangle(pixel_shader=palette, width=115, height=70,
|
||||||
|
x=120, y=60, color_index = 4)
|
||||||
|
# io indicator circle
|
||||||
|
circle = vectorio.Circle(pixel_shader=palette, radius=8, x=10, y=10, color_index=3)
|
||||||
|
textOnly_group.append(circle)
|
||||||
|
# graphics bitmap
|
||||||
|
bitmap, palette_bit = adafruit_imageload.load(
|
||||||
|
"/bat_bg.bmp",
|
||||||
|
bitmap=displayio.Bitmap,
|
||||||
|
palette=displayio.Palette,
|
||||||
|
)
|
||||||
|
# purple is made transparent
|
||||||
|
palette_bit.make_transparent(0)
|
||||||
|
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette_bit)
|
||||||
|
group.append(tile_grid)
|
||||||
|
group.append(circle)
|
||||||
|
# font for graphics
|
||||||
|
sm_file = "/roundedHeavy-26.bdf"
|
||||||
|
sm_font = bitmap_font.load_font(sm_file)
|
||||||
|
# font for text only
|
||||||
|
lg_file = "/roundedHeavy-46.bdf"
|
||||||
|
lg_font = bitmap_font.load_font(lg_file)
|
||||||
|
volt_text = bitmap_label.Label(sm_font, text=" V", x=150, y=33)
|
||||||
|
group.append(volt_text)
|
||||||
|
big_volt_text = bitmap_label.Label(lg_font, text=" V")
|
||||||
|
big_volt_text.anchor_point = (0.5, 0.0)
|
||||||
|
big_volt_text.anchored_position = (board.DISPLAY.width / 2, 0)
|
||||||
|
textOnly_group.append(big_volt_text)
|
||||||
|
percent_text = bitmap_label.Label(sm_font, text=" %", x=150, y=90)
|
||||||
|
big_percent_text = bitmap_label.Label(lg_font, text=" %", x=board.DISPLAY.width//2, y=90)
|
||||||
|
big_percent_text.anchor_point = (0.5, 1.0)
|
||||||
|
big_percent_text.anchored_position = (board.DISPLAY.width / 2, board.DISPLAY.height - 15)
|
||||||
|
textOnly_group.append(big_percent_text)
|
||||||
|
|
||||||
|
# buttons
|
||||||
|
button0 = digitalio.DigitalInOut(board.D0)
|
||||||
|
button0.direction = digitalio.Direction.INPUT
|
||||||
|
button0.pull = digitalio.Pull.UP
|
||||||
|
button0_state = False
|
||||||
|
button1 = digitalio.DigitalInOut(board.D1)
|
||||||
|
button1.direction = digitalio.Direction.INPUT
|
||||||
|
button1.pull = digitalio.Pull.DOWN
|
||||||
|
button1_state = False
|
||||||
|
button2 = digitalio.DigitalInOut(board.D2)
|
||||||
|
button2.direction = digitalio.Direction.INPUT
|
||||||
|
button2.pull = digitalio.Pull.DOWN
|
||||||
|
button2_state = False
|
||||||
|
|
||||||
|
# MAX17048 instantiation
|
||||||
|
monitor = adafruit_max1704x.MAX17048(board.I2C())
|
||||||
|
monitor.activity_threshold = 0.01
|
||||||
|
|
||||||
|
# colors for battery graphic
|
||||||
|
def get_color(value):
|
||||||
|
if value < 30:
|
||||||
|
return 0
|
||||||
|
elif 30 <= value <= 75:
|
||||||
|
return 1
|
||||||
|
else:
|
||||||
|
return 2
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# reset button state on release
|
||||||
|
if button0.value and button0_state:
|
||||||
|
button0_state = False
|
||||||
|
if not button1.value and button1_state:
|
||||||
|
button1_state = False
|
||||||
|
if not button2.value and button2_state:
|
||||||
|
button2_state = False
|
||||||
|
# toggle sending to adafruit io
|
||||||
|
if not button0.value and not button0_state:
|
||||||
|
button0_state = True
|
||||||
|
send_io = not send_io
|
||||||
|
if send_io:
|
||||||
|
circle.color_index = 3
|
||||||
|
else:
|
||||||
|
circle.color_index = 4
|
||||||
|
# toggle graphics or text only
|
||||||
|
if button1.value and not button1_state:
|
||||||
|
button1_state = True
|
||||||
|
if board.DISPLAY.root_group == group:
|
||||||
|
board.DISPLAY.root_group = textOnly_group
|
||||||
|
else:
|
||||||
|
board.DISPLAY.root_group = group
|
||||||
|
# toggle battery graphic or % text
|
||||||
|
if button2.value and not button2_state:
|
||||||
|
button2_state = True
|
||||||
|
if len(group) > 4:
|
||||||
|
group.pop()
|
||||||
|
group.pop()
|
||||||
|
else:
|
||||||
|
group.append(text_bg)
|
||||||
|
group.append(percent_text)
|
||||||
|
# read MAX17048 every 60 seconds
|
||||||
|
if first_run or ticks_diff(ticks_ms(), bat_clock) >= bat_timer:
|
||||||
|
first_run = False
|
||||||
|
battery_volts = monitor.cell_voltage
|
||||||
|
battery_percent = monitor.cell_percent
|
||||||
|
print(f"Battery voltage: {battery_volts:.2f} Volts")
|
||||||
|
print(f"Battery percentage: {battery_percent:.1f} %")
|
||||||
|
print()
|
||||||
|
battery_display = map_range(battery_percent, 0, 100, 0, 72)
|
||||||
|
battery_x = map_range(battery_percent, 0, 100, 210, 140)
|
||||||
|
# update rectangle to reflect battery charge
|
||||||
|
rect.width = int(battery_display)
|
||||||
|
rect.x = int(battery_x)
|
||||||
|
rect.color_index = get_color(battery_percent)
|
||||||
|
volt_text.text = f"{battery_volts:.2f} V"
|
||||||
|
percent_text.text = f"{battery_percent:.1f} %"
|
||||||
|
big_volt_text.text = f"{battery_volts:.2f} V"
|
||||||
|
big_percent_text.text = f"{battery_percent:.1f} %"
|
||||||
|
if battery_percent >= 100 and send_io:
|
||||||
|
io.send_data(battery_feed["key"], battery_percent)
|
||||||
|
bat_clock = ticks_add(bat_clock, bat_timer)
|
||||||
7673
Feather_TFT_Battery_Monitor/roundedHeavy-26.bdf
Normal file
7673
Feather_TFT_Battery_Monitor/roundedHeavy-26.bdf
Normal file
File diff suppressed because it is too large
Load diff
11874
Feather_TFT_Battery_Monitor/roundedHeavy-46.bdf
Normal file
11874
Feather_TFT_Battery_Monitor/roundedHeavy-46.bdf
Normal file
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue