Extruder/Heated bed PID control for the FRDM-K64F

Dependencies:   PID millis mbed

Revision:
2:6e731a17523c
Parent:
0:8b77aea74642
--- a/main.cpp	Wed Jan 27 21:32:34 2016 +0000
+++ b/main.cpp	Sun Feb 07 19:08:57 2016 +0000
@@ -1,39 +1,151 @@
 /** A demo application to show how to mangage and control a heater element 
- * through a PID loop using a Thermistor input and PWM output.
- * For more information on PID control 
+ * through a PID loop using a Thermistor input and PWM output
+ * for the @NXP (@freescale) FRDM-K64F demo board.
+ *
+ * This particular example drives the heater element for a 3d Printer Extruder.
+ *
+ * For more information on PID control check out Brett Beauregard's Arduino PID library:
+ *
+ *  https://github.com/br3ttb/Arduino-PID-Library
+ *
+ * The wikipedia article on PID controllers is a good place to start on
+ * understanding how they work:
+ *
+ *  http://en.wikipedia.org/wiki/PID_controller
+ *
+ * The Thermistor value to Temerature routine uses the Steinhart-Hart equation.
+ This is a Thermistor to Temerature conversion demo 
+
+Much thanks to @Adafruit for this tutorial:
+https://learn.adafruit.com/thermistor/using-a-thermistor
+
+The 100K Thermistor is configured with a 4.7k series resistor 
+tied to vcc (3.3v)  like this:
+
+    +3.3v
+      |
+      \
+      /  4.7k series resistor
+      \
+      /
+      |
+      .-----------O To Anlog pin on FRDM board
+      |
+      \
+      /
+  Thermistor  100k Nominal
+      \
+      /
+      |
+     ---
+     GND
  *
  * Author(s): Michael Ball  unix_guru@hotmail.com
  *
  */
 
 #include "mbed.h"
-
-#include "PIDHeater.h"                  // PIDHeater simply takes two variables
-                                        // The Thermistor input and the Heater output.
-                                        // 
+#include "millis.h"
+#include "PID.h"                                       
+                                        
+float getTemperature();
+                                        
 Serial pc(USBTX, USBRX);
-Ticker ticker;                        
+Ticker PrintTicker;                     // Send process results to Console once per second       
+Ticker ticker;                          // Set up the millis() ticker.
+                                       
+#define  DEFAULT_Kp 1
+#define  DEFAULT_Ki 0.002
+#define  DEFAULT_Kd 20
 
-#define RATE 0.1                        // Check temp every 100ms
-PIDHeater extruder(A3, PTC3);           // Thermistor on A3 heater on PTC3
+#define AUTOMATIC 1
+#define MANUAL    0
+#define DIRECT  0
+#define REVERSE  1
+#define thermistor A3                       // FRDM-K64F Analog input pin A3   - Adjust to your particular board
+#define driver PTC3                         // FRDM-K64F PWM output pin PTC3   - Adjust to your particular board
 
-void run_PID_loop() {                        // Periodically test temperature and set output
-    extruder.run();
+AnalogIn Thermistor(thermistor);            // Read temperature value from thermistor on A3
+PwmOut Driver(driver);                      // PWM drive FET heater on PTC3  values are 0-1.0 
+                                            // For 0-100% 
+             
+float Input, Output, Setpoint; 
+PID controller(&Input, &Output, &Setpoint, DEFAULT_Kp , DEFAULT_Ki , DEFAULT_Kd , DIRECT);
+
+#define RATE 1.0                            // Print rate  Once per second
+  
+void PrintValues() {                        // Routine to print out results to console
+    pc.printf("Input      Output     Setpoint   Kp        Ki        Kd        time\r\n");
+    pc.printf("%f, %f, %f, %f, %f, %f, %d \r\n", 
+            Input, Output, Setpoint, controller.GetKp() , controller.GetKi() , controller.GetKd() , millis() );
+
 }    
 
+
 int main(){
  
-  extruder.configureRange(0,250);       // Set MIN/MAX temperature in degrees Celcius.
-  extruder.setTemperature(25);         // Set target temperature to 25 degrees Celcius.
+  startMillis();                            // Initialize timer.
+ 
+  pc.baud(115200);    
+  pc.printf("\r\nThermistor PID Test - Build " __DATE__ " " __TIME__ "\r\n");
   
-  ticker.attach(&run_PID_loop,RATE);    // Start PID process running at 100ms rate.
+  PrintTicker.attach(&PrintValues,RATE);    // Start PID process running at 100ms rate.
+
+  Setpoint = 80;                            // Set target temperature in degrees Celcius.
+  controller.SetMode(AUTOMATIC);            // Turn PID controller on.
+  
 
   while(1){
    
-     pc.printf("Extruder Temperature is %f\r\n", extruder.getTemperature());
-     
-     wait(1);  
+     Input = getTemperature();              // Actual temperature in Degrees Celcius
+
+     controller.Compute();                  // Process PID loop. 
+
+     Driver = Output/1000;                  // Sent PWM value scaled 0 - 1.0 as mbed requires 
 
   }
  
-}
\ No newline at end of file
+}
+
+
+// This is the workhorse routine that calculates the temperature
+// using the Steinhart-Hart equation for thermistors
+// https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
+
+float getTemperature() {
+#define THERMISTORNOMINAL 100000      // 100k 
+// temp. for nominal resistance (almost always 25 C)
+#define TEMPERATURENOMINAL 25   
+// The beta coefficient of the thermistor (usually 3000-4000)
+#define BCOEFFICIENT 3950
+// the value of the 'other' resistor
+#define SERIESRESISTOR 4700    
+
+// This is the workhorse routine that calculates the temperature
+// using the Steinhart-Hart equation for thermistors
+// https://en.wikipedia.org/wiki/Steinhart%E2%80%93Hart_equation
+
+    float temperature, resistance;
+    float steinhart;
+    int a;
+    
+    a = Thermistor.read_u16();       // Read 16bit Analog value
+//    pc.printf("Raw Analog Value for Thermistor = %d\r\n",a);
+  
+    /* Calculate the resistance of the thermistor from analog votage read. */
+    resistance = (float) SERIESRESISTOR / ((65536.0 / a) - 1);
+//    pc.printf("Resistance for Thermistor = %f\r\n",resistance);
+   
+    steinhart = resistance / THERMISTORNOMINAL;         // (R/Ro)
+    steinhart = log(steinhart);                         // ln(R/Ro)
+    steinhart /= BCOEFFICIENT;                          // 1/B * ln(R/Ro)
+    steinhart += 1.0 / (TEMPERATURENOMINAL + 273.15);   // + (1/To)
+    steinhart = 1.0 / steinhart;                        // Invert
+    temperature = steinhart - 273.15;                   // convert to C
+
+//    pc.printf("Extruder Temperature is %f\r\n", temperature);
+ 
+    return temperature;    
+
+}
+