Hello! Here are some images of the new grow setup:
and here is the working version of the code:
import time
from time import sleep
from time import strftime
import tweepy
consumer_key=""
consumer_secret=""
access_token=""
access_token_secret=""
auth = tweepy.OAuthHandler(consumer_key, consumer_secret)
auth.set_access_token(access_token, access_token_secret)
api = tweepy.API(auth)
PiPlanter_Full = False
import logging
logging.basicConfig()
from apscheduler.scheduler import Scheduler
import os
import sys
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BOARD)
# Start of mysql setup
import MySQLdb
user = MySQLdb.connect(host="localhost",user="root",passwd="")
cursor = user.cursor()
MySQLdb_Name = 'PiPlanter' + strftime("_%m_%d_%Y_%I_%M_%S%p")
mysql_table_name = MySQLdb_Name + '_table'
mysql_create = 'CREATE DATABASE IF NOT EXISTS PiPlanter'
mysql_grant = "GRANT ALL ON `" + MySQLdb_Name + "`.* TO 'piplanter'@'localhost' IDENTIFIED BY 'password'"
mysql_use = 'USE PiPlanter'
if PiPlanter_Full == True:
#Full PiPlanter
mysql_table = "CREATE TABLE " + mysql_table_name + "(Sample_Number INT NOT NULL AUTO_INCREMENT PRIMARY KEY,Time VARCHAR(100),P_TMP0 VARCHAR(100),P_MST0 VARCHAR(100),P_TMP1 VARCHAR(100),P_MST1 VARCHAR(100),P_TMP2 VARCHAR(100),P_MST2 VARCHAR(100),P_TMP3 VARCHAR(100),P_MST3 VARCHAR(100),A_TMP0 VARCHAR(100),A_LDR0 VARCHAR(100),A_LDR1 VARCHAR(100),A_MST0 VARCHAR(100))"
else:
#Simple PiPlanter
mysql_table = "CREATE TABLE " + mysql_table_name + "(Sample_Number INT NOT NULL AUTO_INCREMENT PRIMARY KEY,Time VARCHAR(100),P_MST0 VARCHAR(100),P_MST1 VARCHAR(100),A_TMP0 VARCHAR(100),A_LDR0 VARCHAR(100))"
#A new database must be created each time the program runs
cursor.execute(mysql_create)
cursor.execute(mysql_grant)
cursor.execute(mysql_use)
cursor.execute(mysql_table)
pins = {'MST_Enable' : 8} #assign names to GPIO pins
for d in pins.itervalues():
GPIO.setup(d,GPIO.OUT)
#first ADC setup on SPI port 1
import spidev
spi_1 = spidev.SpiDev()
spi_1.open(0, 1)
#first ADC setup on SPI port 0
import spidev
spi_0 = spidev.SpiDev()
spi_0.open(0, 0)
#this function can be used to find out the ADC value on ADC 0
def readadc_0(adcnum_0):
if adcnum_0 > 7 or adcnum_0 < 0:
return -1
r_0 = spi_0.xfer2([1, 8 + adcnum_0 << 4, 0])
adcout_0 = ((r_0[1] & 3) << 8) + r_0[2]
return adcout_0
#this function can be used to find out the ADC value on ADC 1
def readadc_1(adcnum_1):
if adcnum_1 > 7 or adcnum_1 < 0:
return -1
r_1 = spi_1.xfer2([1, 8 + adcnum_1 << 4, 0])
adcout_1 = ((r_1[1] & 3) << 8) + r_1[2]
return adcout_1
#this function converts a given value from the ADC and turns it into usable data
def convertadc(adcinput,unit):
millivolts = adcinput*(3300.0/1024.0) #converts the ADC value to milivolts
temp_c = ((millivolts - 100.0)/10)-40.0
percent = (adcinput/1024.0)*100
if unit == 'c' : #used for a temperature sensor to return Celsius
return temp_c
elif unit == 'f' : #used for a temperature sensor to return Fahrenheit
temp_f = (temp_c * 9.0 / 5.0) + 32
return temp_f
elif unit == 'mV':
return millivolts
elif unit == '%':
return percent
else:
print "convertadc input error"
return 0
#returns a usable numerical value from the ADC
def pollsensor(sensor,unit,precision,samples):
GPIO.output(pins['MST_Enable'], True)
if PiPlanter_Full == True:
#Full PiPlanter
sensors = {\
'P_TMP0' : convertadc(readadc_0(0),unit),\
'P_MST0' : convertadc(readadc_0(1),unit),\
'P_TMP1' : convertadc(readadc_0(2),unit),\
'P_MST1' : convertadc(readadc_0(3),unit),\
'P_TMP2' : convertadc(readadc_0(4),unit),\
'P_MST2' : convertadc(readadc_0(5),unit),\
'P_TMP3' : convertadc(readadc_0(6),unit),\
'P_MST3' : convertadc(readadc_0(7),unit),\
'A_TMP0' : convertadc(readadc_1(0),unit),\
'A_LDR0' : convertadc(readadc_1(1),unit),\
'A_LDR1' : convertadc(readadc_1(2),unit),\
'A_MST0' : convertadc(readadc_1(3),unit)}
else:
#Simple PiPlanter
sensors = {\
'P_MST0' : convertadc(readadc_0(0),unit),\
'P_MST1' : convertadc(readadc_0(1),unit),\
'A_TMP0' : convertadc(readadc_0(2),unit),\
'A_LDR0' : convertadc(readadc_0(3),unit)}
outputsum = 0
for x in range(0,samples): #An averaging algorithm that creates a more precise reading
outputsum = outputsum + sensors[sensor]
output = round(outputsum/samples, precision)
GPIO.output(pins['MST_Enable'], False)
return output
#samples all sensors, outputs different formats of the data to be used in other places in the program
def sampleallsensors(sensor_precision,sensor_samples,form):
if PiPlanter_Full == True:
#Full PiPlanter
current_sensors = {\
'P_TMP0' : pollsensor('P_TMP0' , 'f', sensor_precision, sensor_samples),\
'P_MST0' : pollsensor('P_MST0' , '%', sensor_precision, sensor_samples),\
'P_TMP1' : pollsensor('P_TMP1' , 'f', sensor_precision, sensor_samples),\
'P_MST1' : pollsensor('P_MST1' , '%', sensor_precision, sensor_samples),\
'P_TMP2' : pollsensor('P_TMP2' , 'f', sensor_precision, sensor_samples),\
'P_MST2' : pollsensor('P_MST2' , '%', sensor_precision, sensor_samples),\
'P_TMP3' : pollsensor('P_TMP3' , 'f', sensor_precision, sensor_samples),\
'P_MST3' : pollsensor('P_MST3' , '%', sensor_precision, sensor_samples),\
'A_TMP0' : pollsensor('A_TMP0' , 'f', sensor_precision, sensor_samples),\
'A_LDR0' : pollsensor('A_LDR0' , '%', sensor_precision, sensor_samples),\
'A_LDR1' : pollsensor('A_LDR1' , '%', sensor_precision, sensor_samples),\
'A_MST0' : pollsensor('A_MST0' , '%', sensor_precision, sensor_samples)}
else:
#Simple PiPlanter
current_sensors = {\
'P_MST0' : pollsensor('P_MST0' , '%', sensor_precision, sensor_samples),\
'P_MST1' : pollsensor('P_MST1' , '%', sensor_precision, sensor_samples),\
'A_TMP0' : pollsensor('A_TMP0' , 'f', sensor_precision, sensor_samples),\
'A_LDR0' : pollsensor('A_LDR0' , '%', sensor_precision, sensor_samples)}
if form == 'MySQL':
if PiPlanter_Full == True:
#Full PiPlanter
output = "INSERT INTO " + mysql_table_name + "(Time, P_TMP0, P_MST0, P_TMP1, P_MST1, P_TMP2, P_MST2, P_TMP3, P_MST3, A_TMP0, A_LDR0, A_LDR1, A_MST0)" + " VALUES(NOW()" + "," + str(current_sensors['P_TMP0']) + "," + str(current_sensors['P_MST0']) + "," + str(current_sensors['P_TMP1']) + "," + str(current_sensors['P_MST1']) + "," + str(current_sensors['P_TMP2']) + "," + str(current_sensors['P_MST2']) + "," + str(current_sensors['P_TMP3']) + "," + str(current_sensors['P_MST3']) + "," + str(current_sensors['A_TMP0']) + "," + str(current_sensors['A_LDR0']) + "," + str(current_sensors['A_LDR1']) + "," + str(current_sensors['A_MST0']) + ")"
else:
#Simple PiPlanter
output = "INSERT INTO " + mysql_table_name + "(Time, P_MST0, P_MST1, A_TMP0, A_LDR0)" + " VALUES(NOW()" + "," + str(current_sensors['P_MST0']) + "," + str(current_sensors['P_MST1']) + "," + str(current_sensors['A_TMP0']) + "," + str(current_sensors['A_LDR0']) + ")"
elif form == 'Console':
if PiPlanter_Full == True:
#Full PiPlanter
output = 'Debug Update:' + ' P_TMP0: ' + str(str(current_sensors['P_TMP0'])) + ',' + ' P_MST0: ' + str(str(current_sensors['P_MST0'])) + ',' + ' P_TMP1: ' + str(str(current_sensors['P_TMP1'])) + ',' + ' P_MST1: ' + str(str(current_sensors['P_MST1'])) + ','+ ' P_TMP2: ' + str(str(current_sensors['P_TMP2'])) + ','+ ' P_MST2: ' + str(str(current_sensors['P_MST2'])) + ','+ ' P_TMP3: ' + str(str(current_sensors['P_TMP3'])) + ','+ ' P_MST3: ' + str(str(current_sensors['P_MST3'])) + ',' + ' A_TMP0: ' + str(str(current_sensors['A_TMP0'])) + ',' + ' A_LDR0: ' + str(str(current_sensors['A_LDR0'])) + ','+ ' A_LDR1: ' + str(str(current_sensors['A_LDR1'])) + ','+ ' A_MST0: ' + str(str(current_sensors['A_MST0']))
else:
#Simple PiPlanter
output = 'Debug Update:' + ' P_MST0: ' + str(str(current_sensors['P_MST0'])) + ',' + ' P_MST1: ' + str(str(current_sensors['P_MST1'])) + ',' + ' A_TMP0: ' + str(str(current_sensors['A_TMP0'])) + ',' + ' A_LDR0: ' + str(str(current_sensors['A_LDR0']))
elif form == 'Twitter':
if PiPlanter_Full == True:
#Full PiPlanter
output = 'Ambient LDR: ' + str(round(((current_sensors['A_LDR0'] + current_sensors['A_LDR1'])/2),1) ) + '%, ' + 'Ambient Tmp: ' + str(round(current_sensors['A_TMP0'],1)) + 'DF, ' + 'Average Plant Tmp: ' + str(round( (current_sensors['P_TMP0'] + current_sensors['P_TMP1'] + current_sensors['P_TMP2'] + current_sensors['P_TMP3'] )/4, sensor_precision-2)) + 'DF, ' + 'Ambient Mst: ' + str(round(current_sensors['A_MST0'],2)) + '%, ' + 'Average Plant Mst: ' + str(round( (current_sensors['P_MST0']+current_sensors['P_MST1']+ current_sensors['P_MST2']+ current_sensors['P_MST3'] )/4 ,1)) + '%'
else:
#Simple PiPlanter
output = 'Ambient Light: ' + str(round((current_sensors['A_LDR0']),1)) + '%, ' + 'Ambient Temp: ' + str(round(current_sensors['A_TMP0'],1)) + 'DF, ' + 'Average Plant Mst: ' + str(round( (current_sensors['P_MST0']+current_sensors['P_MST1'])/2 ,1)) + '%'
else:
print "convertadc input sampleallsensors"
return 0
return output
pumps = {'PUMP0' : 7, 'PUMP1' : 11, 'PUMP2' : 13, 'PUMP3' : 16} #assign names to GPIO pins
for k in pumps.itervalues():
GPIO.setup(k,GPIO.OUT)
#pumps a given amount of water from a given pump
def pumpwater(pump,volume):
LPM = 4.00 #L per minute
ontime = volume*(60/LPM)
GPIO.output(pumps[pump],True)
time.sleep(ontime)
GPIO.output(pumps[pump],False)
output = 'Pumped ' + str(volume) + ' L of water into plants in ' + str(ontime) + ' seconds.'
return output
#Sets up proper directories for folders and images
def visualssetup(time):
#checks if directories above exist
if not os.path.exists(str(os.getcwd()) + '/videos/'):
os.makedirs(str(os.getcwd()) + '/videos/')
if not os.path.exists(str(os.getcwd()) + '/videos/dailys/'):
os.makedirs(str(os.getcwd()) + '/videos/dailys/')
if not os.path.exists(str(os.getcwd()) + '/images/'):
os.makedirs(str(os.getcwd()) + '/images/')
if not os.path.exists(str(os.getcwd()) + '/images/dailys/'):
os.makedirs(str(os.getcwd()) + '/images/dailys/')
global current_dailypicdir
current_dailypicdir = str(os.getcwd()) + '/images/dailys/' + str(time) + '/'
os.makedirs(current_dailypicdir)
global current_dailyvideodir
current_dailyvideodir = str(os.getcwd()) + '/videos/dailys/' + str(time) + '/'
os.makedirs(current_dailyvideodir)
def picture(dir,cycle):
image = dir + str(cycle).zfill(4) + '.jpg'
picture_command = 'raspistill -o ' + dir + str(cycle).zfill(4) + '.jpg'
os.system(picture_command)
return image
def rendervideo():
time = strftime("%m-%d-%Y_%I-%M-%S%p")
global current_videodir
scheduler.shutdown(shutdown_threadpool=False)
render_command = 'sudo mencoder -nosound mf://' + current_dailypicdir + '*.jpg -mf w=2592:h=1944:type=jpg:fps=15 -ovc lavc -lavcopts vcodec=mpeg4:vbitrate=2160000:mbd=2:keyint=132:v4mv:vqmin=3:lumi_mask=0.07:dark_mask=0.2:mpeg_quant:scplx_mask=0.1:tcplx_mask=0.1:naq -o ' + current_dailyvideodir + 'output.avi'
os.system(render_command)
def daily():
visualssetup(strftime("%m-%d-%Y_%I-%M-%S%p"))
api.update_status(pumpwater('PUMP0',3))
global cycle
cycle = 0
def hourly():
cursor.execute(sampleallsensors(3,20,'MySQL'))
user.commit()
print sampleallsensors(3,20,'Console')
pumpwater('PUMP0', .5)
global current_dailypicdir
api.update_status(sampleallsensors(3,20,'Twitter') + " https://esologic.com/?page_id=1042")
picture(current_dailypicdir,cycle)
#pumpwater('PUMP0', 1)
global cycle
cycle = cycle + 1
if __name__ == '__main__':
daily()
hourly()
scheduler = Scheduler(standalone=True)
scheduler.add_interval_job(hourly, hours=1)
scheduler.add_interval_job(daily, days=1)
try:
scheduler.start()
except (KeyboardInterrupt, SystemExit):
pass
I’ll do a much more thorough post when the project is further along. For those playing along at home, you can see that I’ve totally re-written the code for this new version. So far, it has much less functionality but much more stability and flexibility.