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.
*/
#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);
}
No comments:
Post a Comment