Skip to content

Commit

Permalink
Update ups.py
Browse files Browse the repository at this point in the history
  • Loading branch information
tjohn327 authored Aug 12, 2020
1 parent 45ec1c3 commit 0bbaa30
Showing 1 changed file with 51 additions and 137 deletions.
188 changes: 51 additions & 137 deletions src/ups.py
Original file line number Diff line number Diff line change
@@ -1,159 +1,73 @@
#!/usr/bin/python

import smbus
import time
import os, sys
import logging
import socket
import json
import signal
import RPi.GPIO as GPIO
from powerpi import Powerpi

logging.basicConfig(level=logging.DEBUG)

bus = smbus.SMBus(1) # 1 = /dev/i2c-1 (port I2C1)
ADDRESS = 0x6a #I2C address of the ups
#Refer to http://www.ti.com/lit/ds/symlink/bq25895.pdf for register maps

### Initialization ###############################################
REG_WATCHDOG = 0x07
BYTE_WATCHDOG_STOP = 0b10001101 #Stop Watchdog timer
REG_ILIM = 0x00 #ILIM register
BYTE_ILIM = 0b01101000 #2A input current limit
REG_ICHG = 0x04
BYTE_ICHG = 0b00001000 #.5A charging current limit
REG_CONV_ADC = 0x02
REG_BATFET = 0x09
BYTE_BATFET = 0b01001000 #delay before battery is disconnected

try:
bus.write_byte_data(ADDRESS, REG_WATCHDOG, BYTE_WATCHDOG_STOP)
bus.write_byte_data(ADDRESS, REG_ILIM, BYTE_ILIM)
bus.write_byte_data(ADDRESS, REG_ICHG, BYTE_ICHG)
bus.write_byte_data(ADDRESS, REG_BATFET, BYTE_BATFET)
logging.info("UPS initialized")
except:
logging.error("Initialization failed, check connection to the UPS!")
sys.exit(1)
###################################################################


BAT_CAPACITY = 2900 #Battery capacity in mah
CURRENT_DRAW = 2000 #Current draw in mah
REG_CONV_ADC = 0x02
BYTE_CONV_ADC_START = 0b10011101
BYTE_CONV_ADC_STOP = 0b00011101
REG_BATFET_DIS = 0x09
BYTE_BATFET_DIS = 0b01101000
REG_STATUS = 0x0B #address of status register
REG_BATV = 0x0e
REG_FAULT = 0x0c
logging.basicConfig(level=logging.INFO)

GPIO4_AVAILABLE = True
ENABLE_UDP = True
UDP_PORT = 40001
serverAddressPort = ("127.0.0.1", UDP_PORT)
UDPClientSocket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM)
disconnectflag = False
shutdowncmd = 'sudo shutdown -H '
cancelshutdowncmd = 'sudo shutdown -c'
batpercentprev = 0
SLEEPDELAY = 10

ppi = Powerpi()

def int_to_bool_list(num):
return [bool(num & (1<<n)) for n in range(8)]


def 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

def read_status():
global SLEEPDELAY
global disconnectflag
global batpercentprev
try:
bus.write_byte_data(ADDRESS, REG_CONV_ADC, BYTE_CONV_ADC_START)
sample = bus.read_byte_data(ADDRESS, REG_STATUS)
status = int_to_bool_list(sample)
time.sleep(1.2)
sample = bus.read_byte_data(ADDRESS, REG_BATV)
batvbool = int_to_bool_list(sample)
bus.write_byte_data(ADDRESS, REG_CONV_ADC, BYTE_CONV_ADC_STOP)
def read_status(clear_fault=False):
global disconnectflag, ENABLE_UDP
err, status = ppi.read_status(clear_fault)

except :
logging.error("An exception occured while reading values from the UPS!")

else :
if status[2]:
power = "Connected"
else:
power = "Not Connected"

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 = "Not Charging"

#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
if err:
time.sleep(1)
return

batpercent = translate(batv,3.4,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 == "Not Connected" and disconnectflag == False :
if status["PowerInputStatus"] == "Not Connected" and disconnectflag == False :
disconnectflag = True
message = "echo Power Disconnected, system will shutdown in %d minutes! | wall" % (timeleftmin)
message = "echo Power Disconnected, system will shutdown in %d minutes! | wall" % (status['TimeRemaining'])
os.system(message)

if power == "Connected" and disconnectflag == True :
if status["PowerInputStatus"] == "Connected" and disconnectflag == True :
disconnectflag = False
message = "echo Power Restored, battery at %d percent | wall" % (batpercentprev * 100)
message = "echo Power Restored, battery at %d percent | wall" % (status['BatteryPercentage'])
os.system(message)

batpercentprev = batpercent

data = {
'PowerInput': power,
'ChargeStatus' : charge,
'BatteryVoltage' : '%.2f'%batv,
"BatteryPercentage" : int(batpercent*100),
'TimeRemaining' : int(timeleftmin)
}

logging.debug(data)

if(batv < 3.4):
bus.write_byte_data(ADDRESS, REG_BATFET_DIS, BYTE_BATFET_DIS)
os.system('sudo shutdown -H now')
if ENABLE_UDP:
try:
UDPClientSocket.sendto(json.dumps(status), serverAddressPort)
except Exception as ex:
logging.error(ex)

logging.debug(status)

if(status['BatteryVoltage'] < 3.2):
ppi.bat_disconnect()
os.system('sudo shutdown now')

def interrupt_handler(channel):
read_status()

read_status()
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(4, GPIO.FALLING, callback=interrupt_handler, bouncetime=200)
read_status(True)

def main():
if ppi.initialize():
sys.exit(1)

if GPIO4_AVAILABLE:
try:
GPIO.setmode(GPIO.BCM)
GPIO.setup(4, GPIO.IN, pull_up_down=GPIO.PUD_UP)
GPIO.add_event_detect(4, GPIO.FALLING, callback=interrupt_handler, bouncetime=200)
except Exception as ex:
logging.error("Error attaching interrupt to GPIO4, UPS will work without interrupt.")

while (True):
read_status()

while (True):
time.sleep(SLEEPDELAY)
read_status()

if __name__=="__main__":
main()

0 comments on commit 0bbaa30

Please sign in to comment.