PiPlanter 2 | New Code Version / Temporary Setup

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.

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.