FRDM-K64F Code Share
/
PIDHeater
Extruder/Heated bed PID control for the FRDM-K64F
main.cpp@2:6e731a17523c, 2016-02-07 (annotated)
- Committer:
- unix_guru
- Date:
- Sun Feb 07 19:08:57 2016 +0000
- Revision:
- 2:6e731a17523c
- Parent:
- 0:8b77aea74642
FRDM-K64F - First version of PID heater control demo to manage temperature on a 3d printer extruder.
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
unix_guru | 0:8b77aea74642 | 1 | /** A demo application to show how to mangage and control a heater element |
unix_guru | 2:6e731a17523c | 2 | * through a PID loop using a Thermistor input and PWM output |
unix_guru | 2:6e731a17523c | 3 | * for the @NXP (@freescale) FRDM-K64F demo board. |
unix_guru | 2:6e731a17523c | 4 | * |
unix_guru | 2:6e731a17523c | 5 | * This particular example drives the heater element for a 3d Printer Extruder. |
unix_guru | 2:6e731a17523c | 6 | * |
unix_guru | 2:6e731a17523c | 7 | * For more information on PID control check out Brett Beauregard's Arduino PID library: |
unix_guru | 2:6e731a17523c | 8 | * |
unix_guru | 2:6e731a17523c | 9 | * https://github.com/br3ttb/Arduino-PID-Library |
unix_guru | 2:6e731a17523c | 10 | * |
unix_guru | 2:6e731a17523c | 11 | * The wikipedia article on PID controllers is a good place to start on |
unix_guru | 2:6e731a17523c | 12 | * understanding how they work: |
unix_guru | 2:6e731a17523c | 13 | * |
unix_guru | 2:6e731a17523c | 14 | * http://en.wikipedia.org/wiki/PID_controller |
unix_guru | 2:6e731a17523c | 15 | * |
unix_guru | 2:6e731a17523c | 16 | * The Thermistor value to Temerature routine uses the Steinhart-Hart equation. |
unix_guru | 2:6e731a17523c | 17 | This is a Thermistor to Temerature conversion demo |
unix_guru | 2:6e731a17523c | 18 | |
unix_guru | 2:6e731a17523c | 19 | Much thanks to @Adafruit for this tutorial: |
unix_guru | 2:6e731a17523c | 20 | https://learn.adafruit.com/thermistor/using-a-thermistor |
unix_guru | 2:6e731a17523c | 21 | |
unix_guru | 2:6e731a17523c | 22 | The 100K Thermistor is configured with a 4.7k series resistor |
unix_guru | 2:6e731a17523c | 23 | tied to vcc (3.3v) like this: |
unix_guru | 2:6e731a17523c | 24 | |
unix_guru | 2:6e731a17523c | 25 | +3.3v |
unix_guru | 2:6e731a17523c | 26 | | |
unix_guru | 2:6e731a17523c | 27 | \ |
unix_guru | 2:6e731a17523c | 28 | / 4.7k series resistor |
unix_guru | 2:6e731a17523c | 29 | \ |
unix_guru | 2:6e731a17523c | 30 | / |
unix_guru | 2:6e731a17523c | 31 | | |
unix_guru | 2:6e731a17523c | 32 | .-----------O To Anlog pin on FRDM board |
unix_guru | 2:6e731a17523c | 33 | | |
unix_guru | 2:6e731a17523c | 34 | \ |
unix_guru | 2:6e731a17523c | 35 | / |
unix_guru | 2:6e731a17523c | 36 | Thermistor 100k Nominal |
unix_guru | 2:6e731a17523c | 37 | \ |
unix_guru | 2:6e731a17523c | 38 | / |
unix_guru | 2:6e731a17523c | 39 | | |
unix_guru | 2:6e731a17523c | 40 | --- |
unix_guru | 2:6e731a17523c | 41 | GND |
unix_guru | 0:8b77aea74642 | 42 | * |
unix_guru | 0:8b77aea74642 | 43 | * Author(s): Michael Ball unix_guru@hotmail.com |
unix_guru | 0:8b77aea74642 | 44 | * |
unix_guru | 0:8b77aea74642 | 45 | */ |
unix_guru | 0:8b77aea74642 | 46 | |
unix_guru | 0:8b77aea74642 | 47 | #include "mbed.h" |
unix_guru | 2:6e731a17523c | 48 | #include "millis.h" |
unix_guru | 2:6e731a17523c | 49 | #include "PID.h" |
unix_guru | 2:6e731a17523c | 50 | |
unix_guru | 2:6e731a17523c | 51 | float getTemperature(); |
unix_guru | 2:6e731a17523c | 52 | |
unix_guru | 0:8b77aea74642 | 53 | Serial pc(USBTX, USBRX); |
unix_guru | 2:6e731a17523c | 54 | Ticker PrintTicker; // Send process results to Console once per second |
unix_guru | 2:6e731a17523c | 55 | Ticker ticker; // Set up the millis() ticker. |
unix_guru | 2:6e731a17523c | 56 | |
unix_guru | 2:6e731a17523c | 57 | #define DEFAULT_Kp 1 |
unix_guru | 2:6e731a17523c | 58 | #define DEFAULT_Ki 0.002 |
unix_guru | 2:6e731a17523c | 59 | #define DEFAULT_Kd 20 |
unix_guru | 0:8b77aea74642 | 60 | |
unix_guru | 2:6e731a17523c | 61 | #define AUTOMATIC 1 |
unix_guru | 2:6e731a17523c | 62 | #define MANUAL 0 |
unix_guru | 2:6e731a17523c | 63 | #define DIRECT 0 |
unix_guru | 2:6e731a17523c | 64 | #define REVERSE 1 |
unix_guru | 2:6e731a17523c | 65 | #define thermistor A3 // FRDM-K64F Analog input pin A3 - Adjust to your particular board |
unix_guru | 2:6e731a17523c | 66 | #define driver PTC3 // FRDM-K64F PWM output pin PTC3 - Adjust to your particular board |
unix_guru | 0:8b77aea74642 | 67 | |
unix_guru | 2:6e731a17523c | 68 | AnalogIn Thermistor(thermistor); // Read temperature value from thermistor on A3 |
unix_guru | 2:6e731a17523c | 69 | PwmOut Driver(driver); // PWM drive FET heater on PTC3 values are 0-1.0 |
unix_guru | 2:6e731a17523c | 70 | // For 0-100% |
unix_guru | 2:6e731a17523c | 71 | |
unix_guru | 2:6e731a17523c | 72 | float Input, Output, Setpoint; |
unix_guru | 2:6e731a17523c | 73 | PID controller(&Input, &Output, &Setpoint, DEFAULT_Kp , DEFAULT_Ki , DEFAULT_Kd , DIRECT); |
unix_guru | 2:6e731a17523c | 74 | |
unix_guru | 2:6e731a17523c | 75 | #define RATE 1.0 // Print rate Once per second |
unix_guru | 2:6e731a17523c | 76 | |
unix_guru | 2:6e731a17523c | 77 | void PrintValues() { // Routine to print out results to console |
unix_guru | 2:6e731a17523c | 78 | pc.printf("Input Output Setpoint Kp Ki Kd time\r\n"); |
unix_guru | 2:6e731a17523c | 79 | pc.printf("%f, %f, %f, %f, %f, %f, %d \r\n", |
unix_guru | 2:6e731a17523c | 80 | Input, Output, Setpoint, controller.GetKp() , controller.GetKi() , controller.GetKd() , millis() ); |
unix_guru | 2:6e731a17523c | 81 | |
unix_guru | 0:8b77aea74642 | 82 | } |
unix_guru | 0:8b77aea74642 | 83 | |
unix_guru | 2:6e731a17523c | 84 | |
unix_guru | 0:8b77aea74642 | 85 | int main(){ |
unix_guru | 0:8b77aea74642 | 86 | |
unix_guru | 2:6e731a17523c | 87 | startMillis(); // Initialize timer. |
unix_guru | 2:6e731a17523c | 88 | |
unix_guru | 2:6e731a17523c | 89 | pc.baud(115200); |
unix_guru | 2:6e731a17523c | 90 | pc.printf("\r\nThermistor PID Test - Build " __DATE__ " " __TIME__ "\r\n"); |
unix_guru | 0:8b77aea74642 | 91 | |
unix_guru | 2:6e731a17523c | 92 | PrintTicker.attach(&PrintValues,RATE); // Start PID process running at 100ms rate. |
unix_guru | 2:6e731a17523c | 93 | |
unix_guru | 2:6e731a17523c | 94 | Setpoint = 80; // Set target temperature in degrees Celcius. |
unix_guru | 2:6e731a17523c | 95 | controller.SetMode(AUTOMATIC); // Turn PID controller on. |
unix_guru | 2:6e731a17523c | 96 | |
unix_guru | 0:8b77aea74642 | 97 | |
unix_guru | 0:8b77aea74642 | 98 | while(1){ |
unix_guru | 0:8b77aea74642 | 99 | |
unix_guru | 2:6e731a17523c | 100 | Input = getTemperature(); // Actual temperature in Degrees Celcius |
unix_guru | 2:6e731a17523c | 101 | |
unix_guru | 2:6e731a17523c | 102 | controller.Compute(); // Process PID loop. |
unix_guru | 2:6e731a17523c | 103 | |
unix_guru | 2:6e731a17523c | 104 | Driver = Output/1000; // Sent PWM value scaled 0 - 1.0 as mbed requires |
unix_guru | 0:8b77aea74642 | 105 | |
unix_guru | 0:8b77aea74642 | 106 | } |
unix_guru | 0:8b77aea74642 | 107 | |
unix_guru | 2:6e731a17523c | 108 | } |
unix_guru | 2:6e731a17523c | 109 | |
unix_guru | 2:6e731a17523c | 110 | |
unix_guru | 2:6e731a17523c | 111 | // This is the workhorse routine that calculates the temperature |
unix_guru | 2:6e731a17523c | 112 | // using the Steinhart-Hart equation for thermistors |
unix_guru | 2:6e731a17523c | 113 | // https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation |
unix_guru | 2:6e731a17523c | 114 | |
unix_guru | 2:6e731a17523c | 115 | float getTemperature() { |
unix_guru | 2:6e731a17523c | 116 | #define THERMISTORNOMINAL 100000 // 100k |
unix_guru | 2:6e731a17523c | 117 | // temp. for nominal resistance (almost always 25 C) |
unix_guru | 2:6e731a17523c | 118 | #define TEMPERATURENOMINAL 25 |
unix_guru | 2:6e731a17523c | 119 | // The beta coefficient of the thermistor (usually 3000-4000) |
unix_guru | 2:6e731a17523c | 120 | #define BCOEFFICIENT 3950 |
unix_guru | 2:6e731a17523c | 121 | // the value of the 'other' resistor |
unix_guru | 2:6e731a17523c | 122 | #define SERIESRESISTOR 4700 |
unix_guru | 2:6e731a17523c | 123 | |
unix_guru | 2:6e731a17523c | 124 | // This is the workhorse routine that calculates the temperature |
unix_guru | 2:6e731a17523c | 125 | // using the Steinhart-Hart equation for thermistors |
unix_guru | 2:6e731a17523c | 126 | // https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation |
unix_guru | 2:6e731a17523c | 127 | |
unix_guru | 2:6e731a17523c | 128 | float temperature, resistance; |
unix_guru | 2:6e731a17523c | 129 | float steinhart; |
unix_guru | 2:6e731a17523c | 130 | int a; |
unix_guru | 2:6e731a17523c | 131 | |
unix_guru | 2:6e731a17523c | 132 | a = Thermistor.read_u16(); // Read 16bit Analog value |
unix_guru | 2:6e731a17523c | 133 | // pc.printf("Raw Analog Value for Thermistor = %d\r\n",a); |
unix_guru | 2:6e731a17523c | 134 | |
unix_guru | 2:6e731a17523c | 135 | /* Calculate the resistance of the thermistor from analog votage read. */ |
unix_guru | 2:6e731a17523c | 136 | resistance = (float) SERIESRESISTOR / ((65536.0 / a) - 1); |
unix_guru | 2:6e731a17523c | 137 | // pc.printf("Resistance for Thermistor = %f\r\n",resistance); |
unix_guru | 2:6e731a17523c | 138 | |
unix_guru | 2:6e731a17523c | 139 | steinhart = resistance / THERMISTORNOMINAL; // (R/Ro) |
unix_guru | 2:6e731a17523c | 140 | steinhart = log(steinhart); // ln(R/Ro) |
unix_guru | 2:6e731a17523c | 141 | steinhart /= BCOEFFICIENT; // 1/B * ln(R/Ro) |
unix_guru | 2:6e731a17523c | 142 | steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15); // + (1/To) |
unix_guru | 2:6e731a17523c | 143 | steinhart = 1.0 / steinhart; // Invert |
unix_guru | 2:6e731a17523c | 144 | temperature = steinhart - 273.15; // convert to C |
unix_guru | 2:6e731a17523c | 145 | |
unix_guru | 2:6e731a17523c | 146 | // pc.printf("Extruder Temperature is %f\r\n", temperature); |
unix_guru | 2:6e731a17523c | 147 | |
unix_guru | 2:6e731a17523c | 148 | return temperature; |
unix_guru | 2:6e731a17523c | 149 | |
unix_guru | 2:6e731a17523c | 150 | } |
unix_guru | 2:6e731a17523c | 151 |