Page 1 of 1

My first python

Posted: Mon Dec 17, 2012 10:53 pm
by JavaTheHutt
Hey all! This is my first Python program and I was hoping to get a little feedback on it. The code is to control a grow room via gpio pins. It gets the temperature from a small sensor and turns on the fan at a preset temperature and also runs a light based on a timer. As of now it writes all of the temperature data to a text file. Next I plan to add co2 and humidity sensors. Again this is my first Python script and I can take criticism so please let me know if I have done something bad. Thanks.\
\

Code: Select all

import time
import datetime
import RPi.GPIO as GPIO
import os

#Bad readings.
BAD_READINGS = ["62", "125"]
#20 C is the ideal temp for now.
IDEAL_TEMP = 20000;
#Causes shutdown if temp gets this high
HIGH_TEMP = 22000;
#Seconds in twelve hours
TWELVE_HOURS = 43200
#Runs the shell script to make sure that the pins are setup.
BASH_COMMAND = "sudo ./pythongpiosetup.sh";
#Permissions for the files.
PERMISSION = "w+";
#Location of the temperature sensor.
SENSOR_LOCATION = "/sys/bus/w1/devices/28-0000040099fc/w1_slave";
#Location to write room stats.
OUTPUT_LOCATION = "roomstats.txt";
#Location of log file.
LOG_LOCATION = "log.txt";
#Location to write error messages to.
ERROR_LOCATION = "problems.txt";
#Pin that is connected to the fan.
FAN = 11;
#Pin that controls the light.
LIGHT = 12;
#Where the temp data starts for this sensor.
DATA_INDEX = 69;
#Delimiter for the data file.
DELIMITER = " ";
#Denotes an appliance is runnig.
ON = True;
#Denotes appliance is off.
OFF = False;
#Creates a new line.
NEW_LINE = "\n";
#Decimal char.
DECIMAL = '.';
#Divide by this number to get the correct decimal place in the temp.
FACTOR = 1000.0;

#Controls a light on a timer and a fan that is activated from the temperature.
class Controller():      
      def __init__(self, the_cycle):
          os.system(BASH_COMMAND);
          self.my_cycle = the_cycle;
          self.setupPins();
          self.my_data_file = open(OUTPUT_LOCATION, PERMISSION);
          self.my_log = open(LOG_LOCATION, PERMISSION);
          self.my_error_file = open(ERROR_LOCATION, PERMISSION);
          self.my_light_on = OFF;
          self.my_cycle_time = 0;
          self.my_run_time = 0;
          print "Initialization complete.";
          return;

      #Clears warnings because I dont have a way to clean up after termination.
      def setupPins(self):
          GPIO.setwarnings(OFF);
          GPIO.setmode(GPIO.BOARD);
          GPIO.setup(LIGHT, GPIO.OUT);
          GPIO.setup(FAN, GPIO.OUT);
          if not self.my_cycle:
             GPIO.output(LIGHT, ON); 
             self.my_light_on = ON;
          else:
             GPIO.output(LIGHT, OFF);
             GPIO.output(FAN, OFF);
             self.my_light_on = OFF;
          print "Outputs set";
          return;
          
      #Gets the raw data from the sensor.
      def getRawData(self):
          file = open(SENSOR_LOCATION);
          text = file.read();
          file.close();
          return text;
          
      #grabs the temp out of the raw data.
      def extractTemp(self, the_text):
          return the_text[DATA_INDEX:the_text.__len__() - 1];
          
      #Returns just the temp data.
      def getTempData(self):
          t0 = time.time();
          ftext = self.extractTemp(self.getRawData());
          self.isGoodRead(ftext);
          self.setClocks(t0, time.time());
          return ftext; 
          
      #Hack to filter bad values.
      def isGoodRead(self, the_temp):
          result = True;
          for bad_temp in BAD_READINGS:
              if the_temp == bad_temp:
                 result = False;
                 break;
          return result;
      
      #If room temp gets too high this method waits until the temp drops to
      #the ideal temp in order to resume operation.
      def coolDown(self, the_time, the_temp):
          self.writeHighTempLogEntry(the_time, the_temp);
          GPIO.output(FAN, ON);
          if self.my_light_on:
             GPIO.output(LIGHT, OFF);
          temp = self.getTempData();
          while int(temp) > IDEAL_TEMP:       
                temp = self.getTempData();
                self.writeData(self.my_run_time, temp);
          self.my_error_file.write("HIGH TEMP CLEARED! Time: %s Temp: %s"%(self.dropDecimals(self.my_run_time), self.addDecimal(temp)));
          if self.my_light_on:
             GPIO.output(LIGHT, ON);
          return;
                
      #Writes a helpful message to the error file if cooldown occured.
      def writeHighTempLogEntry(self, the_time, the_temp):
          self.my_error_file.write("HIGH TEMP! %s seconds. %s degrees C."%(self.dropDecimals(self.my_run_time), self.addDecimal(the_temp))); 
          self.my_error_file.write(NEW_LINE);
          return;
      
      #Cycles the light if the cycle time has been reached.
      def checkLight(self, the_delta):
          if the_delta > TWELVE_HOURS:
             self.my_cycle_time = 0;
             self.my_light_on = not self.my_light_on;
             GPIO.output(LIGHT, self.my_light_on);
          return;
          
      #Turns the fan on if the temp is above the set point.
      def checkFan(self, the_temp):
          if int(the_temp) > HIGH_TEMP:
             self.coolDown(time.time(), the_temp);             
          elif int(the_temp) > IDEAL_TEMP:
             GPIO.output(FAN, ON);
          else:
               GPIO.output(FAN, OFF);
          return;
          
      #Adds decimal point to the temp.
      def addDecimal(self, the_temp):
          temp = float(the_temp);
          return str(temp / FACTOR);
    
      #Writes data to the data file.
      #run_time(in_seconds)\current temp * 1000 in celsius\true for fan running\true for light on.    
      def writeData(self, the_time, the_data):
          self.my_data_file.write(str(the_time)[0:str(the_time).find('.')]);
          self.my_data_file.write(DELIMITER);
          self.my_data_file.write(the_data);
          self.my_data_file.write(DELIMITER);
          if GPIO.input(FAN) == 1:
             self.my_data_file.write(str(ON));
          else:
               self.my_data_file.write(str(OFF));
          self.my_data_file.write(DELIMITER);
          if (self.my_light_on):
             self.my_data_file.write(str(ON));
          else:
             self.my_data_file.write(str(OFF));
          self.my_data_file.write(NEW_LINE);
          return;
          
      #Sets the runtime and cycle clocks.
      def setClocks(self, t0, t1):
          elapsed = t1 - t0;
          self.my_cycle_time += elapsed;
          self.my_run_time += elapsed;
          return;
          
      #Drops decimal places.
      def dropDecimals(self, the_number):
          string = str(the_number);
          return string[0:string.find(DECIMAL)];          
          
      #Starts the polling loop.
      def start(self):
          print "Running...";
          while True:
                temp_data = self.getTempData();
                self.checkLight(self.my_cycle_time);
                self.checkFan(temp_data);
                self.writeData(self.my_run_time, temp_data);
          self.my_data_file.close();      
          return;

Controller(True).start();

Re: My first python

Posted: Mon Dec 17, 2012 11:25 pm
by toxibunny
nicely done. does it work?

Re: My first python

Posted: Mon Dec 17, 2012 11:38 pm
by JavaTheHutt
It works so far but I still need a way to filter out the occasional bad reading from the sensor.