Maker.io main logo

IoT Battery Monitor

2024-12-03 | By Adafruit Industries

License: See Original Project 3D Printing ESP32 Adafruit Feather

Courtesy of Adafruit

Guide by Ruiz Brothers and 1 other contributor

Overview

 

Build an internet connected battery charger and monitor with ‎Feather ESP32-S2 Reverse TFT, CircuitPython, and Adafruit IO.‎

The on-board MAX17048 LiPoly battery monitor chip reads the ‎batteries voltage and is displayed on the Feather ESP32's built-in ‎color TFT display. Use the on-board button to cycle between icons ‎and text.‎

The project uses Adafruit IO actions to receive an SMS text or email ‎when the battery is fully charged.‎

monitor_1

Enclosure

The 3D printed enclosure snap fits together and features a tray for ‎holding a 1200mAh battery. The enclosure can swivel forwards and ‎back allowing for an adjustable viewing angle.‎

Use a JST extension cable to easily swap out batteries without ‎having to unplug from the Feather.‎

enclosure_2

Parts

Battery Options

  • ‎1 x 100mAh Lithium-Ion Polymer Battery - 3.7v‎

  • ‎1 x 150mAh Lithium-Ion Polymer Battery - 3.7v‎

  • ‎1 x 350mAh Lithium-Ion Polymer Battery - 3.7v‎

  • ‎1 x 400mAh Lithium-Ion Polymer Battery - 3.7v

  • ‎1 x 420mAh Lithium-Ion Polymer Battery - 3.7v‎

  • ‎1 x 500mAh Lithium-Ion Polymer Battery - 3.7v

  • ‎1 x 1200mAh Lithium-Ion Polymer Battery - 3.7v‎

  • ‎1 x 2000mAh Lithium-Ion Polymer Battery - 3.7v

‎ ‎Hardware

The following hardware is necessary for the case assembly.‎

  • ‎4x M2.5 x 6mm long machine screws‎

  • ‎2x M2 x 6mm long FF standoffs‎

Text editor powered by tinymce.‎

CAD Files

‎3D Printed Parts‎

STL files for 3D printing are oriented to print "as-is" on FDM style ‎machines. Parts are designed to 3D print without any support ‎material using PLA filament. Original design source may be ‎downloaded using the links below.‎

cad_3

Download STLs.zip

Download CAD source

CAD Assembly

The Feather ESP32-S2 Reverse TFT Feather board is secured to the ‎enclosure's back cover using both M2 and M2.5 fasteners. The back ‎cover snap fits onto the front cover. The front cover is secured to the ‎battery tray using M2.5 fastener. ‎

3d_printing_CAD

Build Volume

The parts require a 3D printer with a minimum build volume.‎

  • ‎68mm (X) x 62mm (Y) x 20mm (Z)‎

build_4

Design Source Files

The project assembly was designed in Fusion 360. This can be ‎downloaded in different formats like STEP, STL and more.‎

Electronic components like Adafruit boards, displays, connectors ‎and more can be downloaded from the Adafruit CAD parts GitHub ‎Repo.‎

design_5

Text editor powered by tinymce.‎

CircuitPython

CircuitPython is a derivative of MicroPython designed to simplify ‎experimentation and education on low-cost microcontrollers. It ‎makes it easier than ever to get prototyping by requiring no upfront ‎desktop software downloads. Simply copy and edit files on ‎the CIRCUITPY drive to iterate.‎

CircuitPython Quickstart

Follow this step-by-step to quickly get CircuitPython running on your ‎board.‎

Download the latest version of CircuitPython for this board via ‎circuitpython.org

Click the link above to download the latest CircuitPython UF2 file.

Save it wherever is convenient for you.‎

click_6

board_7

Plug your board into your computer, using a known-good data-sync ‎cable, directly, or via an adapter if needed.‎

Double-click the reset button (highlighted in red above), and you ‎will see the RGB status LED(s) turn green (highlighted in green ‎above). If you see red, try another port, or if you're using an adapter ‎or hub, try without the hub, or different adapter or hub.‎

For this board, tap reset and wait for the LED to turn purple, and as ‎soon as it turns purple, tap reset again. The second tap needs to ‎happen while the LED is still purple.‎

If double-clicking doesn't work the first time, try again. Sometimes it ‎can take a few tries to get the rhythm right!‎

A lot of people end up using charge-only USB cables and it is very ‎frustrating! Make sure you have a USB cable you know is good for ‎data sync.‎

You will see a new disk drive appear called FTHRS2BOOT.‎

‎ ‎Drag the adafruit_circuitpython_etc.uf2 file to FTHRS2BOOT.‎

drive_8

drive_9

The BOOT drive will disappear, and a new disk drive ‎called CIRCUITPY will appear.‎

That's it!‎

boot_10

Text editor powered by tinymce.‎

Create Your settings.toml File

CircuitPython works with WiFi-capable boards to enable you to ‎make projects that have network connectivity. This means working ‎with various passwords and API keys. As of CircuitPython 8, there is ‎support for a settings.toml file. This is a file that is stored on ‎your CIRCUITPY drive, that contains all of your secret network ‎information, such as your SSID, SSID password and any API keys for ‎IoT services. It is designed to separate your sensitive information ‎from your code.py file so you are able to share your code without ‎sharing your credentials.‎

CircuitPython previously used a secrets.py file for this purpose. ‎The settings.toml file is quite similar.‎

Your settings.toml file should be stored in the main directory of your ‎CIRCUITPY drive. It should not be in a folder.‎

CircuitPython settings.toml File

This section will provide a couple of examples of what ‎your settings.toml file should look like, specifically for CircuitPython ‎WiFi projects in general.‎

The most minimal settings.toml file must contain your WiFi SSID ‎and password, as that is the minimum required to connect to WiFi. ‎Copy this example, paste it into your settings.toml, and update:‎

  • your_wifi_ssid

  • your_wifi_password

Download File

Copy Code
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"

Many CircuitPython network-connected projects on the Adafruit ‎Learn System involve using Adafruit IO. For these projects, you ‎must also include your Adafruit IO username and key. Copy the ‎following example, paste it into your settings.toml file, and update:‎

  • your_wifi_ssid

  • your_wifi_password

  • your_aio_username

  • your_aio_key

Download File

Copy Code
CIRCUITPY_WIFI_SSID = "your_wifi_ssid"
CIRCUITPY_WIFI_PASSWORD = "your_wifi_password"
ADAFRUIT_AIO_USERNAME = "your_aio_username"
ADAFRUIT_AIO_KEY = "your_aio_key"

Some projects use different variable names for the entries in ‎the settings.toml file. For example, a project might ‎use ADAFRUIT_AIO_ID in the place of ADAFRUIT_AIO_USERNAME. If you run into ‎connectivity issues, one of the first things to check is that the ‎names in the settings.toml file match the names in the code.‎

Not every project uses the same variable name for each entry in the ‎settings.toml file! Always verify it matches the code.‎

settings.toml File Tips

Here is an example settings.toml file.‎

‎Download File

Copy Code
# Comments are supported
CIRCUITPY_WIFI_SSID = "guest wifi"
CIRCUITPY_WIFI_PASSWORD = "guessable"
CIRCUITPY_WEB_API_PORT = 80
CIRCUITPY_WEB_API_PASSWORD = "passw0rd"
test_variable = "this is a test"
thumbs_up = "\U0001f44d"

In a settings.toml file, it's important to keep these factors in mind:‎

  • Strings are wrapped in double quotes; ex: "your-string-here"

  • Integers are not quoted and may be written in decimal with ‎optional sign (+1, -1, 1000) or hexadecimal (0xabcd).‎

    • Floats, octal (0o567) and binary (0b11011) are not supported.‎

  • Use \u escapes for weird characters, \x and \ooo escapes are not ‎available in .toml files

    • Example: \U0001f44d for 👍 (thumbs up emoji) ‎and \u20ac for € (EUR sign)‎

  • Unicode emoji, and non-ASCII characters, stand for themselves ‎as long as you're careful to save in "UTF-8 without BOM" format‎‎

When your settings.toml file is ready, you can save it in your text ‎editor with the .toml extension.‎

settings_11

Accessing ‎Your settings.toml Information ‎in code.py

In your code.py file, you'll need to import the os library to access ‎the settings.toml file. Your settings are accessed with ‎the os.getenv() function. You'll pass your settings entry to the function ‎to import it into the code.py file.‎

Download File

Copy Code
import os

print(os.getenv("test_variable"))

codepy_12

In the upcoming CircuitPython WiFi examples, you'll see how ‎the settings.toml file is used for connecting to your SSID and ‎accessing your API keys.‎

Text editor powered by tinymce.‎

Code the Battery Monitor

Once you've finished setting up your Feather ESP32-S2 Reverse TFT ‎with CircuitPython, you can access the code and necessary libraries ‎by downloading the Project Bundle.‎

To do this, click on the Download Project Bundle button in the ‎window below. It will download to your computer as a zipped folder.‎

‎Download Project Bundle

Copy Code
# 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)

View on GitHub

Upload the Code and Libraries to the Feather ESP32-S2 Reverse TFT

After downloading the Project Bundle, plug your Feather ESP32-S2 ‎Reverse TFT into the computer's USB port with a known good USB ‎data+power cable. You should see a new flash drive appear in the ‎computer's File Explorer or Finder (depending on your operating ‎system) called CIRCUITPY. Unzip the folder and copy the following ‎items to the Feather's CIRCUITPY drive:‎

  • lib folder

  • code.py

  • bat_bg.bmp

  • roundedHeavy-26.bdf‎

  • roundedHeavy-46.bdf‎

Your Feather ESP32-S2 Reverse TFT CIRCUITPY drive should look like ‎this after copying the lib folder, .bdf font files, .bmp image file and ‎the code.py file.‎

file_13

Add Your settings.toml File

As of CircuitPython 8.0.0, there is support for Environment Variables. ‎Environment variables are stored in a settings.toml file. Similar ‎to secrets.py, the settings.toml file separates your sensitive ‎information from your main code.py file. Add your settings.toml file ‎as described in the Create Your settings.toml File page earlier in this ‎guide. You'll need to include your WiFi network SSID and password ‎as CIRCUITPY_WIFI_SSID and CIRCUITPY_WIFI_PASSWORD and your Adafruit IO ‎username and key as AIO_USERNAME and AIO_KEY.‎

‎Download File

Copy Code
CIRCUITPY_WIFI_SSID = "YOUR-SSID-HERE"
CIRCUITPY_WIFI_PASSWORD = "YOUR-SSID-PASSWORD-HERE"
AIO_USERNAME = "YOUR-AIO-USERNAME-HERE"
AIO_KEY = "YOUR-AIO-KEY-HERE"

How the CircuitPython Code Works

At the top of the code are some states that are used in the ‎loop. send_io enables sending the battery charging data to Adafruit ‎IO. bat_timer is the amount of time that the battery monitor is checked ‎and first_run and used to note that the code is running for the first ‎time in the loop.‎

‎Download File

Copy Code
# states
send_io = True
bat_clock = ticks_ms()
bat_timer = 60 * 1000
first_run = True

After the states are the settings.toml imports and WiFi and Adafruit ‎IO connections.‎

‎Download File

Copy Code
# 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")

If your WiFi access point name or password are incorrect, an error ‎will be generated.‎

Graphics

Next are the graphics. There are two display groups: one that ‎includes graphical elements and one that is text only. You can switch ‎between then in the loop depending on your preferences. ‎the bat_bg bitmap file is loaded using the adafruit_image library ‎and its background color is made transparent. vectorio shapes are ‎used to show the battery charge graphic and if you are sending data ‎to Adafruit IO.‎

‎Download File

Copy Code
# 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)

Then all of the text attributes are created. There are two font files, ‎one for a smaller font and one for a larger font. The larger font is used ‎for the text only graphics group.‎

‎Download File

Copy Code
# 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 and I2C

The three buttons on the Feather are setup as digitalio inputs. The ‎onboard MAX17048 is instantiated over I2C.‎

‎Download File

Copy Code
# 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

There is a simple function called get_color() that maps the charge ‎percentage of the battery to a color in a palette. This changes the ‎color of the battery from red to yellow to green as it charges up.‎

Download File

Copy Code
# colors for battery graphic
def get_color(value):
    if value < 30:
        return 0
    elif 30 <= value <= 75:
        return 1
    else:
        return 2

The Loop

In the loop, the buttons control the UI appearance and code ‎functionality. Button D0 toggles sending the battery info to Adafruit ‎IO. Button D1 changes between the text only display group and the ‎graphical group. Button D2 changes between representing the ‎battery charge percentage in text or via the battery graphic.‎

‎Download File

Copy Code
# 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)

Monitor the Battery

Every minute the MAX17048 is read to check on the battery voltage ‎and charge percentage. The graphics are updated with the data to ‎show on the TFT. If you chose to send the data to IO, the charge ‎percentage is sent to your feed when the battery is fully charged.‎

Download File

Copy Code
# 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)

Text editor powered by tinymce.‎

Adafruit IO Trigger

Create New Action

You can receive an email when the battery has been fully charged.‎

  • ‎ ‎Go to https://io.adafruit.com and click on Actions

  • Click the New Actions button.‎

  • Choose Yes, use Blockly!‎

trigger_14

Reactive Trigger Setup

  • Click on the Triggers menu, then click on Reactive

  • Drag the Reactive block and snap it to the Trigger section in ‎the Action Root block

  • Click on the Values menu, then click on the Feed block

  • Drag the Feed block and snap it to the Feed section in ‎the Reactive block. Then, select the battery-monitor feed from ‎the dropdown menu

  • Click on the Values menu, then click the A number, whole or ‎decimal block.‎

  • Drag the A number, whole or decimal block and snap it to ‎the Feed or Value section of the Reactive block. Then, type ‎‎"100" into the Feed or Value block.‎

  • Under the Operator section, select ">=" from the dropdown ‎menu.‎

setup_15

Action Setup

  • Click on Actions menu, then click on Email

  • Drag the Email block and snap it to the Action section in the ‎Action Root block.‎

  • Type your preferred text into the subject and body in ‎the Email block.‎

  • Click on Values menu, then click on a Feed block.‎

  • Drag the Feed block into the using section in the Email block. ‎Then, select battery-monitor from the dropdown menu

Click the Save button when you are finished. ‎

action_16

action_17

New Email

You'll now receive an email when the battery is fully charged.‎

email_18

Text editor powered by tinymce.‎

Assembly

Installing Feather

Get the 3D printed back cover, hardware screws, and Feather ready ‎to assemble.‎

Place the Feather over the back cover with the mounting holes lined ‎up and the TFT screen facing up.‎

Use the following hardware to secure the Feather to the back cover.‎

  • ‎2x M2 x 6mm long machine screws‎

  • ‎2x M2.5 x 6mm long machine screws‎

assembly_19

assembly_20

Secure Feather

Install and fasten the hardware screws to secure the Feather ESP32-‎S2 to the 3D printed back cover.‎

Ensure the Feather has been secured in the correct orientation.‎

secure_21

secure_22

Connect JST Extension

Plug in the 2-pin JST extension cable to the battery port on-board ‎the Feather ESP32-S2.‎

connect_23

Install Case & Battery Tray

Slide the 3D printed case in between the battery tray's two ‎mounting tabs.‎

Line up the mounting holes, then insert and fasten two M2.5 x 6mm ‎long machine screws to secure the two parts together.‎

install_24

install_25

Assemble Enclosure

Orient the back cover with the front case and begin to fit the JST ‎extension cable inside the enclosure. ‎

Fit the JST extensions cables socket connector through the notch in ‎the back cover.‎

Press the front case and back cover together to close them shut.‎

press_26

press_27

Install Battery

Connect the battery to the JST extension cable.‎

Place the battery into the 3D printed tray.‎

battery_28

battery_29

Final Build

Congratulations on your build!‎

The Feather ESP32-S2 will power on immediately after connecting ‎the battery. Plug in a USB cable to your Feather to begin charging ‎the battery.‎

Allow the Feather to connect to your WiFi and establish a voltage ‎reading. This may take a minute or two to output to the TFT display.‎

final_30

Text editor powered by tinymce.‎

Usage

Button D0‎

Press the D0 button (top) to enable sending data to Adafruit IO. The ‎blue circle indicates data is sending to Adafruit IO.‎

3d_printing_usage-D0

Button D1‎

Press the D1 button (middle) to toggle between icon view and plain ‎text view.‎

3d_printing_usage-D1

Button D2‎

Press the D2 button (bottom) to toggle between the battery icon ‎and battery percentage text.‎

3d_printing_usage-D2

USB Charging

Use a 5V 1A power supply and USB-C type cable to charge the ‎battery.‎

usb_34

Text editor powered by tinymce.

制造商零件编号 5345
ADAFRUIT ESP32-S2 REVERSE TFT FE
Adafruit Industries LLC
制造商零件编号 1131
JST-PH BATTERY EXT CABLE
Adafruit Industries LLC
制造商零件编号 5044
CABLE A PLUG TO C PLUG 6.5'
Adafruit Industries LLC
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum