Skip to content

Instantly share code, notes, and snippets.

@frankgould
Created August 25, 2020 14:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frankgould/3613f3d17ed24c02058a303f55f46a95 to your computer and use it in GitHub Desktop.
Save frankgould/3613f3d17ed24c02058a303f55f46a95 to your computer and use it in GitHub Desktop.
Geekworm UPS3 RPi HAT Modified Example Code
import os, smbus, time, logging, atexit
from datetime import datetime
log_file = '/home/rover_logs/rover-battery-log-' + datetime.now().strftime('%m-%d-%y') + '.txt'
logging.basicConfig(filename=log_file,level=logging.DEBUG)
logging.info('==================== Rover UPS3 Battery Capacity Communications Client Logging Started ' + datetime.now().strftime('%m-%d-%y %H:%M:%S'))
BYTE_CONV_ADC_START = 0b10011101
BYTE_CONV_ADC_STOP = 0b00011101
BYTE_WATCHDOG_STOP = 0b10001101 #Stop Watchdog timer
MAX17048_ADDR = 0x36
BQ25895_ADDRESS = 0x6A
REG_WATCHDOG = 0x07
REG_ILIM = 0x00 #ILIM register
BYTE_ILIM = 0b01111111 #3.25A input current limit
REG_ICHG = 0x04
BYTE_ICHG = 0b01111111 #.5A charging current limit
REG_BATFET = 0x09
BYTE_BATFET = 0b01001000 #delay before battery == disconnected
REG_CONV_ADC = 0x02
REG_STATUS = 0x0B #address of status register
REG_BATV = 0x0e
BAT_CAPACITY = 2500 #Battery capacity in mah
CURRENT_DRAW = 2000 #Current draw in mah
disconnectflag = False
POWEROFF_POWER = 5
count = 0
def shutdown(*kwarg):
logging.info('Shutdown occurred, shutting RPi down now at ' + str(datetime.now().strftime('%H:%M:%S')) + '.')
atexit.register(shutdown)
def bq25895_int_to_bool_list(num):
return [bool(num & (1<<n)) for n in range(8)]
def bq25895_translate(val, in_from, in_to, out_from, out_to):
out_range = out_to - out_from
in_range = in_to - in_from
in_val = val - in_from
val=(float(in_val)/in_range)*out_range
out_val = out_from+val
return out_val
# Get voltage from max17048
def max17048_getstatus():
global max17048_v, max17048_soc
max17048_v_16 = bus.read_word_data(MAX17048_ADDR, 0x02);
soc = bus.read_word_data(MAX17048_ADDR, 0x04);
max17048_v = (((max17048_v_16 & 0x00FF) << 8) + (max17048_v_16 >> 8)) * 78.125 / 1000000
max17048_soc = (((soc & 0x00FF) << 8) + (soc >> 8)) / 256
bus = smbus.SMBus(1)
bus.write_word_data(MAX17048_ADDR, 0xFE ,0xFFFF)
bus.write_byte_data(BQ25895_ADDRESS, REG_WATCHDOG, BYTE_WATCHDOG_STOP)
bus.write_byte_data(BQ25895_ADDRESS, REG_ILIM, BYTE_ILIM)
bus.write_byte_data(BQ25895_ADDRESS, REG_ICHG, BYTE_ICHG)
bus.write_byte_data(BQ25895_ADDRESS, REG_BATFET, BYTE_BATFET)
# BQ25895 read status
def bq25895_read_status():
global disconnectflag, bq25895_status
bus.write_byte_data(BQ25895_ADDRESS, REG_CONV_ADC, BYTE_CONV_ADC_START)
sample = bus.read_byte_data(BQ25895_ADDRESS, REG_STATUS)
status = bq25895_int_to_bool_list(sample)
time.sleep(1.2)
sample = bus.read_byte_data(BQ25895_ADDRESS, REG_BATV)
batvbool = bq25895_int_to_bool_list(sample)
bus.write_byte_data(BQ25895_ADDRESS, REG_CONV_ADC, BYTE_CONV_ADC_STOP)
vsys_stat = status[0]
sdp_stat = status[1]
pg_stat = status[2]
chrg_stat = status[4] * 2 + status[3]
vbus_stat = status[7] * 4 + status[6] * 2 + status[5]
if status[2]:
power = "Connected"
else:
power = "Disconnected"
if status[3] and status[4]:
charge = "Charging done"
elif status[4] and not status[3]:
charge = "Charging"
elif not status[4] and status[3]:
charge = "Pre-Charge"
else:
charge = "Discharging"
#convert batv register to volts
batv = 2.304
batv += batvbool[6] * 1.280
batv += batvbool[5] * 0.640
batv += batvbool[4] * 0.320
batv += batvbool[3] * 0.160
batv += batvbool[2] * 0.08
batv += batvbool[1] * 0.04
batv += batvbool[0] * 0.02
batpercent = bq25895_translate(batv,3.5,4.184,0,1)
if batpercent<0 :
batpercent = 0
elif batpercent >1 :
batpercent = 1
timeleftmin = int( batpercent * 60* BAT_CAPACITY / CURRENT_DRAW)
if timeleftmin < 0 :
timeleftmin = 0
if power == "Connected" :
timeleftmin = -1
if power == "Disconnected" and disconnectflag == False :
disconnectflag = True
message = "***** Battery at " + str(int(batpercent * 100)) + "%. Power Disconnected, system will shutdown in " + str((timeleftmin)) + " minutes!"
print(message)
logging.info(message)
if power == "Connected" and disconnectflag == True :
disconnectflag = False
message = "***** Power Restored, battery at " + str(int(batpercent * 100)) + "%."
print(message)
logging.info(message)
bq25895_status = {
'Input': power,
'ChargeStatus' : charge,
'BatteryVoltage' : '%.2f' % batv,
"BatteryPercentage" : int(batpercent*100),
'TimeRemaining' : int(timeleftmin)
}
if(batv < 3.5):
bus.write_byte_data(BQ25895_ADDRESS, REG_BATFET_DIS, BYTE_BATFET_DIS)
max17048_getstatus()
bq25895_read_status()
print ("Input: " , bq25895_status['Input'])
print ("State: " , bq25895_status['ChargeStatus'])
print ("Voltage: " , bq25895_status['BatteryVoltage'])
print ("Capacity: " + str(bq25895_status['BatteryPercentage']) + "%")
print ("max17048_soc: " + str(max17048_soc))
try:
while (True):
max17048_getstatus()
bq25895_read_status()
if ((bq25895_status['Input'] != 'Connected') and (max17048_soc < POWEROFF_POWER)):
count += 1
message = "**** Shutting down in " + str(50-(count*5)) + " seconds. Value max17048_soc = " + str(max17048_soc) + " *****"
print(message)
logging.info(message)
if count == 10:
os.system("sudo halt -h")
if str(bq25895_status['Input']) == 'Connected':
message = str(datetime.now().strftime('%H:%M:%S')) + " - Input: " + str(bq25895_status['Input']) + ", State: " + str(bq25895_status['ChargeStatus']) + ", Voltage: " + str(bq25895_status['BatteryVoltage']) + ", Capacity: " + str(bq25895_status['BatteryPercentage']) + "%. Value max17048_soc = " + str(max17048_soc)
else:
message = str(datetime.now().strftime('%H:%M:%S')) + " - Input: " + str(bq25895_status['Input']) + ", State: " + str(bq25895_status['ChargeStatus']) + ", Voltage: " + str(bq25895_status['BatteryVoltage']) + ", max17048_soc: " + str(max17048_soc) + ", TimeRemaining: " + str(bq25895_status['TimeRemaining']) + " minutes."
print (message)
logging.info(message)
time.sleep(5)
except Exception as err:
message = 'Exception error: ' + str(err)
print (message)
logging.info(message)
exit
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment