Skip to content

Commit 56c9b77

Browse files
committed
adding battery monitor project code
Adding code and assets for the Feather battery monitor project guide
1 parent 99e514d commit 56c9b77

File tree

4 files changed

+19715
-0
lines changed

4 files changed

+19715
-0
lines changed
31.7 KB
Binary file not shown.

Feather_TFT_Battery_Monitor/code.py

Lines changed: 168 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,168 @@
1+
# SPDX-FileCopyrightText: 2024 Liz Clark for Adafruit Industries
2+
# SPDX-License-Identifier: MIT
3+
4+
import ssl
5+
import os
6+
import socketpool
7+
import wifi
8+
import board
9+
import digitalio
10+
import displayio
11+
import vectorio
12+
from adafruit_bitmap_font import bitmap_font
13+
from adafruit_display_text import bitmap_label
14+
import adafruit_imageload
15+
from adafruit_io.adafruit_io import IO_HTTP, AdafruitIO_RequestError
16+
import adafruit_max1704x
17+
import adafruit_requests
18+
from simpleio import map_range
19+
from adafruit_ticks import ticks_ms, ticks_add, ticks_diff
20+
21+
# states
22+
send_io = True
23+
bat_clock = ticks_ms()
24+
bat_timer = 60 * 1000
25+
first_run = True
26+
# settings.toml imports
27+
aio_username = os.getenv('AIO_USERNAME')
28+
aio_key = os.getenv('AIO_KEY')
29+
# connect to wifi
30+
wifi.radio.connect(os.getenv('CIRCUITPY_WIFI_SSID'), os.getenv('CIRCUITPY_WIFI_PASSWORD'))
31+
pool = socketpool.SocketPool(wifi.radio)
32+
requests = adafruit_requests.Session(pool, ssl.create_default_context())
33+
io = IO_HTTP(aio_username, aio_key, requests)
34+
try:
35+
# get feed
36+
battery_feed = io.get_feed("battery-monitor")
37+
except AdafruitIO_RequestError:
38+
# if no feed exists, create one
39+
battery_feed = io.create_new_feed("battery-monitor")
40+
# default group
41+
group = displayio.Group()
42+
# text only group
43+
textOnly_group = displayio.Group()
44+
board.DISPLAY.root_group = group
45+
# palette for vector graphics
46+
palette = displayio.Palette(5)
47+
palette[0] = 0xFF0000
48+
palette[1] = 0xFFFF00
49+
palette[2] = 0x00FF00
50+
palette[3] = 0x0000FF
51+
palette[4] = 0x000000
52+
# battery rectangle
53+
rect = vectorio.Rectangle(pixel_shader=palette, width=72, height=45, x=140, y=70, color_index = 0)
54+
group.append(rect)
55+
text_bg = vectorio.Rectangle(pixel_shader=palette, width=115, height=70,
56+
x=120, y=60, color_index = 4)
57+
# io indicator circle
58+
circle = vectorio.Circle(pixel_shader=palette, radius=8, x=10, y=10, color_index=3)
59+
textOnly_group.append(circle)
60+
# graphics bitmap
61+
bitmap, palette_bit = adafruit_imageload.load(
62+
"/bat_bg.bmp",
63+
bitmap=displayio.Bitmap,
64+
palette=displayio.Palette,
65+
)
66+
# purple is made transparent
67+
palette_bit.make_transparent(0)
68+
tile_grid = displayio.TileGrid(bitmap, pixel_shader=palette_bit)
69+
group.append(tile_grid)
70+
group.append(circle)
71+
# font for graphics
72+
sm_file = "/roundedHeavy-26.bdf"
73+
sm_font = bitmap_font.load_font(sm_file)
74+
# font for text only
75+
lg_file = "/roundedHeavy-46.bdf"
76+
lg_font = bitmap_font.load_font(lg_file)
77+
volt_text = bitmap_label.Label(sm_font, text=" V", x=150, y=33)
78+
group.append(volt_text)
79+
big_volt_text = bitmap_label.Label(lg_font, text=" V")
80+
big_volt_text.anchor_point = (0.5, 0.0)
81+
big_volt_text.anchored_position = (board.DISPLAY.width / 2, 0)
82+
textOnly_group.append(big_volt_text)
83+
percent_text = bitmap_label.Label(sm_font, text=" %", x=150, y=90)
84+
big_percent_text = bitmap_label.Label(lg_font, text=" %", x=board.DISPLAY.width//2, y=90)
85+
big_percent_text.anchor_point = (0.5, 1.0)
86+
big_percent_text.anchored_position = (board.DISPLAY.width / 2, board.DISPLAY.height - 15)
87+
textOnly_group.append(big_percent_text)
88+
89+
# buttons
90+
button0 = digitalio.DigitalInOut(board.D0)
91+
button0.direction = digitalio.Direction.INPUT
92+
button0.pull = digitalio.Pull.UP
93+
button0_state = False
94+
button1 = digitalio.DigitalInOut(board.D1)
95+
button1.direction = digitalio.Direction.INPUT
96+
button1.pull = digitalio.Pull.DOWN
97+
button1_state = False
98+
button2 = digitalio.DigitalInOut(board.D2)
99+
button2.direction = digitalio.Direction.INPUT
100+
button2.pull = digitalio.Pull.DOWN
101+
button2_state = False
102+
103+
# MAX17048 instantiation
104+
monitor = adafruit_max1704x.MAX17048(board.I2C())
105+
monitor.activity_threshold = 0.01
106+
107+
# colors for battery graphic
108+
def get_color(value):
109+
if value < 30:
110+
return 0
111+
elif 30 <= value <= 75:
112+
return 1
113+
else:
114+
return 2
115+
116+
while True:
117+
# reset button state on release
118+
if button0.value and button0_state:
119+
button0_state = False
120+
if not button1.value and button1_state:
121+
button1_state = False
122+
if not button2.value and button2_state:
123+
button2_state = False
124+
# toggle sending to adafruit io
125+
if not button0.value and not button0_state:
126+
button0_state = True
127+
send_io = not send_io
128+
if send_io:
129+
circle.color_index = 3
130+
else:
131+
circle.color_index = 4
132+
# toggle graphics or text only
133+
if button1.value and not button1_state:
134+
button1_state = True
135+
if board.DISPLAY.root_group == group:
136+
board.DISPLAY.root_group = textOnly_group
137+
else:
138+
board.DISPLAY.root_group = group
139+
# toggle battery graphic or % text
140+
if button2.value and not button2_state:
141+
button2_state = True
142+
if len(group) > 4:
143+
group.pop()
144+
group.pop()
145+
else:
146+
group.append(text_bg)
147+
group.append(percent_text)
148+
# read MAX17048 every 60 seconds
149+
if first_run or ticks_diff(ticks_ms(), bat_clock) >= bat_timer:
150+
first_run = False
151+
battery_volts = monitor.cell_voltage
152+
battery_percent = monitor.cell_percent
153+
print(f"Battery voltage: {battery_volts:.2f} Volts")
154+
print(f"Battery percentage: {battery_percent:.1f} %")
155+
print()
156+
battery_display = map_range(battery_percent, 0, 100, 0, 72)
157+
battery_x = map_range(battery_percent, 0, 100, 210, 140)
158+
# update rectangle to reflect battery charge
159+
rect.width = int(battery_display)
160+
rect.x = int(battery_x)
161+
rect.color_index = get_color(battery_percent)
162+
volt_text.text = f"{battery_volts:.2f} V"
163+
percent_text.text = f"{battery_percent:.1f} %"
164+
big_volt_text.text = f"{battery_volts:.2f} V"
165+
big_percent_text.text = f"{battery_percent:.1f} %"
166+
if battery_percent >= 100 and send_io:
167+
io.send_data(battery_feed["key"], battery_percent)
168+
bat_clock = ticks_add(bat_clock, bat_timer)

0 commit comments

Comments
 (0)