Hello! Here are some images of the new grow setup:
and here is the working version of the code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 |
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.