• sales

    +86-0755-88291180

RPi-UPS-PD-3-(A) User Guide

I2C enable and Search】

】Enable I2C

[] Method 1

Enable i2c in config.txt sudo nano /boot/config.txt

Add at the bottom of the configuration file

dtparam=i2c_arm=on

Crtl+O to save, Ctrl+X to exit

sudo reboot

Reboot to take effect


[] Method 2

Use the raspi-config command to select and enable i2c

sudo raspi-config --> Interface Options --> I2C --> YES --> OK


[] Method 3

Use raspi-config to directly enable i2c

sudo raspi-config nonint do_i2c <0/1>

Parameter 0: Enable I2C

Parameter 1: Disable I2C


】Search enabled i2c devices


】Search i2c device address

Because i2c1 is enabled by default and UPS also uses i2c1, here we only use i2c1 as an example:

sudo i2cdetect -y 1


The address of the power reading and writing chip is detected to be 0x36


【GUI display battery status】


】Install Software

sudo apt-get update

sudo apt-get install python3-tk


】Edit code file

sudo mkdir -m a+x ./battery_status_code

cd ./battery_status_code

sudo nano ./battery_status_GUI_app.py


】Add the following code to the file

import tkinter as tk

from tkinter import PhotoImage

import smbus

import time

import threading

device_address = 0x36

VCELL = 0x02

SOC = 0x04

SOC1 = 0x05

MODE = 0x06

VERSION = 0x08

CONFIG = 0x0C

COMMAND = 0xFE

bus = smbus.SMBus(1)

def read_custom_bits(device_address, register, num_bits):

num_bytes = (num_bits + 7) // 8 # 计算所需的字节数

# 从设备中读取指定字节数的数据

data = bus.read_i2c_block_data(device_address, register, num_bytes)

# 将字节数据转换为位串

bit_string = ''.join(format(byte, '08b') for byte in data)

# 从位串中提取指定位数的数据

result = int(bit_string[:num_bits], 2)

return result

def update_data():

while True:

VCELL_data = read_custom_bits(device_address, VCELL, 12)

SOC_data = bus.read_byte_data(device_address, SOC)

SOC1_data = bus.read_byte_data(device_address, SOC1)

# MODE_data = bus.read_byte_data(device_address, MODE)

# VERSION_data = bus.read_byte_data(device_address, VERSION)

# CONFIG_data = bus.read_byte_data(device_address, CONFIG)

# COMMAND_data = bus.read_byte_data(device_address, COMMAND)

# 更新标签文本

vcell_label.config(text=f"Battery voltage: {VCELL_data * 0.00125:.4f} V")

soc_label.config( text=f"Battery level: {SOC_data + (SOC1_data / 256):.2f} %")

# vcell_label.config(text=f"VCELL: {VCELL_data * 0.00125:.4f} V")

# soc_label.config(text=f"SOC: {SOC_data + (SOC1_data / 256):.2f} %")

# mode_label.config(text=f"MODE: {MODE_data}")

# version_label.config(text=f"VERSION: {VERSION_data}")

# config_label.config(text=f"CONFIG: {CONFIG_data}")

# command_label.config(text=f"COMMAND: {COMMAND_data}")

time.sleep(0.5)

def start_update_thread():

threading.Thread(target=update_data, daemon=True).start()

root = tk.Tk()

root.title("I2C Data Monitor")

root.attributes("-fullscreen", True)

# 添加Logo

logo = PhotoImage(file="/home/pi/battery_status_code/logo.png")

logo_label = tk.Label(root, image=logo)

logo_label.pack(pady=10)

vcell_label = tk.Label(root, text="Battery voltage: ", font=("Helvetica", 16))

vcell_label.pack(pady=10)

soc_label = tk.Label(root, text="Battery level: ", font=("Helvetica", 16))

soc_label.pack(pady=10)

#vcell_label = tk.Label(root, text="VCELL: ", font=("Helvetica", 16))

#vcell_label.pack(pady=10)

#soc_label = tk.Label(root, text="SOC: ", font=("Helvetica", 16))

#soc_label.pack(pady=10)

#mode_label = tk.Label(root, text="MODE: ", font=("Helvetica", 16))

#mode_label.pack(pady=10)

#version_label = tk.Label(root, text="VERSION: ", font=("Helvetica", 16))

#version_label.pack(pady=10)

#config_label = tk.Label(root, text="CONFIG: ", font=("Helvetica", 16))

#config_label.pack(pady=10)

#command_label = tk.Label(root, text="COMMAND: ", font=("Helvetica", 16))

#command_label.pack(pady=10)

button = tk.Button(root, text="Close", command=root.quit, font=("Helvetica", 16))

button.pack(pady=20)

# 启动更新数据的线程

start_update_thread()

# 绑定按键事件,按F11键切换全屏模式,按Esc键退出全屏模式

root.bind("<F11>", lambda event: root.attributes("-fullscreen", not root.attributes("-fullscreen")))

root.bind("<Escape>", lambda event: root.attributes("-fullscreen", False))

root.mainloop()

NOTE:Please note that the path of the logo image should be consistent with the actual path.
You will get this file : battery_status_GUI_app.rar

】Execute program

sudo python3 ./battery_status_GUI_app.py

NOTE:To execute the program in the GUI environment, if you only execute it in ssh, you will get an error "Unable to access the graphical environment"



】Automatic startup

[] Create Python script

Compile a Python script for a Tkinter program, such as the above program
"/home/pi/battery_status_code/battery_status_GUI_app.py"

[] Create a systemd service file

Create a file called "gui_app.service" which defines the behavior of the Tkinter GUI application as a service and run the following command in the terminal:
sudo nano /etc/systemd/system/gui_app.service

[] Add the following code to the file

[Unit]

Description=Tkinter GUI Application

After=graphical.target

[Service]

User=pi

Environment=DISPLAY=:0

ExecStart=/usr/bin/python3 /home/pi/battery_status_code/battery_status_GUI_app.py

Restart=always

[Install]

WantedBy=graphical.target

You will get this file : gui_app.service

[] Reload systemd configuration

Run the following command to reload the systemd configuration file so that it recognizes the new service file
sudo systemctl daemon-reload

[] Enable and start the service

Run the following commands to enable and start the service so it will automatically run at system boot:
sudo systemctl enable gui_app.service
sudo systemctl start gui_app.service

[] Verify whether the service is running

Check the status of the service using the following command
sudo systemctl status gui_app.service
If the service is running normally, you will see the status of the service as `active (running)'.


Command line display battery status

】Edit code file

sudo mkdir -m a+x ./battery_status_code

cd ./battery_status_code

sudo nano ./battery_status_command_app.py


】Add the following code to the file

import smbus

import time

import sys

device_address = 0x36

VCELL = 0x02

SOC = 0x04

SOC1 = 0x05

MODE = 0x06

VERSION = 0x08

CONFIG = 0x0C

COMMAND = 0xFE

bus = smbus.SMBus(1)

def read_custom_bits(device_address, register, num_bits):

num_bytes = (num_bits + 7) // 8 # 计算所需的字节数

# 从设备中读取指定字节数的数据

data = bus.read_i2c_block_data(device_address, register, num_bytes)

# 将字节数据转换为位串

bit_string = ''.join(format(byte, '08b') for byte in data)

# 从位串中提取指定位数的数据

result = int(bit_string[:num_bits], 2)

return result

def clear_screen():

# 清除屏幕并将光标移动到起始位置

sys.stdout.write("\033[H\033[J")

sys.stdout.flush()

while True:

clear_screen()

VCELL_data = read_custom_bits(device_address, VCELL, 12)

SOC_data = bus.read_byte_data(device_address, SOC)

SOC1_data = bus.read_byte_data(device_address, SOC1)

MODE_data = bus.read_byte_data(device_address, MODE)

VERSION_data = bus.read_byte_data(device_address, VERSION)

CONFIG_data = bus.read_byte_data(device_address, CONFIG)

COMMAND_data = bus.read_byte_data(device_address, COMMAND)

# 打印读取的数据

print(" Battery status \n")

print("Battery voltage:", (VCELL_data * 0.00125))

print("Battery level :", SOC_data + (SOC1_data / 256), "%")

print()

time.sleep(1)

You will get this file : battery_status_command_app.py

】Execute program

sudo python3 ./battery_status_command_app.py


【Resources】

Max17043 data sheet: MAX17043.pdf

MAX17043 Register Table

Register function explanation:

VCELL (02h-03h)
】Measures battery voltage for power calculation and status monitoring.
】The data is a 12-bit A/D conversion result with an accuracy of 1.25mV.
SOC (04h-05h)
】Estimates the remaining battery power through the ModelGauge algorithm in percentage (0% ~ 100%).
】The data is 16 bits, usually the high byte is the main value and the low byte represents the decimal part.
MODE (06h-07h)
】Controls the chip mode, such as the QuickStart command (QuickStart) or entering sleep mode (Sleep Mode).
】The QuickStart command forces the chip to re-evaluate the battery status.
VERSION (08h-09h)
】Returns the hardware version number of the chip to facilitate compatibility verification of the chip version.
CONFIG (0Ch-0Dh)
】Used to set compensation parameters or optimize chip performance, such as adjusting battery characteristic parameters to improve measurement accuracy.
】Can be used to enable functions such as idle mode detection.
COMMAND (FEh-FFh)
】Used to send reset commands (such as writing 0x0054 to reset the chip) or other special operation commands.
】The default value is 971Ch, which indicates the initial state of the chip.

【Support

Monday-Friday (9:30-6:30) Saturday (9:30-5:30)   - (China time)

Email: services01@spotpear.com

WhatsApp


TAG: X1300 X1300-A2 Raspberry Pi 5 HDMI to CSI-2 Shield 1080P@60fps & Audio & Video Also Raspberry Pi PICO Long-Range Communication Jetson Orin 5G/4G/3G expansion board GNSS GPS SIM8260G-M2 SIM8262E-M2 EG25-G Mini PCIe SIMCom Original 4G LTE Cat-4 Module Global Coverage GNSS PCI Express Mini Card AV to LVDS Raspberry Pi 5 PCM5122 I2S Audio Card DAC Also For PI4 /PI3 /Zero Series ESP32 C3 LCD Development Board 1.3 inch Display Screen ST7789 240x240 3D Transparent Refractive Prism Mini TV For Arduino 14 inch Dual LCD Computer PC Monitor Display Double Secondary Screen Type C Mini HDMI 1080P For Windows/MacOS Raspberry Pi IR Thermal Imagi Retail electronic Labe RS485 Bus Raspberry Pi Camera 12MP Sony IMX708 autofocus HDR Module 3 Sensor Assembly ESP32-S3 DeepSeek AI Box Robot Development Board N16R8 Toy Doll Option 0.71 inch Electronic Eyes Industrial-grade isolated 2-way RS485 hub repeater One RS485 TO Two RS485 ESP32 C3 Voice Robot Mini Development Board AI DeepSeek Toy Doll Core 1.28 inch 1.54inch LCD RP2040 ESP32-S3FH4R2-MINI-Tiny-Stamp-WIFI-Bluetooth5 ESP32 S3 LCD Camera Development Board 2 inch Display QMI8658 Sensor / Battery Port LVGL/HMI For Arduino Raspberry Pi 5 Power Milk-V Duo Camera