Arduino PID Coffee Roaster

Arduino PID Coffee Roaster Eric Lau MCEN 5115 – Graduate Project Mechanical Engineering Department University of Colorado at Boulder Boulder, CO Intr...
Author: Tracy Wright
18 downloads 2 Views 8MB Size
Arduino PID Coffee Roaster Eric Lau MCEN 5115 – Graduate Project Mechanical Engineering Department University of Colorado at Boulder Boulder, CO

Introduction For my graduate project I built an automated coffee-roasting device to roast green coffee beans into beans that can be used to brew coffee. The main components of the project are a hot air popcorn popper and an Arduino Uno microcontroller to monitor inputs and control the roaster outputs. The bean temperature is critical to proper roasting so a thermocouple is used to monitor current temperature and a PID control loop adjusts the heating element and fan speed to maintain temperature in the desired range.

Construction The Presto Pop-Lite popcorn popper used for this project is designed for 110V AC power without any user adjustment of fan speed or heating elements. In order to accomplish this there are two heating elements inside; the larger of the two provides most of the heat required for the popper, while a secondary heating element is wired in series with the fan motor to bring the 110V input down to a lower voltage that the motor is able to operate at. The motor is a small DC motor with 4 diodes to direct the alternating current to the appropriate terminals. The first objective was to separate the heating system from the fan system. After they were separated, the two systems were controlled independently by the microcontroller. For the purpose of my coffee roaster, the main heating element was used as the only heat source and the secondary heating element was not required. The heating element was connected to a solid-state relay controlled by the Arduino program. The fan motor was rewired to work with a 19V DC power supply with a MOSFET controlling motor fan speed with a pulse width modulated signal from the Arduino. The 4 diode bride was removed from the terminals, replaced with a single diode to prevent back EMF due to changes in motor speed. Temperature data is collected via a J-type thermocouple. Due to the small voltage produced by a thermocouple, the Arduino was not able to monitor the voltage directly. A MAX6675 thermocouple amplifier was used to amplify the thermocouple signal and convert it to a digital signal that the Arduino can use.

A small serial LCD screen is used to allow the Arduino to function independently of a computer. The screen provides information about the current temperature, current temperature set point, time until next set point, and when the roast is finished.

Arduino and Control System The Arduino Uno microcontroller uses a PID control system to compare the thermocouple temperature input against the temperature set point and adjust the output accordingly. Initially, I planned to control the air flow, via fan speed, to alter the temperature in the roasting chamber; however, in order to keep the beans moving and roasting evenly, the fan speed had to be set to the maximum so the temperature control is accomplished by altering the percentage of time the heating element is on or off for. I used an existing block of code as the foundation for my code but changed a number of things to incorporate direct control over the heating coils and to use a thermocouple for more accurate temperature reading. Existing Arduino libraries were used for interfacing with the MAX6675 thermocouple chip, operating the PID control system, and outputting to a LCD display. The full code used is included below for reference. The code also allows for interfacing with a processing graphical user interface to display the operation of the PID control system. A trial run of the PID system controlling temperature is included below; however, I was not able to get the GUI to operate for a full roasting cycle. Materials Used Presto Pop-Lite Hot Air Popcorn Popper Arduino Uno J-Type Thermocouple MAX6675 Thermocouple Chip (with Sparkfun breakout board) Solid State Relay IRL510 MOSFET Arduino Protoshield 16X2 LCD, Serial Enabled Adjustable Power Supply Misc wires, resistors, diode References Tutorial for similar project: http://www.instructables.com/id/A-fully-automaticcoffee-bean-roaster-Arduino/?ALLSTEPS Arduino MAX6675 Library: http://playground.arduino.cc/Main/MAX6675Library Arduino Software Serial Library: http://arduino.cc/en/Reference/SoftwareSerial Arduino PID Library: http://playground.arduino.cc/Code/PIDLibrary

Appendix 500 450 400

Temperature (F)

350 300 250 200 150 100 50 0 SetPoint

Temp

Figure 1: PID Temp Control Test Run

Figure 2: Final Version Startup

Figure 3: Final Version Run Screen

Figure 4: Green Beans and Roasted Beans

/* This code is based on code from the link below. Significant changes have been made to the control system * and the temperature monitoring system. Additionally, existing Arduino libraries are used for thermocouple * monitoring, PID control, and software serial communication for a LCD. * * *A fully automatic coffee bean roaster (Arduino) * By Rutger - [email protected] * See http://www.instructables.com/id/A-fully-automatic-coffee-bean-roasterArduino/ * */ //Import the required arduino libraries #include "max6675.h" #include "PID_v1.h" #include #include //initialize variables //MAX6675 int thermoDO = 4; int thermoCS = 5; int thermoCLK = 6; int vccPin = 3; int gndPin = 2;

//Digital output pin MAX6675 //Chip slect pin MAX6675 //Clock pin Max6675 //Power pin for MAX6675 //Ground pin for MAX6675

int Tprofile [] = { // Temperature profile in deg C (phase 1, 2, 3, etc) 132, 132, 200, 218, 230, 475}; // Mikes profile from homeroasters int Sprofile [] = { // Time spent at each phase, seconds 0, 120, 240, 120, 240, 180}; // Mikes profile from homeroasters int final = 230; int cool = 40; int phase = 0; int countdown; int overshoot=3; float slope=0; int serialTime; float temperature = 0.0; int heaterpwm; //PID controller double Input, Setpoint; double Output = 0;

// final roasting temperature (deg C) // temperature to cool to after roasting (deg C) // phase // count down seconds till end of phase // max Temp overshoot before turn off heating coil // setpoint slope // determine phase // Temperature output variable

// parameters for PID

int P = 75; int I = 50; int D = 0; int buttonpin = 10; //int fanpin = 8; always on) int roastpin = 9; int readbutton = 1; int LCDpin=7; serLCD lcd(LCDpin);

//P term //I term //D termv // pushbutton pin // fan motor pwm pin (not used, fan speed set to // heating coil relay pin // the current reading from the button pin

MAX6675 thermocouple(thermoCLK, thermoCS, thermoDO); //write the variables into the MAX6675 library PID myPID(&Input, &Output, &Setpoint ,P ,I ,D,DIRECT); //write the variables into the PID library

void setup() { Serial.begin(9600); myPID.SetMode(AUTOMATIC); //turn the PID on pinMode(vccPin, OUTPUT); //Set vcc pin to output pinMode(gndPin, OUTPUT); //set ground pin to output pinMode(buttonpin, INPUT); // sets the button pin as input //pinMode(fanpin, OUTPUT); // sets the fanpin pin as output pinMode(roastpin, OUTPUT); // sets the roastpin pin as output digitalWrite(vccPin, HIGH); //write vcc pin to high digitalWrite(gndPin, LOW); //write ground pin to low analogWrite(roastpin,0); lcd.clear(); lcd.print("Roaster V_1.0"); delay(2000); lcd.clear(); lcd.print("Push Button"); lcd.setCursor(0,1); lcd.print(" to Begin"); while (readbutton == HIGH) // Press button to start roaster and select min fanspeed { readbutton = digitalRead(buttonpin); };

} void loop() { temperature = thermocouple.readCelsius(); Input = temperature; // go directly to sp during phase 0 if (phase == 0) { Setpoint = Tprofile [phase]; // jump directly to setpoint in first phase if (temperature >= (Setpoint - 5) ) { countdown=-1;} // start phase 1 when setpoint is reached } // if countdown ends, start new phase and count down if (countdown < 0) { phase = phase + 1; serialTime = millis () / 1000; serialTime = serialTime + (Sprofile [phase]); slope = ((Tprofile [phase]) - (Tprofile [(phase - 1)])); slope = (slope / (Sprofile [phase])); } // determine setpoint during phase 1+ if (phase > 0) { countdown = serialTime - ((millis ())/1000); Setpoint = Tprofile [(phase - 1)] + (slope * ((Sprofile [phase]) - countdown)); } // PID controller adjusts roastpin pwm myPID.Compute(); heaterpwm = map (Output,0,255,0,100); // adjust heater pwm based on PID output if (temperature < (Setpoint + overshoot)) { analogWrite (roastpin,heaterpwm); } else { analogWrite (roastpin,0); } // write to LCD screen lcd.clear(); lcd.home(); //lcd.print("P:"); //Current Phase lcd.print(phase);

lcd.print(" P:"); lcd.print(Setpoint); lcd.setCursor(0,1); lcd.print(" T:"); lcd.print(temperature);

//Current Temperature Setpoint //Current Measured Temperature

lcd.print(" Tm:"); //Countdown Time lcd.print(countdown); //send-receive with processing for Front-End PID program SerialReceive(); SerialSend(); // When final temp is reached off button is pressed, cool beans and end // if (temp >= final || readbutton == HIGH) { if (temperature >= final) { // turn off heating coil readbutton = LOW; Setpoint=cool; Output=0; analogWrite (roastpin,0); lcd.clear(); lcd.home(); lcd.print("Cooling"); while (Input >= cool) { // wait untill beans are cooled till ... temperature =thermocouple.readCelsius(); Input =temperature; SerialReceive(); SerialSend(); }; lcd.clear(); lcd.home(); lcd.print("Roasting"); lcd.setCursor(0,1); lcd.print("Finished"); while (1 >= 1) {delay(2000);};//eternal loop } // waits for 0.5 second delay(500); }

// Preexisting code written by someone else to send data to the processing frontend for graphical output on PID //controll when connected to a laptop // union { // This Data structure lets byte asBytes[24]; // us take the byte array float asFloat[6]; // sent from processing and } // easily convert it to a foo; // float array

// getting float values from processing into the arduino // was no small task. the way this program does it is // as follows: // * a float takes up 4 bytes. in processing, convert // the array of floats we want to send, into an array // of bytes. // * send the bytes to the arduino // * use a data structure known as a union to convert // the array of bytes back into an array of floats // the bytes coming from the arduino follow the following // format: // 0: 0=Manual, 1=Auto, else = ? error ? // 1: 0=Direct, 1=Reverse, else = ? error ? // 2-5: float setpoint // 6-9: float input // 10-13: float output // 14-17: float P_Param // 18-21: float I_Param // 22-245: float D_Param void SerialReceive() { // read the bytes sent from Processing int index=0; byte Auto_Man = -1; byte Direct_Reverse = -1; while(Serial.available()&&index