UPS Kit for M1S
The UPS(Uninterrupted Power Supply) device is designed specifically for the ODROID-M1S.
It is equipped with a 18650 rechargeable Li-Ion battery holder, charger control IC and a 5Volt Boost DCDC.
There is a small MCU on the board which measures the battery level and communicate with the ODROID-M1S board via USB interface.
When the AC power source is removed, the UPS keeps supplying the power to the ODROID-M1S boards with the battery.
The M1S-UPS has a USB serial port(ttyACM) to communicate with so that it can trigger the shutdown process by sending a low battery warning.
It will significantly reduce the risk of data loss by a sudden power outage.
When the AC power source becomes available again, the UPS will supply power to the ODROID-M1S again and trigger a power-on event automatically.
If you have 30~40mm PCB spacers and M3 screws, you can mount the UPS on the ODROID-M1S cases.
* The battery is not included in the product package, so you have to buy a PROTECTED 18650 Li-Ion rechargeable battery in your local market and install it.
The length of the 18650 Li-Ion battery with a built-in protection circuit is close to 68mm, which is about 3mm longer than the unprotected bare cell battery length of 65mm.
- Since the retail market in many countries, including South Korea, does not allow the sale of unprotected lithium-ion rechargeable batteries, we designed it to use batteries that include a protection circuit.
- For safety reasons, when purchasing batteries, please choose a reputable battery cell manufacturer if possible. As far as we know that Panasonic, LG, Samsung, and CATL are famous.
Due to the Li-Ion chemical characteristics, the battery voltage level might go higher slightly when the load is very light.
Specification
Power Input | |
Recommended power supply | DC 4.8V ~ 5.3V with 3Amp output |
Charger | |
Charging Time | 5 ~ 9 hours |
Battery Charging Current | 500mA Max. |
Power Ouput | |
DC Output Current | 3A Max. |
DC Output Voltage | 5.2 V |
Recommended Battery | |
Type | Protected Li-Ion 18650 cylindrical cell |
Capacity | Any of 2300~3600 mAh |
Nominal Voltage | 3.7 V |
Estimated ODROID-M1S running time (500mA @ 5V) | About 3~4 hours with a fully charged battery |
The product package contains only the UPS board and cables.
You must purchase a protection circuit included 18650 lithium-ion battery separately.
Firmware Release
Release v0.5 : 2023-11-22 m1s_ups_fw rev 0.5
- Fixed an issue where auto power-on would not work on power-up again if the battery was completely discharged.
- Boot voltage setting changed from 3300mV to 3500mV to prevent malfunction (Power on/off loop occurs at boot voltage (3300 mV) and forced power off voltage (3300 mV)).
Release v0.4 : 2023-09-04 m1s_ups_fw rev 0.4
- Fixed battery voltage condition value to force system power off.
- 3400mV → 3300mV
- Fixed an issue where the power would turn off after firmware update.
How to update UPS firmware
Required Ubuntu packages
root@odroid:~/m1s_ups# apt install wget unzip vim usbutils minicom
Install update tools and scripts
root@odroid:~# mkdir-p m1s_ups root@odroid:~# cd m1s_ups # Update tool download root@odroid:~/m1s_ups# wget https://cdn.jsdelivr.net/gh/DeqingSun/ch55xduino@playground/ch55xduino/tools/linux_arm/vnproch55x root@odroid:~/m1s_ups# chmod 777 ./vnproch55x root@odroid:~/m1s_ups# cp vnproch55x /bin/
Firmware update script
- fw_update.sh
#!/bin/bash #/*---------------------------------------------------------------------------*/ #/* Define CH55xduino ttyACM VID/PID (1209:c550) */ #/*---------------------------------------------------------------------------*/ VID_CH55xduino="1209" PID_CH55xduino="C550" FW_UPDATE_TOOL="/bin/vnproch55x" UPS_TTY_NODE="" #/*---------------------------------------------------------------------------*/ #/* find ttyNode name : VID_CH55xduino(1209):PID_CH55xduino(c550) #/*---------------------------------------------------------------------------*/ function find_tty_node { UPS_TTY_NODE=`find $(grep -l "PRODUCT=$(printf "%x/%x" "0x${VID_CH55xduino}" "0x${PID_CH55xduino}")" \ /sys/bus/usb/devices/[0-9]*:*/uevent | sed 's,uevent$,,') \ /dev/null -name dev -o -name dev_id | sed 's,[^/]*$,uevent,' | xargs sed -n -e s,DEVNAME=,/dev/,p -e s,INTERFACE=,,p` } #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/* START Script */ #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/* update hex file check */ #/*---------------------------------------------------------------------------*/ if [ -z "$1" ]; then echo "------------------------------------------------------------" echo "Useage : ./fw_update.sh {update hex file}" echo "------------------------------------------------------------" exit 1 elif [ ! -e "$1" ]; then echo "------------------------------------------------------------" echo "File not found ($1)." echo "------------------------------------------------------------" exit 1 fi #/*---------------------------------------------------------------------------*/ #/* update tool check */ #/*---------------------------------------------------------------------------*/ if [ -z "${FW_UPDATE_TOOL}" ]; then echo "------------------------------------------------------------" echo "Can't found f/w update tool. ${FW_UPDATE_TOOL}" echo "------------------------------------------------------------" exit 1 fi #/*---------------------------------------------------------------------------*/ #/* find CH55xduino ttyACM node (1209:c550) */ #/*---------------------------------------------------------------------------*/ find_tty_node #/*---------------------------------------------------------------------------*/ #/* Script exit handling when node not found. */ #/*---------------------------------------------------------------------------*/ if [ -z "${UPS_TTY_NODE}" ]; then echo "------------------------------------------------------------" echo "Can't found ttyACM(CH55xduino) device. (1209:c550)" echo "------------------------------------------------------------" exit 1 else echo "------------------------------------------------------------" echo "Found ttyACM(CH55xduino) device. Node name = ${UPS_TTY_NODE}" echo "------------------------------------------------------------" fi #/*---------------------------------------------------------------------------*/ #/* ttyACM F/W update mode setup */ #/*---------------------------------------------------------------------------*/ stty -F ${UPS_TTY_NODE} 1200 raw -echo #/*---------------------------------------------------------------------------*/ #/* UPS f/w update */ #/*---------------------------------------------------------------------------*/ vnproch55x -r 2 $1 #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/
Firmware download and flash into the MCU on the UPS board
# Firmware download root@odroid:~/m1s_ups# wget https://wiki.odroid.com/_media/en/m1s_ups/rev0.4_hex.zip root@odroid:~/m1s_ups# unzip rev0.4_hex.zip # Disable M1S_UPS control service for firmware update root@odroid:~/m1s_ups# service m1s_ups stop root@odroid:~/m1s_ups# systemctl disable m1s_ups # Update firmware root@odroid:~/m1s_ups# stty -F /dev/ttyACM0 1200 root@odroid:~/m1s_ups# vnproch55x -r 2 ./rev0.4_hex/ups_fw.ino.hex # or use update script (fw_update.sh) root@odroid:~/m1s_ups# ./fw_update.sh ./rev0.4_hex/ups_fw.ino.hex # Enable M1S_UPS control service root@odroid:~/m1s_ups# systemctl enable m1s_ups root@odroid:~/m1s_ups# service m1s_ups start # check ups log root@odroid:~/m1s_ups# tail -f /var/log/syslog Sep 4 07:14:27 server bash[1480]: ------------------------------------------------------------ Sep 4 07:14:27 server bash[1480]: ------------------------------------------------------------ Sep 4 07:14:31 server bash[1480]: Mon Sep 4 07:14:31 UTC 2023 Sep 4 07:14:31 server bash[1480]: UPS Battery Status (Charging...) Sep 4 07:14:31 server bash[1480]: UPS Battery Volt : 4077 mV Sep 4 07:14:31 server bash[1480]: SYSTEM Power OFF : UPS Battery Volt is lower then 3750 mV Sep 4 07:14:31 server bash[1480]: ------------------------------------------------------------ Sep 4 07:14:31 server bash[1480]: ------------------------------------------------------------ Sep 4 07:14:35 server bash[1480]: Mon Sep 4 07:14:35 UTC 2023 Sep 4 07:14:35 server bash[1480]: UPS Battery Status (Charging...) Sep 4 07:14:35 server bash[1480]: UPS Battery Volt : 4077 mV Sep 4 07:14:35 server bash[1480]: SYSTEM Power OFF : UPS Battery Volt is lower then 3750 mV Sep 4 07:14:35 server bash[1480]: ------------------------------------------------------------
Documents
Datasheet CH552DS1:ch552ds1.pdf
Datasheet TC4056A:tc4056a_c84051.pdf
Datasheet TLV70245DBVR:texas-instruments-tlv70245dbvr.pdf
Datasheet TPS61088RHLR:texas-instruments-tps61088rhlr.pdf
PCB Layout(DWG):ups4m1s_rev1.0_230818_mech.zip
PCB Pattern(PNG):m1s_ups_board.zip
How to connect the UPS to ODROID-M1S
The 14 PIN Header (J3) of the M1S board and the 14 PIN header(J1) of the UPS board must be connected 1:1 (1 Pin → 1 Pin).
Check UPS MCU interface connection
# check ttyUSB Device root@odroid:~/m1s_ups# lsusb | grep 1209:c550 Bus 001 Device 062: ID 1209:c550 Generic CH55xduino # find the ch55xduino device node root@odroid:~/m1s_ups# echo "ch55xduino dev node =" `find $(grep -l "PRODUCT=$(printf "%x/%x" "0x1209" "0xc550")" \ /sys/bus/usb/devices/[0-9]*:*/uevent | sed 's,uevent$,,') \ /dev/null -name dev -o -name dev_id | sed 's,[^/]*$,uevent,' | xargs sed -n -e s,DEVNAME=,/dev/,p -e s,INTERFACE=,,p` ch55xduino dev node = /dev/ttyACM0 # Request battery avr voltage (auto repeat 1 sec) root@odroid:~/m1s_ups# echo "@V1#" > /dev/ttyACM0 root@odroid:~/m1s_ups# cat /dev/ttyACM0 @V3950# @V3951# @V3952# ^C # disable auto repeat root@odroid:~/m1s_ups# echo "@V0#" > /dev/ttyACM0
Install UPS control service
# Download M1S_UPS control service package root@odroid:~/m1s_ups# wget https://wiki.odroid.com/_media/en/m1s_ups/service.zip root@odroid:~/m1s_ups# unzip ./service.zip root@odroid:~/m1s_ups# chmod 777 -R ./service root@odroid:~/m1s_ups# cd service # Install M1S_UPS Control service root@odroid:~/m1s_ups/service# ./install_service.sh # Check that the control service is running root@odroid:~/m1s_ups/service# systemctl status m1s_ups # If you want to stop/remove the control service root@odroid:~/m1s_ups/service# service m1s_ups stop root@odroid:~/m1s_ups/service# systemctl disable m1s_ups
H/W Block Diagram
S/W Flow Chart
State indicators(LED)
Power ON state (Blink period is 500 msec)
Battery Level Indicator(LED) (Charging, FULL / Discharging) |
||||
Battery Display Level | LV4 | LV3 | LV2 | LV1 |
LV4 (3950mV) | ON / BLINK | ON | ON | ON |
LV3 (3750 mV) | OFF | ON / BLINK | ON | ON |
LV2 (3650 mV) | OFF | OFF | ON / BLINK | ON |
LV1 (3550 mV) | OFF | OFF | OFF | ON / BLINK |
LV0 (3400 mV) | OFF | OFF | OFF | OFF |
Error : Battery Remove | Blink | OFF | OFF | Blink |
Power OFF state (Blink period is 2 sec)
Battery Level Indicator(LED) (M1S_UPS Power OFF state) |
||||
Battery Display Level | LV4 | LV3 | LV2 | LV1 |
LV4 (3950mV) | BLINK | BLINK | BLINK | BLINK |
LV3 (3750 mV) | OFF | BLINK | BLINK | BLINK |
LV2 (3650 mV) | OFF | OFF | BLINK | BLINK |
LV1 (3550 mV) | OFF | OFF | OFF | BLINK |
LV0 (3400 mV) | OFF | OFF | OFF | OFF |
Error : Battery Remove | Blink | OFF | OFF | Blink |
Charger state
Charger State Indicator(LED) | ||
Charger State | CHRG | FULL |
Error : Battery Remove | BLINK | 0 |
Charging | 0 | 1 |
Full Charged | 1 | 0 |
Discharging | 1 | 1 |
Battery discharge graph by Load (@500mA, @2A)
If your ODROID-M1S System takes 2A, the M1S_UPS can supply the power to your system around 9~10 minutes at least.(Battery level@3550mV)
It seems to be fine to shutdown the system safely.
When the battery level is below 3300mV, the ODROID-M1S will be forced shut down by the “RESET” and “PWRBTN” gpios on the m1s_ups board.
Picture of the board temperature when charging the battery.
Warning :
The UPS board generates a lot of heat when charging, so be careful not to touch the board.
Serial Protocol
ODROID-M1S → M1S_UPS (Request) | |||||
START (1 Byte) | CMD (1 Byte) | DATA (1 Byte) | END (1 Byte) | Description | |
@ | L | 0 ~ 9 | # | Battery Level | 1 ~ 9 : Automatically report data every (1 ~ 9) second. * : Report once and disable automatic reporting. (default) |
V | Battery Voltage(Avr) | ||||
C | Charger State | ||||
W | Watchdog Setup | 1 ~ 9 : Watchdog enable & watchdog time reset (sec) * : Watchdog disable (default) |
|||
O | Power On Battery level | Set the battery level when restarting after a power outage. (default : Turns on when power input is detected.) Cal Power On Battery Value = 3500mV + (set value) * 50mV 0 : 3400 mV (default) 1 : 3550 mV 2 : 3600 mV … 9 : 3950 mV |
|||
P | x | Power Off Event | Notify m1s_ups that poweroff command has been executed. (m1s_ups enters Power OFF state) | ||
F | x | Firmware Version | Request the current F/W version. | ||
R | 1 / 0 | (DEBUG) RESET GPIO Control | 1 : Set High, 0 : Set Low * : Setting is ignored. |
||
B | 1 / 0 | (DEBUG) PWRBT GPIO Control | |||
X | x | (DEBUG) UPS Watchdog reset | Stop UPS firmware for UPS Watchdog reset. | ||
T | x | (DEBUG) Battery Level LED Test | Execute firmware for LED test. |
M1S_UPS → ODROID-M1S (Response) | ||||||||
START (1 Byte) | CMD (1 Byte) | DATA (4 Bytes) | END (1 Byte) | Description | ||||
MSB | LSB | |||||||
@ | L | 1 / 0 (LV4) | 1 / 0 (LV3) | 1 / 0 (LV2) | 1 / 0 (LV1) | # | Battery Level | Battery level indicator(LED) state |
V | 0 ~ 9999 | Battery Voltage(Avr) | 1-minute moving average battery value. | |||||
C | F | 1 / 0 | C | 1 / 0 | Charger State | Charger state indicator(LED) F (FULL LED State), C (CHRG LED State) FULL = 0., CHRG = 0 : Error condition (Battery remove) FULL = 1., CHRG = 0 : Charging FULL = 0., CHRG = 1 : Full charged FULL = 1., CHRG = 1 : Discharging |
||
W | 0 ~ 9999 | Watchdog Setup | Displays the set watchdog setting value. | |||||
O | 0 ~ 9999 | Power On Battery level | Displays the set power-on voltage value after power outage. | |||||
P | - | O | F | F | Power Off Event | |||
F | V | 1 / 9 | - | 1 / 9 | Firmware Version | F/W version. (Version 0.1 = V0-1) | ||
R | 1 / 0 | (DEBUG) RESET GPIO Control | 1 : GPIO Status High 0 : GPIO Status Low |
|||||
B | 1 / 0 | (DEBUG) PWRBTN GPIO Control |
M1S_UPS responds with a “@V3700#” command to ODROID-M1S through the ttyACM port.
UPS Control Script
- check_ups.sh
#!/bin/bash #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ # # # Script configuration start # # #/*---------------------------------------------------------------------------*/ #/* Battery level definition value for UPS system */ #/*---------------------------------------------------------------------------*/ BATTERY_LEVEL_FULL="4300" #/* Battery level define (1 ~ 9) */ BATTERY_LEVEL_3550mV="3550" BATTERY_LEVEL_3600mV="3600" BATTERY_LEVEL_3650mV="3650" BATTERY_LEVEL_3700mV="3700" BATTERY_LEVEL_3750mV="3750" BATTERY_LEVEL_3800mV="3800" BATTERY_LEVEL_3850mV="3850" BATTERY_LEVEL_3900mV="3900" BATTERY_LEVEL_3950mV="3950" BATTERY_LEVEL_0mV="0" #/*---------------------------------------------------------------------------*/ #/* Set battery level for system power off */ #/* BATERRY_LEVEL_FULL : Power off when battery discharge condition detected. */ #/* BATERRY_LEVEL_3550mV : Power off when battery is below 3550mV. #/* (BATERRY_LEVEL_3550mV is maintained for 10 minutes at 5V/2A load.) */ #/*---------------------------------------------------------------------------*/ # CONFIG_POWEROFF_BATTERY_LEVEL=${BATTERY_LEVEL_FULL} CONFIG_POWEROFF_BATTERY_LEVEL=${BATTERY_LEVEL_3550mV} #/*---------------------------------------------------------------------------*/ #/* Set battery level for system power on */ #/* Power on when battery charge condition detected.(default) */ # BATTERY_LEVEL_0mV : Detect charging status.(default) #/*---------------------------------------------------------------------------*/ CONFIG_POWERON_BATTERY_LEVEL=${BATTERY_LEVEL_0mV} # CONFIG_POWERON_BATTERY_LEVEL=${BATTERY_LEVEL_3550mV} #/*---------------------------------------------------------------------------*/ #/* Set watchdog reset time */ # 0 : Disable.(default) # 1 ~ 9 : Watchdog reset time(sec) : Warnning # # WARNING: The watchdog reset value must be greater than the script execution time. # # The script takes about 4-5 seconds to run once. # #/*---------------------------------------------------------------------------*/ CONFIG_WATCHDOG_RESET_TIME="" #/*---------------------------------------------------------------------------*/ # # # Script configuration end # # #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/* Define CH55xduino ttyACM VID/PID (1209:c550) */ #/*---------------------------------------------------------------------------*/ VID_CH55xduino="1209" PID_CH55xduino="C550" #/*---------------------------------------------------------------------------*/ #/* Define tmp file */ #/*---------------------------------------------------------------------------*/ UPS_TTY_NODE="" UPS_TTY_DATA="/tmp/ttyUPS.dat" #/*---------------------------------------------------------------------------*/ #/* battery log filename (default disable) */ #/* eg) UPS_TTY_LOG="/tmp/ttyUPS.log" */ #/*---------------------------------------------------------------------------*/ UPS_TTY_LOG="" #/*---------------------------------------------------------------------------*/ #/* Script start time and date */ #/*---------------------------------------------------------------------------*/ CURRENT_TIME=$(date) #/*---------------------------------------------------------------------------*/ #/* UPS Command List */ #/*---------------------------------------------------------------------------*/ # Send command to read battery volt to UPS. UPS_CMD_BATTERY_VOLT="@V0#" # Send command to read battery level to UPS. # LED 1 : BATTERY DISPLAY LEVEL 1 (3550 mV > Battery voltage) # LED 2 : BATTERY DISPLAY LEVEL 2 (3650 mV > Battery voltage) # LED 3 : BATTERY DISPLAY LEVEL 3 (3750 mV > Battery voltage) # LED 4 : BATTERY DISPLAY LEVEL 4 (3900 mV > Battery voltage) UPS_CMD_BATTERY_LEVEL="@L0#" # Send command to read charger status to UPS. UPS_CMD_CHARGER_STATUS="@C0#" # Send command to ups off to UPS. UPS_CMD_POWEROFF="@P0#" # Send command to power on level to UPS. # * : Detect charging status.(default) # 0 ~ 4 : BATTERY LEVEL UPS_CMD_POWERON="@O0#" # Send command to watchdog reset time to UPS. # * : Disable.(default) # 1 ~ 9 : Watchdog reset time UPS_CMD_WATCHDOG="@W0#" #/*---------------------------------------------------------------------------*/ #/* for communication with ups */ #/*---------------------------------------------------------------------------*/ UPS_CMD_STR="" #/*---------------------------------------------------------------------------*/ #/* UPS system data */ #/*---------------------------------------------------------------------------*/ UPS_BATTERY_VOLT="0" UPS_STATUS_CHRG="0" UPS_STATUS_FULL="0" #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/* Kill previously running processes(dead process). */ #/*---------------------------------------------------------------------------*/ function kill_dead_process { PID="" PID=`ps -eaf | grep ${UPS_TTY_NODE} | grep -v grep | awk '{print $2}'` if [ -n "$PID" ]; then echo "------------------------------------------------------------" echo "Killing $PID" kill -9 $PID echo "------------------------------------------------------------" fi } #/*---------------------------------------------------------------------------*/ #/* find ttyNode name : VID_CH55xduino(1209):PID_CH55xduino(c550) #/*---------------------------------------------------------------------------*/ function find_tty_node { UPS_TTY_NODE=`find $(grep -l "PRODUCT=$(printf "%x/%x" "0x${VID_CH55xduino}" "0x${PID_CH55xduino}")" \ /sys/bus/usb/devices/[0-9]*:*/uevent | sed 's,uevent$,,') \ /dev/null -name dev -o -name dev_id | sed 's,[^/]*$,uevent,' | xargs sed -n -e s,DEVNAME=,/dev/,p -e s,INTERFACE=,,p` } #/*---------------------------------------------------------------------------*/ #/* Send control commands to the UPS via the UPS_CMD_STR variable. #/*---------------------------------------------------------------------------*/ function ups_cmd_send { # ttyACM response data wait settings. cat ${UPS_TTY_NODE} > ${UPS_TTY_DATA} & sleep 1 # Get PID (cat command) to kill background process PID="" PID=$! #/* Send command string to UPS */ echo -ne ${UPS_CMD_STR} > ${UPS_TTY_NODE} sleep 1 #/* Update data */ case ${UPS_CMD_STR} in ${UPS_CMD_BATTERY_VOLT}) # Update battery volt data. UPS_BATTERY_VOLT=`cut -c 3-6 < ${UPS_TTY_DATA}` ;; ${UPS_CMD_BATTERY_LEVEL}) # Update charger status data. UPS_BATTERY_LV4=`cut -c 3 < ${UPS_TTY_DATA}` UPS_BATTERY_LV3=`cut -c 4 < ${UPS_TTY_DATA}` UPS_BATTERY_LV2=`cut -c 5 < ${UPS_TTY_DATA}` UPS_BATTERY_LV1=`cut -c 6 < ${UPS_TTY_DATA}` ;; ${UPS_CMD_CHARGER_STATUS}) # Update charger status data. UPS_STATUS_CHRG=`cut -c 6 < ${UPS_TTY_DATA}` UPS_STATUS_FULL=`cut -c 4 < ${UPS_TTY_DATA}` ;; * ) ;; esac # Kill background process(cat cmd) if [ -n "$PID" ]; then kill $PID fi } #/*---------------------------------------------------------------------------*/ # UPS system staus check. #/*---------------------------------------------------------------------------*/ function check_ups_status { #/* UPS Status : Error...(Battery Removed) */ if [ ${UPS_STATUS_CHRG} -eq "0" -a ${UPS_STATUS_FULL} -eq "0" ]; then echo "------------------------------------------------------------" echo "ERROR: Battery Removed. force power off..." echo "------------------------------------------------------------" system_poweroff return fi #/* UPS Status : Discharging... */ if [ ${UPS_STATUS_CHRG} -eq "1" -a ${UPS_STATUS_FULL} -eq "1" ]; then echo "UPS Battery Status (Discharging...)" #/* UPS Battery Status : Low Battery */ if [ ${UPS_BATTERY_VOLT} -lt ${CONFIG_POWEROFF_BATTERY_LEVEL} ]; then if [ ${CONFIG_POWEROFF_BATTERY_LEVEL} -eq ${BATTERY_LEVEL_FULL} ]; then #/* Power off after Detecting UPS battery discharge. */ echo "------------------------------------------------------------" echo "Detected UPS battery discharge." echo "------------------------------------------------------------" else echo "------------------------------------------------------------" echo "UPS Battery Volt : ${UPS_BATTERY_VOLT} mV" echo "UPS Battery Volt is lower then ${CONFIG_POWEROFF_BATTERY_LEVEL} mV" echo "------------------------------------------------------------" fi system_poweroff fi else if [ ${UPS_STATUS_CHRG} -eq "0" ]; then echo "UPS Battery Status (Charging...)" else echo "UPS Battery Status (Full Charged..)" fi fi echo "UPS Battery Volt : ${UPS_BATTERY_VOLT} mV" if [ ${CONFIG_POWEROFF_BATTERY_LEVEL} -eq ${BATTERY_LEVEL_FULL} ]; then echo "SYSTEM Power OFF : Detecting UPS battery discharge." else echo "SYSTEM Power OFF : UPS Battery Volt is lower then ${CONFIG_POWEROFF_BATTERY_LEVEL} mV" fi } #/*---------------------------------------------------------------------------*/ # Send command to ups off to UPS. #/*---------------------------------------------------------------------------*/ function system_poweroff { UPS_CMD_STR=${UPS_CMD_POWEROFF} ups_cmd_send echo "------------------------------------------------------------" echo "run poweroff command..." echo "------------------------------------------------------------" if [ -n "${UPS_TTY_LOG}" ]; then echo "${CURRENT_TIME}, POWEROFF" >> ${UPS_TTY_LOG} echo "-------------------------" >> ${UPS_TTY_LOG} fi poweroff exit 0 } #/*---------------------------------------------------------------------------*/ #/* Set watchdog reset time */ # 0 : Disable.(default) # 1 ~ 9 : Watchdog reset time(sec) : Warnning # # WARNING: The watchdog reset value must be greater than the script execution time. # # The script takes about 4-5 seconds to run once. # #/*---------------------------------------------------------------------------*/ function watchdog_reset { if [ ${CONFIG_WATCHDOG_RESET_TIME} -gt "9" -o ${CONFIG_WATCHDOG_RESET_TIME} -lt "0"] then echo "CONFIG_WATCHDOG_RESET_TIME=${CONFIG_WATCHDOG_RESET_TIME} value error." echo "WATCHDOG Disable" CONFIG_WATCHDOG_RESET_TIME="0" fi UPS_CMD_WATCHDOG="@W${CONFIG_WATCHDOG_RESET_TIME}#" UPS_CMD_STR=${UPS_CMD_WATCHDOG} ups_cmd_send } #/*---------------------------------------------------------------------------*/ #/* Set battery level for system power on */ #/* Power on when battery charge condition detected.(default) */ # 0 : Detect charging status.(default) # 1 ~ 9 : BATTERY LEVEL #/*---------------------------------------------------------------------------*/ function ups_poweron_setup { #/* Update data */ case ${CONFIG_POWERON_BATTERY_LEVEL} in ${BATTERY_LEVEL_3550mV}) POWERON_BATTERY_LEVEL="1" ;; ${BATTERY_LEVEL_3600mV}) POWERON_BATTERY_LEVEL="2" ;; ${BATTERY_LEVEL_3650mV}) POWERON_BATTERY_LEVEL="3" ;; ${BATTERY_LEVEL_3700mV}) POWERON_BATTERY_LEVEL="4" ;; ${BATTERY_LEVEL_3750mV}) POWERON_BATTERY_LEVEL="5" ;; ${BATTERY_LEVEL_3800mV}) POWERON_BATTERY_LEVEL="6" ;; ${BATTERY_LEVEL_3850mV}) POWERON_BATTERY_LEVEL="7" ;; ${BATTERY_LEVEL_3900mV}) POWERON_BATTERY_LEVEL="8" ;; ${BATTERY_LEVEL_3950mV}) POWERON_BATTERY_LEVEL="9" ;; * ) POWERON_BATTERY_LEVEL="0" ;; esac if [ ${POWERON_BATTERY_LEVEL} -eq "0" ] then echo "Power on when battery charge condition detected.(default)" fi UPS_CMD_POWERON="@O${POWERON_BATTERY_LEVEL}#" UPS_CMD_STR=${UPS_CMD_POWERON} ups_cmd_send } #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/ #/* START Script */ #/*---------------------------------------------------------------------------*/ #/* find CH55xduino ttyACM node (1209:c550) */ #/*---------------------------------------------------------------------------*/ find_tty_node #/*---------------------------------------------------------------------------*/ #/* Script exit handling when node not found. */ #/*---------------------------------------------------------------------------*/ if [ -z "${UPS_TTY_NODE}" ]; then echo "------------------------------------------------------------" echo "Can't found ttyACM(CH55xduino) device. (1209:c550)" echo "------------------------------------------------------------" exit 1 else echo "------------------------------------------------------------" echo "Found ttyACM(CH55xduino) device. Node name = ${UPS_TTY_NODE}" echo "------------------------------------------------------------" fi #/*---------------------------------------------------------------------------*/ #/* Log status display */ #/*---------------------------------------------------------------------------*/ if [ -n "${UPS_TTY_LOG}" ]; then echo "------------------------------------------------------------" echo "Log Enable (${UPS_TTY_LOG})" echo "------------------------------------------------------------" echo "------------------------" >> ${UPS_TTY_LOG} echo "${CURRENT_TIME}, POWERON" >> ${UPS_TTY_LOG} fi #/*---------------------------------------------------------------------------*/ #/* Kill previously running processes(dead process). */ #/*---------------------------------------------------------------------------*/ kill_dead_process #/*---------------------------------------------------------------------------*/ #/* ttyACM Baudrate setup */ #/*---------------------------------------------------------------------------*/ stty -F ${UPS_TTY_NODE} 9600 raw -echo #/*---------------------------------------------------------------------------*/ #/* Set battery level for system power on */ #/*---------------------------------------------------------------------------*/ if [ -n "${CONFIG_UPS_ON_BATTERY_LEVEL}" ]; then ups_poweron_setup fi #/*---------------------------------------------------------------------------*/ #/* Main Loop (The script takes about 4-5 seconds to run once.) */ #/*---------------------------------------------------------------------------*/ while true do echo "------------------------------------------------------------" # Send command to read battery volt to UPS. UPS_CMD_STR=${UPS_CMD_BATTERY_VOLT} ups_cmd_send UPS_CMD_STR=${UPS_CMD_CHARGER_STATUS} ups_cmd_send #/* current date, time */ CURRENT_TIME=$(date) #/* Display UPS Status */ echo ${CURRENT_TIME} check_ups_status #/* Battery Log save */ if [ -n "${UPS_TTY_LOG}" ]; then echo "${CURRENT_TIME}, ${UPS_BATTERY_VOLT}" >> ${UPS_TTY_LOG} fi #/* Watchdog control */ if [ -n "${CONFIG_WATCHDOG_RESET_TIME}" ]; then watchdog_reset fi echo "------------------------------------------------------------" done #/*---------------------------------------------------------------------------*/ #/*---------------------------------------------------------------------------*/
Give execute permission to everybody with following command.
root@odroid:~# chmod a+x ./check_ups.sh
How to modify the script according to your usage scenario.
Default Scenario
- When power is supplied to the M1S_UPS, the M1S_UPS supplies power to the ODROID-M1S.
- When a power failure occurs, the control script issues a poweroff command to ODROID-M1S and sends a power off event to M1S_UPS.
- When M1S_UPS receives power off event from ODROID-M1S, M1S UPS enters sleep mode.
- When the power comes back on after a power outage, the M1S_UPS wakes up from sleep mode and supplies power to the ODROID-M1S.
Scenario1
- When the board is turned off when the battery voltage drops below battery level 2 (3650mV).
You can set the battery voltage at which the board turns off via the “CONFIG_POWEROFF_BATTERY_LEVEL=” variable in the M1S_UPS Control script.
#/*---------------------------------------------------------------------------*/ #/* Set battery level for system power off */ #/* BATERRY_LEVEL_FULL : Power off when battery discharge condition detected. */ #/*---------------------------------------------------------------------------*/ # CONFIG_POWEROFF_BATTERY_LEVEL=${BATTERY_LEVEL_FULL} CONFIG_POWEROFF_BATTERY_LEVEL=${BATTERY_LEVEL_3650mV}
Scenario2
- If you want the board to turn on only when the battery voltage is higher than battery level 2 (3650mV) when the power comes back on after a power outage.
You can set the battery voltage at which the board turns on via the “CONFIG_POWERON_BATTERY_LEVEL=” variable in the M1S_UPS Control script.
#/*---------------------------------------------------------------------------*/ #/* Set battery level for system power on */ #/* BATTERY_LEVEL_0mV : Power on when battery charge condition detected. */ #/*---------------------------------------------------------------------------*/ # CONFIG_POWERON_BATTERY_LEVEL=${BATTERY_LEVEL_0mV} CONFIG_POWERON_BATTERY_LEVEL=${BATTERY_LEVEL_3650mV}
Scenario3
- If you need to use Watchdog for system stability.
You can set the battery voltage at which the board turns on via the “CONFIG_UPS_WATCHDOG_TIME=” variable in the M1S_UPS Control script.
#/*---------------------------------------------------------------------------*/ #/* Set watchdog reset time */ # 0 : Disable.(default) # 1 ~ 9 : Watchdog reset time(sec) : Warnning # # WARNING: The watchdog reset value must be greater than the script execution time. # # The script takes about 4-5 seconds to run once. # #/*---------------------------------------------------------------------------*/ CONFIG_UPS_WATCHDOG_TIME=""
Warning :
If the watchdog reset value is not greater than the script execution time, the system reboots.
Log enable
- If you want to record ups battery log
The log file creation location can be set through the “UPS_TTY_LOG=” variable in the M1S_UPS control script.
#/*---------------------------------------------------------------------------*/ #/* battery log filename (default disable) */ #/* eg) UPS_TTY_LOG="/tmp/ttyUPS.log" */ #/*---------------------------------------------------------------------------*/ UPS_TTY_LOG=""
How to build and download
Required Ubuntu packages
root@odroid:~/m1s_ups# apt install wget unzip git vim libusb-1.0-0-dev build-essential usbtuils curl minicom
Using the Arduino IDE
Permission for Linux
By default, Linux will not expose enough permission for Arduino to upload the code with the USB bootloader.
Copy 99-ch55xbl.rules in this repo to /etc/udev/rules.d/ and restart your computer.
Otherwise, the upload tool may not find the bootloader device.
Using the Arduino CLI
arduino-cli install and environment setup
root@odroid:~# mkdir cli root@odroid:~/cli# cd cli root@odroid:~/cli# curl -fsSL https://raw.githubusercontent.com/arduino/arduino-cli/master/install.sh | sh root@odroid:~/cli# cp ./bin/arduino-cli /bin/ root@odroid:~/cli# arduino-cli config init
Add the ch55xduino board package url to the arduino-cli config file
root@odroid:~/cli# vi ~/.arduino15/arduino-cli.yaml additional_urls: - https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json
Download and copy the ch55xduino board package index file to the ~/.arduino-cli directory
root@odroid:~/cli# wget https://raw.githubusercontent.com/DeqingSun/ch55xduino/ch55xduino/package_ch55xduino_mcs51_index.json root@odroid:~/cli# cp ./package_ch55xduino_mcs51_index.json ~/.arduino15
Install the ch55xduino core and board package library
root@odroid:~/cli# arduino-cli core install arduino:avr CH55xDuino:mcs51
Download the source code file and unzip the compressed file
# download source code root@odroid:~/m1s_ups# wget https://wiki.odroid.com/_media/en/m1s_ups/ups_fw.zip root@odroid:~/m1s_ups# unzip ./ups_fw.zip root@odroid:~/m1s_ups# chmod 777 -R ./ups_fw
Source code compile and firmware update
# compile only root@odroid:~/m1s_ups# arduino-cli compile -b CH55xDuino:mcs51:ch552 ups_fw
# compile and firmware update root@odroid:~/m1s_ups# arduino-cli compile -b CH55xDuino:mcs51:ch552 ups_fw -u -p /dev/ttyACM0
# firmware update only root@odroid:~/m1s_ups# arduino-cli upload -b CH55xDuino:mcs51:ch552 -i ups_fw.hex -p /dev/ttyACM0