RPi-UPS-PD-3-(A) 使用教程

I2C开启与查询

开启I2C

开启I2C的方法有多种

方法一:

在config.txt开启i2c sudo nano /boot/config.txt

在配置文件的最下面添加

dtparam=i2c_arm=on

Crtl+O保存、Ctrl+X退出

sudo reboot

重启生效


方法二:

使用raspi-config指令依次选择开启i2c

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


方法三:

使用raspi-config直接开启i2c

sudo raspi-config nonint do_i2c <0/1>

参数0: 开启 I2C

参数1: 关闭 I2C

查询开启的i2c设备


查询i2c设备地址

因为默认开启的i2c1并且UPS使用的也是i2c1,所以这里仅用i2c1为例子:

sudo i2cdetect -y 1


检测到电量读写芯片的地址是0x36


GUI显示电池状态

安装Tkinter】

sudo apt-get update
sudo apt-get install python3-tk


编辑代码文件】

sudo mkdir -m a+x ./battery_status_code
cd ./battery_status_code
sudo nano ./battery_status_GUI_app.py


在文件中添加以下代码】

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:注意logo图片的路径要以实际路径保持一致

文件下载:battery_status_GUI_app.rar


执行程序】

sudo python3 ./battery_status_GUI_app.py

NOTE:要在GUI环境执行该程序,如果只在ssh执行则会报“无法访问图形环境”的错误



执行效果】


如需要开机自启动该程序

NOTE:因为该程序必须在GUI环境才能正常启动,所以在/etc/rc.local自启动脚本的方法是无效的,得使用服务的方法实现自启动;

创建Python脚本】

编译一个Tkinter程序的Python脚本,如上述程序“/home/pi/battery_status_code/battery_status_GUI_app.py

创建一个systemd服务文件】

创建一个名为"gui_app.service"的文件,该文件定义了Tkinter GUI应用程序作为服

务的行为,并在终端中运行以下命令

sudo nano /etc/systemd/system/gui_app.service

在文件中添加以下代码】

[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

文件下载:gui_app.service


重新加载systemd配置】

运行以下命令以重新加载systemd配置文件,使其识别新的服务文件

sudo systemctl daemon-reload

启用并启动服务】

运行以下命令以启用并启动服务,这样它将在系统启动时自动运行:

sudo systemctl enable gui_app.service
sudo systemctl start gui_app.service

验证服务是否运行】

使用以下命令检查服务的状态

sudo systemctl status gui_app.service

如果服务运行正常,会看到服务的状态为`active(running)'。


指令行显示电池状态

编辑代码文件】

sudo mkdir -m a+x ./battery_status_code
cd ./battery_status_code
sudo nano ./battery_status_command_app.py


在文件中添加以下代码】

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)

文件下载:battery_status_command_app.py


执行程序】

sudo python3 ./battery_status_command_app.py


执行效果】


资料

Max17043数据手册:ADI-MAX17043.pdf

寄存器表


寄存器表功能解释

VCELL (02h-03h)

测量电池电压,用于电量计算和状态监控。

数据为 12 位的 A/D 转换结果,精度为 1.25mV。

SOC (04h-05h)

通过 ModelGauge 算法估算电池剩余电量,单位是百分比(0% ~ 100%)。

数据为 16 位,通常高字节是主要数值,低字节表示小数部分。

MODE (06h-07h)

控制芯片的模式,例如快速启动命令(QuickStart)或进入睡眠模式(Sleep Mode)。

快速启动命令可强制芯片重新评估电池状态。

VERSION (08h-09h)

返回芯片的硬件版本号,方便进行芯片版本的兼容性验证。

CONFIG (0Ch-0Dh)

用于设置补偿参数或优化芯片性能,例如调整电池特性参数以提高测量精度。

可以用于启用空闲模式检测等功能。

COMMAND (FEh-FFh)

用于发送复位命令(例如写入 0x0054 重置芯片)或其他特殊操作命令。

默认值为 971Ch,表示芯片的初始状态。


售后

周一-周五(9:30-6:30)周六(9:30-5:30)

手机:13434470212

邮箱:services04@spotpear.cn

QQ:202004841