-
-
Save matt2005/ea07182227f43f83917a to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python2.7 | |
# script by Alex Eames http://RasPi.tv | |
# explained here... | |
# http://raspi.tv/2013/controlled-shutdown-duration-test-of-pi-model-a-with-2-cell-lipo | |
# DO NOT use this script without a Voltage divider or other means of | |
# reducing battery voltage to the ADC. This is exaplained on the above blog page | |
import time | |
import os | |
import subprocess | |
import smtplib | |
import string | |
import RPi.GPIO as GPIO | |
from time import gmtime, strftime | |
GPIO.setmode(GPIO.BCM) | |
################################################################################ | |
######################### Program Variables you MUST SET ####################### | |
# email variables | |
fromaddr = '[email protected]' | |
toaddr = 'destination email address' | |
# Googlemail login details | |
username = 'your googlemail/gmail username' | |
password = 'your googlemail/gmail password' | |
########## Program variables you might want to tweak ########################### | |
# voltage divider connected to channel 0 of mcp3002 | |
adcs = [0] # 0 battery voltage divider | |
reps = 10 # how many times to take each measurement for averaging | |
cutoff = 7.5 # cutoff voltage for the battery | |
previous_voltage = cutoff + 1 # initial value | |
time_between_readings = 60 # seconds between clusters of readings | |
# Define Pins/Ports | |
SPICLK = 8 # FOUR SPI ports on the ADC | |
SPIMISO = 23 | |
SPIMOSI = 24 | |
SPICS = 25 | |
####### You shouldn't need to change anything below here ####################### | |
################################################################################ | |
# read SPI data from MCP3002 chip, 2 possible adc's (0 & 1) | |
# this uses a bitbang method rather than Pi hardware spi | |
# modified code based on an adafruit example for mcp3008 | |
def readadc(adcnum, clockpin, mosipin, misopin, cspin): | |
if ((adcnum > 1) or (adcnum < 0)): | |
return -1 | |
if (adcnum == 0): | |
commandout = 0x6 | |
else: | |
commandout = 0x7 | |
GPIO.output(cspin, True) | |
GPIO.output(clockpin, False) # start clock low | |
GPIO.output(cspin, False) # bring CS low | |
commandout <<= 5 # we only need to send 3 bits here | |
for i in range(3): | |
if (commandout & 0x80): | |
GPIO.output(mosipin, True) | |
else: | |
GPIO.output(mosipin, False) | |
commandout <<= 1 | |
GPIO.output(clockpin, True) | |
GPIO.output(clockpin, False) | |
adcout = 0 | |
# read in one empty bit, one null bit and 10 ADC bits | |
for i in range(12): | |
GPIO.output(clockpin, True) | |
GPIO.output(clockpin, False) | |
adcout <<= 1 | |
if (GPIO.input(misopin)): | |
adcout |= 0x1 | |
GPIO.output(cspin, True) | |
adcout /= 2 # first bit is 'null' so drop it | |
return adcout | |
# this function creates and logs to a file called battery_log.txt | |
# you can change the name if you want, but you'll have to change line 98 as well | |
def write_log(logline): | |
logfile = open('battery_log.txt', 'a') | |
logfile.write(logline + '\n') | |
logfile.close() | |
# you can edit the text for the email to suit your requirements | |
def send_email(): | |
BODY = string.join(( | |
"From: %s" % fromaddr, | |
"To: %s" % toaddr, | |
"Subject: Shutting down the model A now", | |
"", | |
"Your battery voltage was just measured at or below threshold.", | |
"If it happens twice in a row, we shut down.", | |
), "\r\n") | |
# send the email | |
server = smtplib.SMTP('smtp.gmail.com:587') | |
server.starttls() | |
server.login(username,password) | |
server.sendmail(fromaddr, toaddr, BODY) | |
server.quit() | |
#Set up ports | |
GPIO.setup(SPIMOSI, GPIO.OUT) # set up the SPI interface pins | |
GPIO.setup(SPIMISO, GPIO.IN) | |
GPIO.setup(SPICLK, GPIO.OUT) | |
GPIO.setup(SPICS, GPIO.OUT) | |
# create log file | |
item = 'Battery log data' | |
logfile = open('battery_log.txt', 'w') | |
logfile.write(item + '\n') | |
logfile.close() | |
try: | |
while True: | |
for adcnum in adcs: | |
# read the analog pin | |
adctot = 0 | |
for i in range(reps): | |
read_adc = readadc(adcnum, SPICLK, SPIMOSI, SPIMISO, SPICS) | |
adctot += read_adc | |
time.sleep(0.05) | |
read_adc = adctot / reps / 1.0 | |
print read_adc | |
# convert analog reading to Volts = ADC * ( 3.33 / 1024 ) | |
# 3.33 tweak according to the 3v3 measurement on the Pi | |
volts = read_adc * ( 3.33 / 1024.0) * 2.837 | |
voltstring = str(volts)[0:5] | |
print "Battery Voltage: %.2f" % volts | |
# now we need to log the time and voltage in the log file | |
logline = str(strftime("%Y-%m-%d %H:%M:%S", gmtime())) | |
logline += ', ' | |
logline += voltstring | |
print "adding %s to log file" % logline | |
write_log(logline) | |
# put safeguards in here so that it takes 2 or 3 successive readings | |
if volts <= cutoff: | |
# get it to send you an email at this point before full cutoff | |
try: | |
send_email() | |
print "email sent" | |
except: | |
print "email failed" | |
if previous_voltage <= cutoff: | |
logline = 'Shutting down due to low V at ' | |
logline += str(strftime("%Y-%m-%d %H:%M:%S", gmtime())) | |
write_log(logline) | |
# initiate shutdown process | |
print "OK. Syncing file system, then we're shutting down." | |
command = os.system("sync") | |
command = 0 | |
if command == 0: | |
print "we're shutting down now" | |
command = "/usr/bin/sudo /sbin/shutdown -h now" | |
process = subprocess.Popen(command.split(), stdout=subprocess.PIPE) | |
output = process.communicate()[0] | |
print output | |
previous_voltage = volts | |
time.sleep(time_between_readings) | |
except KeyboardInterrupt: # trap a CTRL+C keyboard interrupt | |
GPIO.cleanup() | |
time.sleep(5) | |
GPIO.cleanup() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment