Text Editor
Adafruit recommends using the Mu editor for editing your CircuitPython code. You can get more info in this guide.
Alternatively, you can use any text editor that saves simple text files.
Download the Project Bundle
Your project will use a specific set of CircuitPython libraries and the code.py file. To get everything you need, click on the Download Project Bundle link below, and uncompress the .zip file.
Drag the contents of the uncompressed bundle directory onto your board's CIRCUITPY drive, replacing any existing files or directories with the same names, and adding any new ones that are necessary.
# SPDX-FileCopyrightText: Copyright (c) 2024 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT
"""
USB C PD power supply w HUSB238
pick voltages and then set them, measures high side current with INA219
"""
import time
import board
import keypad
import displayio
import terminalio
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
import adafruit_husb238
from adafruit_ina219 import INA219
i2c = board.I2C()
tft_d0_button = keypad.Keys((board.D0,), value_when_pressed=False, pull=True)
tft_buttons = keypad.Keys((board.D1, board.D2), value_when_pressed=True, pull=True)
# Initialize INA219 current sensor
ina219 = INA219(i2c)
TXTCOL_VOLT = 0x8f00cd
TXTCOL_CURR = 0xb30090
TXTCOL_DIM = 0xCD8F00
TXTCOL_HEAD = 0xCD8F00
TXTCOL_BTN = 0xa0a0a0
BGCOL = 0x220030
display = board.DISPLAY
group = displayio.Group()
background_rect = Rect(0, 0, display.width, display.height, fill=BGCOL)
group.append(background_rect)
warning_text = "plug in USB C PD cable, press reset"
FONT = terminalio.FONT
display.root_group = group
RUNNING = None
PLUGGED = None
# Initialize HUSB238 PD dummy
try:
pd = adafruit_husb238.Adafruit_HUSB238(i2c)
RUNNING = True
PLUGGED = True
except ValueError:
print("plug in a USB C PD cable, then press reset")
RUNNING = False
PLUGGED = False
warning_label = label.Label(
FONT, text=warning_text, color=0xdd0000,
scale=1, anchor_point=(0,0),
anchored_position=(20, 10)
)
group.append(warning_label)
#stop the code here
while not RUNNING:
pass
while RUNNING:
voltages = pd.available_voltages
print("The following voltages are available:")
for i, volts in enumerate(voltages):
print(f"{volts}V")
v = 0
if pd.attached:
pd.voltage = voltages[0]
print(f"Voltage is set to {pd.voltage}V/{pd.current}A")
display = board.DISPLAY
group = displayio.Group()
background_rect = Rect(0, 0, display.width, display.height, fill=BGCOL)
group.append(background_rect)
vert_bar = Rect(40, 0, 3, display.height, fill=0x000000)
group.append(vert_bar)
FONT = terminalio.FONT
header_label = label.Label(
FONT, text="Power Deliverer", color=TXTCOL_HEAD,
scale=2, x=50, y=8
)
group.append(header_label)
voltage_label = label.Label(
FONT, text=str(voltages[0])+"V", color=TXTCOL_VOLT,
scale=5, anchor_point=(0,0),
anchored_position=(50, 20)
)
group.append(voltage_label)
current_label = label.Label(
FONT, text="0mA", color=TXTCOL_CURR,
scale=5, anchor_point=(0,0),
anchored_position=(50, 80)
)
group.append(current_label)
go_label = label.Label(FONT, text="set", color=TXTCOL_BTN, scale=2, x=1, y=6)
group.append(go_label)
up_label = label.Label(FONT, text="+v", color=TXTCOL_BTN, scale=2, x=1, y=display.height//2-2)
group.append(up_label)
down_label = label.Label(FONT, text="-v", color=TXTCOL_BTN, scale=2, x=1, y=display.height-12)
group.append(down_label)
display.root_group = group
while True:
tft_d0_button_event = tft_d0_button.events.get()
if tft_d0_button_event and tft_d0_button_event.pressed:
try:
print(f"Setting to {voltages[v]}V!")
pd.voltage = voltages[v]
voltage_label.text=str(voltages[v]) + "V"
voltage_label.color=TXTCOL_VOLT
print(f"It is set to {pd.voltage}V/{pd.current}A")
print()
PLUGGED=True
except OSError:
print(warning_text)
voltage_label.text="replug"
current_label.text="USB C"
PLUGGED=False
if PLUGGED:
tft_buttons_event = tft_buttons.events.get()
if tft_buttons_event and tft_buttons_event.pressed:
if tft_buttons_event.key_number == 0:
v = (v + 1) % len(voltages) # maybe have this stop at max
voltage_label.color=TXTCOL_DIM
voltage_label.text="["+str(voltages[v]) + "V]"
print(f"Voltage will be set to {voltages[v]}V")
if tft_buttons_event.key_number == 1:
v = (v - 1) % len(voltages) # maybe have this stop at min
voltage_label.color=TXTCOL_DIM
voltage_label.text="["+str(voltages[v]) + "V]"
print(f"Voltage will be set to {voltages[v]}V")
current = ina219.current # current in mA
# power = ina219.power # power in watts
current_label.text= str(abs(int(current))) + "mA"
if ina219.overflow:
print("Internal Math Overflow Detected!")
print("")
time.sleep(0.2)
How it Works
Library Imports
First, we import all the necessary libraries -- these allow us to interact with the current sensor and the Power Delivery dummy, as well as display text and shapes on the TFT screen.
import time import board import keypad import displayio import terminalio from adafruit_display_text import label from adafruit_display_shapes.rect import Rect import adafruit_husb238 from adafruit_ina219 import INA219
i2c = board.I2C() tft_d0_button = keypad.Keys((board.D0,), value_when_pressed=False, pull=True) tft_buttons = keypad.Keys((board.D1, board.D2), value_when_pressed=True, pull=True)
ina219 = INA219(i2c)
TXTCOL_VOLT = 0x8f00cd TXTCOL_CURR = 0xb30090 TXTCOL_DIM = 0xCD8F00 TXTCOL_HEAD = 0xCD8F00 TXTCOL_BTN = 0xa0a0a0 BGCOL = 0x220030 display = board.DISPLAY group = displayio.Group() background_rect = Rect(0, 0, display.width, display.height, fill=BGCOL) group.append(background_rect)
Initialize HUSB238
Here, we set up the USB-C PD controller dummy so we can ask the PD supply for different voltages. If the USB-C PD supply is unplugged, it displays a warning message rather than crash the code.
try:
pd = adafruit_husb238.Adafruit_HUSB238(i2c)
RUNNING = True
PLUGGED = True
except ValueError:
print("plug in a USB C PD cable, then press reset")
RUNNING = False
PLUGGED = False
warning_label = label.Label(
FONT, text=warning_text, color=0xdd0000,
scale=1, anchor_point=(0,0),
anchored_position=(20, 10)
)
group.append(warning_label)
#stop the code here
Main Loop
In the main loop, the available voltages are displayed and button presses handled -- these change the voltage settings and update the display with current readings.
while True:
tft_d0_button_event = tft_d0_button.events.get()
if tft_d0_button_event and tft_d0_button_event.pressed:
try:
print(f"Setting to {voltages[v]}V!")
pd.voltage = voltages[v]
voltage_label.text=str(voltages[v]) + "V"
voltage_label.color=TXTCOL_VOLT
print(f"It is set to {pd.voltage}V/{pd.current}A")
PLUGGED=True
except OSError:
print(warning_text)
voltage_label.text="replug"
current_label.text="USB C"
PLUGGED=False
if PLUGGED:
tft_buttons_event = tft_buttons.events.get()
if tft_buttons_event and tft_buttons_event.pressed:
if tft_buttons_event.key_number == 0:
v = (v + 1) % len(voltages)
voltage_label.color=TXTCOL_DIM
voltage_label.text="["+str(voltages[v]) + "V]"
print(f"Voltage will be set to {voltages[v]}V")
if tft_buttons_event.key_number == 1:
v = (v - 1) % len(voltages)
voltage_label.color=TXTCOL_DIM
voltage_label.text="["+str(voltages[v]) + "V]"
print(f"Voltage will be set to {voltages[v]}V")
current = ina219.current
current_label.text= str(abs(int(current))) + "mA"
if ina219.overflow:
print("Internal Math Overflow Detected!")
time.sleep(0.2)
Page last edited January 22, 2025
Text editor powered by tinymce.