Table of Contents

FOSS Data-Logging for Junsi iCharger

Batteries in general and lithium based batteries in particular require special attention, when it comes to charging and balancing. For this reason, the lab has a Junsi iCharger 1010B+, which offers a complete battery management solution for virtually every battery technology out there and some non-battery related features as well (like DC-Motor burn-in and foam-cutting programs).

Junsi iCharger 1010B+

It has proved itself as reliable hardware for over a year, especially taking care of the custom made LiPo battery packs for the orion. It even offers a USB port for software updates and data-logging. Unfortunetaly, until now, only LogView users could get the logging data, but that would require a closed-source non-free operating system to run, which isn't available here (see Apollo-NG's Code of Conduct). Additionally, while LogView itself may be free (as in free beer), it doesn't seem to be open-source, so another solution was due…

Luckily, the USB port is actually just a serial port based on the cp210x serial to USB converter. Remember to build and load the kernel module, it should look like this, when you plug-in the iCharger:

[2865177.518351] usb 1-6.2: new full-speed USB device number 60 using ehci_hcd
[2865177.604715] usb 1-6.2: New USB device found, idVendor=10c4, idProduct=ea60
[2865177.604720] usb 1-6.2: New USB device strings: Mfr=1, Product=2, SerialNumber=3
[2865177.604723] usb 1-6.2: Product: Junsi iCharger 1010B+
[2865177.604726] usb 1-6.2: Manufacturer: Silicon Labs
[2865177.604728] usb 1-6.2: SerialNumber: 0906102520
[2865177.605380] cp210x 1-6.2:1.0: cp210x converter detected
[2865177.668344] usb 1-6.2: reset full-speed USB device number 60 using ehci_hcd
[2865177.753915] usb 1-6.2: cp210x converter now attached to ttyUSB0

Python Code

The following code will read, translate and calculate all vital battery and voltage/current data. It was written in Python, since it's always inherently available on Gentoo systems, but should be easily adaptable into any other language. A node.js implementation with realtime web(socket) graphs would be interesting, to make it even possible to remote-monitor the process.

#!/usr/bin/env python
# -*- coding: utf-8 -*-
#
########################################################################
#
#   This program is free software: you can redistribute it and/or modify
#   it under the terms of the GNU General Public License as published by
#   the Free Software Foundation, either version 3 of the License, or
#   (at your option) any later version.
#
#   This program is distributed in the hope that it will be useful,
#   but WITHOUT ANY WARRANTY; without even the implied warranty of
#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#   GNU General Public License for more details.
#
#   You should have received a copy of the GNU General Public License
#   along with this program. If not, see <http://www.gnu.org/licenses/>.
#
########################################################################

import os, sys
import time
import serial

# discharge end voltage (empty)

dchg_end = 3.2


# iCharger modes of operation
mop=[None]*13

mop[1]  = "Charging"
mop[2]  = "Discharging"
mop[3]  = "Monitor"
mop[4]  = "Waiting"
mop[5]  = "Motor burn-in"
mop[6]  = "Finished"
mop[7]  = "Error"
mop[8]  = "LIxx trickle"
mop[9]  = "NIxx trickle"
mop[10] = "Foam cut"
mop[11] = "Info"
mop[12] = "External-discharging"

# configure the serial connections 
# change according to the ttyUSB assigned to the iCharger (dmesg)

ser = serial.Serial(
    port='/dev/ttyUSB0',
)

ser.open()
ser.isOpen()

### MAIN #############################################################

while 1 :

	line 	= ser.readline	()
	raw 	= line.split	(';')

	v_bat 	= float			(raw[4])/1000
	v_c1  	= float			(raw[6])/1000
	v_c2  	= float			(raw[7])/1000
	v_c3  	= float			(raw[8])/1000
	v_in  	= float			(raw[3])/1000
	i_chg 	= int			(raw[5])*10
	i_sum 	= float			(raw[18])/1000
	t_int 	= float			(raw[16])/10
	t_ext 	= float			(raw[17])/10

	s_vc1 	= ((float		(raw[6])/1000)-dchg_end)*100
	s_vc2 	= ((float		(raw[7])/1000)-dchg_end)*100
	s_vc3 	= ((float		(raw[8])/1000)-dchg_end)*100
	s_bat 	= round			((((float(raw[4])/1000)
		    -   			(dchg_end*3))*100/3), 1)

	print "Mode:           " + mop[int(raw[1])]
	print "Batt:           " + str(v_bat) + " V (" + str(s_bat) + "%)"
	print "Cell 1:         " + str(v_c1) + " V (" + str(s_vc1) + "%)"
	print "Cell 2:         " + str(v_c2) + " V (" + str(s_vc2) + "%)"
	print "Cell 3:         " + str(v_c3) + " V (" + str(s_vc3) + "%)"
	print "Supply:         " + str(v_in) + " V"
	print "Charge Current: " + str(i_chg) + " mA"
	print "Charge Amount:  " + str(i_sum) + " A"
	print "Temp INT:       " + str(t_int) + " °C"
	print "Temp EXT:       " + str(t_ext) + " °C"
	print ">>" + line


It only requires the pyserial package, on gentoo you can just:

$ emerge -av pyserial

To run the application, make sure your user has permission to read the ttyUSB device and run:

$ python pycharger.py

There was not enough time to come up with a fancy pygtk or any other graphical implementation to show the data in real-time on a graph. Since the basic code, the data-mapping and the calculations are done and released under GPL3+ now, maybe someone else can step-in and extend the features to have realtime graphs :)

Examples

Monitoring Mode

The following example shows the data-log output of pycharger.py, with the iCharger in monitoring mode. The battery is one of orion battery packs, after half a night of recording:

Mode:           Monitor
Batt:           12.199 V (86.6%)
Cell 1:         4.064 V (86.4%)
Cell 2:         4.072 V (87.2%)
Cell 3:         4.067 V (86.7%)
Supply:         12.315 V
Charge Current: 0 mA
Charge Amount:  0.0 A
Temp INT:       34.3 °C
Temp EXT:       22.3 °C
>>$1;3;;12315;12199;0;4064;4072;4067;0;0;0;0;0;0;0;343;223;0;46

Mode:           Monitor
Batt:           12.199 V (86.6%)
Cell 1:         4.065 V (86.5%)
Cell 2:         4.071 V (87.1%)
Cell 3:         4.068 V (86.8%)
Supply:         12.328 V
Charge Current: 0 mA
Charge Amount:  0.0 A
Temp INT:       33.8 °C
Temp EXT:       22.5 °C
>>$1;3;;12328;12199;0;4065;4071;4068;0;0;0;0;0;0;0;338;225;0;39

Mode:           Monitor
Batt:           12.199 V (86.6%)
Cell 1:         4.064 V (86.4%)
Cell 2:         4.071 V (87.1%)
Cell 3:         4.067 V (86.7%)
Supply:         12.315 V
Charge Current: 0 mA
Charge Amount:  0.0 A
Temp INT:       33.8 °C
Temp EXT:       22.2 °C
>>$1;3;;12315;12199;0;4064;4071;4067;0;0;0;0;0;0;0;338;222;0;32

Charging

The same battery pack, at the end of a charge cycle, in the final balancing phase:

Mode:           Charging
Batt:           12.618 V (100.6%)
Cell 1:         4.2 V (100.0%)
Cell 2:         4.205 V (100.5%)
Cell 3:         4.205 V (100.5%)
Supply:         12.362 V
Charge Current: 180 mA
Charge Amount:  0.725 A
Temp INT:       40.0 °C
Temp EXT:       26.7 °C
>>$1;1;;12362;12618;18;4200;4205;4205;0;0;0;0;0;0;0;400;267;725;31

Mode:           Charging
Batt:           12.599 V (100.0%)
Cell 1:         4.2 V (100.0%)
Cell 2:         4.205 V (100.5%)
Cell 3:         4.205 V (100.5%)
Supply:         12.315 V
Charge Current: 180 mA
Charge Amount:  0.725 A
Temp INT:       39.7 °C
Temp EXT:       26.6 °C
>>$1;1;;12315;12599;18;4200;4205;4205;0;0;0;0;0;0;0;397;266;725;29

Mode:           Charging
Batt:           12.579 V (99.3%)
Cell 1:         4.194 V (99.4%)
Cell 2:         4.205 V (100.5%)
Cell 3:         4.204 V (100.4%)
Supply:         12.315 V
Charge Current: 170 mA
Charge Amount:  0.725 A
Temp INT:       39.7 °C
Temp EXT:       26.6 °C
>>$1;1;;12315;12579;17;4194;4205;4204;0;0;0;0;0;0;0;397;266;725;19


Although the code could only be tested with the 1010B+ here, it is likely to be compatible to all sister models. If you have a different Junsi model and are able to test the code, please be so kind and leave some feedback for other people, who also look for free and open-source data logging alternatives.

If you're looking for a cheap grid power supply to drive the charger, any old PC AT or ATX power supply will do, since the charger itself is nothing else but a versatile buck/boost converter, regulated by a micro controller and assisted by a battery of balancing resistors. The 12V output of a 300W ATX supply is being used here.