Skip to content
Browse files

tims new code

  • Loading branch information...
1 parent 50f49b5 commit e4a3532210585e5abc15f022fcb7d0afbe89ec46 @daniel-cloudspace committed Mar 10, 2012
Showing with 93 additions and 34 deletions.
  1. +93 −34 open_incubator.ino
View
127 open_incubator.ino
@@ -1,59 +1,118 @@
-#include <PID_v1.h>
-#define RelayPin 13
+/* FamiLAB incubator V0.2: Now with cooling capability!
+This project arose out of the need for a 37˚C incubator for E.coli culturing (Biohacking).
+Additionally a peltier was used so that organisms that grow at lower temperature (20˚), could be cultured as well.
+A L6203 heavyduty H-bridge was used to achieve the PWM switching, and also the switch the peltier from heating mode to cooling mode
+PID code taken, with some modification, from "PID without a PhD" by Tim Wescott http://igor.chudov.com/manuals/Servo-Tuning/PID-without-a-PhD.pdf
-//Define Variables we'll be connecting to
-double Setpoint, Input, Output;
+TODO:
+7-segment display output!
+Verification of thermristor temp readings?
-//Specify the links and initial tuning parameters
-PID myPID(&Input, &Output, &Setpoint,2,5,1, DIRECT);
+*/
-int WindowSize = 5000;
-unsigned long windowStartTime;
+//Define our variables
+const int internalThermistor = 0; //Analog input attatched to the thermistor inside the incubator
+const int externalThermistor = 1; //Analog input attatched to the thermistor sampling the ambient air temperature outside the box
+const int inOne = 9; //Goes to logic input pin #1 for the L6203 H-bridge, if this is High and the inTwo is low, Out1 will source current and Out2 will sink it
+const int inTwo = 10; //Goes to logic input pin #2 for the L6203 H-bridge, if this is High and the inOne is low, Out2 will source current and Out1 will sink it
+const int enablePin = 11; //Goes to the enable pin, if this isn't brought high the chip won't do anything
+double setPoint = 37; //Temperature setpoint, in degrees celcius
+double error = 0;
+double feedback = 0;
+double tempReading = 0;
+double tempReadingExternal = 0;
+int sampleInverval = 1000; //Sampling interval in milliseconds
+struct SPid {
+double dState; // Last position input double
+double iState; // Integrator state
+double iMax;
+double iMin; // Maximum and minimum allowable integrator state
+double pGain; // proportional gain
+double iGain; // integral gain
+double dGain; // derivative gain
+
+};
+
+struct SPid thePID;
+
+double UpdatePID(struct SPid *pid, double error, double position) {
+double pTerm, dTerm, iTerm, feedback;
+pTerm = pid->pGain * error;
+// calculate the proportional term
+// calculate the integral state with appropriate limiting
+pid->iState += error;
+if (pid->iState > pid->iMax) pid->iState = pid->iMax; else if (pid->iState < pid->iMin) pid->iState = pid->iMin;
+iTerm = pid->iGain * pid->iState * double(sampleInverval/1000); // calculate the integral term
+dTerm = pid->dGain * (position - pid->dState); pid->dState = position;
+
+feedback = pTerm + iTerm - dTerm;
+//Our analog write function only takes 0-255, so if the PID output is greater than 255 cap it.
+if (feedback > 255) feedback = 255; if (feedback < -255) feedback = -255;
+
+return feedback;
+
+}
double thermistor_read(int RawADC) {
double Temp;
Temp = log(((10240000/RawADC) - 10000));
Temp = 1 / (0.001129148 + (0.000234125 + (0.0000000876741 * Temp * Temp ))* Temp );
Temp = Temp - 273.15; // Convert Kelvin to Celcius
- Temp = (Temp * 9.0)/ 5.0 + 32.0; // Convert Celcius to Fahrenheit
return Temp;
}
-void setup()
-{
- Setpoint = 130;
- myPID.SetOutputLimits(0, WindowSize);
- //turn the PID on
- myPID.SetMode(AUTOMATIC);
+void setup() {
+ //Begin serial and initialize our data values for thePID struct.
+ Serial.begin(9600);
+ thePID.pGain = 15;
+ thePID.iGain = 1.5;
+ thePID.dGain = 1;
+ thePID.iMax = 160;
+ thePID.iMin = -160;
+ pinMode(inOne,OUTPUT);
+ pinMode(inTwo,OUTPUT);
+ pinMode(enablePin,OUTPUT);
+ digitalWrite(enablePin,HIGH);
+ digitalWrite(inOne,LOW);
+ digitalWrite(inTwo,LOW);
- Serial.begin(9600);
+
+
}
-void loop()
-{
- Input = thermistor_read(analogRead(0));
- myPID.Compute();
-
- /************************************************
- * turn the output pin on/off based on pid output
- ************************************************/
- unsigned long now = millis();
- if(now - windowStartTime > WindowSize) { // time to shift the Relay Window
- windowStartTime += WindowSize;
- }
+void loop() {
+ //Internal Thermistor
+ tempReading = thermistor_read(analogRead(0));
+ tempReadingExternal = thermistor_read(analogRead(5));
+ error = setPoint - tempReading;
+ feedback = UpdatePID(&thePID,error,tempReading);
+ //Serial.print("Interior Temp: ");
+ Serial.println(tempReading);
+ //Serial.print("Exterior Temp: ");
+ //Serial.println(tempReadingExternal);
+ //Serial.print("Feedback: ");
+ //Serial.println(feedback);
- if(Output > now - windowStartTime)
- digitalWrite(RelayPin,HIGH);
+ //If feedback is >= 0, then heat the box by PWM switching the peltier
+ if (feedback >= 0)
+ {
+ analogWrite(inOne,feedback);
+ analogWrite(inTwo,0);
+ }
else
- digitalWrite(RelayPin,LOW);
+ //If feedback is < 0, flip the current through the peltier so that its now cooling and PWM it the same way.
+ {
+ analogWrite(inOne,0);
+ analogWrite(inTwo,-feedback);
+ }
+
- Serial.println(Input);
- analogWrite(3,Output);
+ delay(sampleInverval);
+
}
-

0 comments on commit e4a3532

Please sign in to comment.
Something went wrong with that request. Please try again.