Monday, December 2, 2013

We have slightly modified the design of our fan so that the LCD displays the current and desired temperature as well as the RPM of the fan.  The following is a basic bread board setup and code for our fan.

Schematic for fan controller

*/
#include <OneWire.h>
#include <DallasTemperature.h>
#include <PID_v1.h>
#include <LiquidCrystal.h>

//Definitions
#define FAN 9           // Output pin for fan
#define ONE_WIRE_BUS 8  // Temperature Input is on Pin 2
#define click 3        //Rotary Encoder Click
#define encoder0PinA  2 //Rotary Encoder Pin A
#define encoder0PinB  4 //Rotary Encoder Pin B
#define CRITICAL 50.00  //Critical temperature to ignore PID and turn on fans

volatile unsigned int encoder0Pos = 0;  //Encoder value for ISR

LiquidCrystal lcd(12, 11, 13, 5,6,7);  //set up LCD

//Setup Temperature Sensor
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

//Setup PID
double Setpoint, Input, Output;                                          //I/O for PID
double aggKp=40, aggKi=2, aggKd=10;                                     //original: aggKp=4, aggKi=0.2, aggKd=1, Aggressive Turning,50,20,20
double consKp=20, consKi=1, consKd=5;                                  //original consKp=1, consKi=0.05, consKd=0.25, Conservative Turning,20,10,10
PID myPID(&Input, &Output, &Setpoint, consKp, consKi, consKd, REVERSE);  //Initialize PID

//interface
int timeCounter;
void setup()

  // start serial port for temperature readings
  Serial.begin(9600);
  Serial.println("Start");

  //Temperature Setup
  sensors.begin();                    //Start Library
  sensors.requestTemperatures();      // Send the command to get temperatures
  Input = sensors.getTempCByIndex(0); //Set Input to Current Temperature
  Setpoint = 28;                      //Inintialize desired Temperature in Deg C
  encoder0Pos=28;

  //PID Setup
  myPID.SetMode(AUTOMATIC);
  //TCCR2B = TCCR2B & 0b11111000 | 0x01; //adjust the PWM Frequency, note: this changes timing like delay()

  //Setup Pins
  pinMode(FAN, OUTPUT);                   // Output for fan speed, 0 to 255
  pinMode(click, INPUT);                  // Click button is an input
  pinMode(encoder0PinA, INPUT);
  digitalWrite(encoder0PinA, HIGH);       // Turn on pullup resistor
  pinMode(encoder0PinB, INPUT);
  digitalWrite(encoder0PinB, HIGH);       // Turn on pullup resistor

  //Set up Interupts
  attachInterrupt(1, clicked, RISING);    // Click button on interrupt 1 - pin 3
  attachInterrupt(0, doEncoder, CHANGE);  // Encoder pin on interrupt 0 - pin 2

  //interface

  timeCounter=0;

  //Setup LCD 16x2 and display startup message
  lcd.begin(16, 2);
  lcd.print(" Smart Fan");
  lcd.setCursor(0,1);
  lcd.print(" Starting Up");
  delay(1000);
  lcd.clear();
}
void loop()
{
   timeCounter++;

   //Get temperature and give it to the PID input
   sensors.requestTemperatures();
   Input=sensors.getTempCByIndex(0);

  //print out info to LCD
  lcd.setCursor(1,0);
  lcd.print("Temp:");
  lcd.print((int)Input);
  lcd.setCursor(9,0);
  lcd.print("RPM:");
  lcd.print((int)Output*4.7059);
  lcd.setCursor(1,1);
  lcd.print("Set:");
  lcd.print((int)Setpoint);

  //Compute PID value
  double gap = abs(Setpoint-Input); //distance away from setpoint
  if(gap<1)
  { 
    //Close to Setpoint, be conservative
    myPID.SetTunings(consKp, consKi, consKd);
  }
  else
  {
     //Far from Setpoint, be aggresive
     myPID.SetTunings(aggKp, aggKi, aggKd);
  }
  myPID.Compute();
  Serial.print(timeCounter);
  Serial.print(" ");
  Serial.print(Input);
  Serial.print(" ");
  Serial.println(Output);
  analogWrite(FAN,255);
  //Write PID output to fan if not critical
  if (Input<CRITICAL)
    analogWrite(FAN,Output);
  else
    analogWrite(FAN,255);
}

void doEncoder()
{
  //pinA and pinB are both high or both low, spinning forward, otherwise it's spinning backwards
  if (digitalRead(encoder0PinA) == digitalRead(encoder0PinB))
  {
    encoder0Pos++;
  }
  else
  {
    encoder0Pos--;
  }
  Serial.println (encoder0Pos, DEC);  //Print out encoder value to Serial
  Setpoint=encoder0Pos;
}
void clicked()
{
  //For interface
  lcd.clear();
  lcd.print("clicked!");
  delay(1000);
}