Michael Guerero
Published © GPL3+

Mini HVAC

A small-scale HVAC system utilizing a closed-loop feedback PID controller that can maintain a set-point temperature within the box.

BeginnerShowcase (no instructions)2,358
Mini HVAC

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Adafruit MCP9808 High Accuracy I2C Temperature Sensor Breakout Board
×1
Antec 140mm PC Fan
×1
Arduino MotorShield Rev3
Arduino MotorShield Rev3
×1
75 Watt Desk Lamp
×1

Story

Read more

Code

Mini HVAC PID Control

Arduino
PID control
#include <AFMotor.h>
#include <Wire.h>
#include "Adafruit_MCP9808.h"

Adafruit_MCP9808 tempsensor = Adafruit_MCP9808();
AF_DCMotor fan(2);

unsigned long currMillis;
unsigned long prevMillis = 0;
double kp = 410;
double ki = 2*kp/20; 
double kd = kp*20/8;
double dt = 0.01;          // Specify sample time in seconds (fixed)
double dtmillis = dt*1000;  // Sample time in milliseconds
int setpoint;
float input;
float Output;
float err;
float pTerm;
int IntThresh;
float integrated_err;
float dTerm;
float iTerm;
float last_err;


void setup(){
  Serial.begin(9600);
  
  if (!tempsensor.begin()) {
    Serial.println("Couldn't find MCP9808!");
    while (1);
  }
  fan.run(RELEASE);
  fan.setSpeed(0);
}

void loop(){
setpoint = 30;               // Specified by user, r(t)
  float c = tempsensor.readTempC();
  Serial.print("Temp: "); 
  Serial.println(c); Serial.println("*C\t");
input = (c);                 // Read by your sensor, y(t) ... analogRead(...)
err = (input - setpoint);    // Compute Error, e(t) = r(t) - y(t)
delay(200);
// ====================== Compute Proportional term: ========================
pTerm = kp * (err);                 
// ====================== Compute Integral term: ===========================
IntThresh = .3;                      // Set value for max intergral term
if (abs(err) > IntThresh)            // Crude way to prevent integrator 'windup'
{                                    
    integrated_err += err;           // Accumulate the error integral
}
else 
{
    integrated_err = 0;              // Zero it if out of bounds 
}
iTerm = ki * integrated_err;         // Compute actual Integral term
// ====================== Compute Derivative term: ===========================
dTerm = kd * (err - last_err)*dt;  
// ====================== Compute PID control command, u(t): =================
Output = constrain(pTerm + iTerm + dTerm, 0, 255);       
fan.run(FORWARD);
fan.setSpeed(Output);    // Use u(t) to drive the plant, i.e. analogWrite(Output), motor.run(Output), etc...

last_err = err;      // Set last_err to err for next time through loop

Credits

Michael Guerero

Michael Guerero

3 projects • 43 followers
Earned my BS in Mechanical Engineering from Cal Poly Pomona in 2018. Currently working for the California Air Resources Board.

Comments