• 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: 0.85inch LCD Core3566102032 UNO Minima RA4M1 ZERO Tiny SuperMini R7FA4M1 Board Compatible With R4 For Arduino ESP32 Development Board C3 1.28 inch Round Rotary LCD Smart Screen 1.28inch Knob Display 240x240 LVGL for Arduino ESP32-P4 Core Board 32MB PSRAM 16MB Flash Raspberry Pi Pico 2 RP2350 ETH CH9120 TCP/UDP Ethernet Network For Arduino Raspberry Pi 5 Electronic EYE 0.71 inch Round LCD Display Screen For Arduino Raspberry Pi ESP32 Pico STM32 Raspberry Pi Display Driver Board Modbus RTU Relay 32CH Raspberry Pi PICO Long-Range Communication ESP32 S3 LCD Camera Development Board 2 inch Display QMI8658 Sensor / Battery Port LVGL/HMI For Arduino Luckfox PicoKVM KVM NanoKVM RV1106 Pico Remote Control /Power /Desktop Maintenance Server HDMI USB For PiKVM Raspberry Pi ESP32 ST7789 ESP32-C6 LCD Development Board 1.3 inch Display 1.3inch Screen ST7789 240x240 Mini TV SD-Port QST LVGL For Arduino Raspberry Pi 7 inch QLED Quantum Dot Display 1024x600 Capacitive Touchscreen For Computer PC/Jetson/Game Raspberry Pi 5 Fan Raspberry Pi USB Camera 5MP OS05A10 Distortion-Free USB 2.0 For Jeston RDK Arduino Thermal imaging camera Raspberry Pi 5inch Display 1024x600 HDMI Capacitive TouchScreen 5 inch LCD B Wide-Cover For Mini PC