• API
• FAQ
• Tools
• Archive
SHARE
TWEET

# Soldering iron

simas1017 Oct 12th, 2016 211 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
1. #include <LiquidCrystal.h>
2. #include "TimerOne.h"
3. #include "Button.h"
4. #include "PID_v1.h"
5. #include "PID_AutoTune_v0.h"
6. #include "EEPROMex.h"
7. #include <avr/wdt.h>
8.
9. #define OFF             0
10. #define ON              1
11.
12. // Pin definitions
13. #define HEATER_PIN      5
14. #define POT_PIN         A1
15. #define TEMP_PIN        A0
16. #define BUTTON_PIN      2
17. #define AUTOTUNE_PIN    3
18.
19. #define LCD_RS          13
20. #define LCD_EN          12
21. #define LCD_D4          11
22. #define LCD_D5          10
23. #define LCD_D6          9
24. #define LCD_D7          8
25.
26. // LCD Update Interval
27. #define UPDATE_INTERVAL 100 // Time im ms between LCD updates
28.
29. /*****************************************************************************************
30. * Temperature equation definition
31. *
32. * Y = a*X + b, where Y is the temperature and X is the analog value read from the sensor.
33. * You'll need two temperatures and it's analog values to calculate a and b.
34. *
35. * To find a, subtract your higher value temperature from your lower value temperature and
36. * divide by the subtraction of their correspondent analog values.
37. *
38. * For example: (30C, 228) and (450C, 590) where 30C is 30 degree celsius and 228 is the
39. * analog value.
40. *
41. * a = (450-30)/(590-228) = 1.16
42. *
43. * To find b, use Y = a*X + b where Y is one of the values you found and X is it's analog
44. * value. The value of a is the one found just before.
45. *
46. * For example:
47. *
48. * 30 = 1.16*228 + b -> b = 30 - 1.16*228 = -234.48
49. *
50. * To use Fahrenheit instead of Celsius, the you should do the same as written above but
51. * measure the values is Fahrenheit instead of Celsius, like (30F, 228) and (450F, 590).
52. *
53. * You'll need to change the "C" prints to "F" too.
54. *****************************************************************************************/
55. #define EQUATION_A  0.441162791
56. #define EQUATION_B  10.153255677
57.
58. // Temperature control definitions
59. #define MIN_TEMP    100 // Minimum setpoint temperature
60. #define MAX_TEMP    500 // Maximum setpoint temperature
61. #define PWM_MAX     1023    // PWM limit, max 1023 (my power supply was shutting down at 1023)
62.
63. // PID VALUES
64. #define KP_VAL      26.67
65. #define KI_VAL      3.56
66. #define KD_VAL      50.01
67.
68. // PID Autotune Variables
69. #define AUTOTUNE_SETPOINT       150 // Temperature around PID autotune will tune
70. #define AUTOTUNE_START_VALUE    (PWM_MAX/2) // Do not change
71. #define AUTOTUNE_STEP_VALUE     AUTOTUNE_START_VALUE // Do not change
72. #define AUTOTUNE_NOISEBAND      3
73. #define AUTOTUNE_LOOKBACK       10
74.
75. // Auto turn-off time (in milliseconds)
76. #define TURN_OFF_TIME 2700000
77.
78. // Global variables
79. uint32_t update_last = 0;
80. uint8_t heater_mode = OFF;
81. uint32_t on_time = 0;
82.
83. // PID Variables
84. double temperature;
85. double setpoint = 0.0;
86. double duty;
87. double kp;
88. double ki;
89. double kd;
94.
95. PID heaterPid(&temperature, &duty, &setpoint, 2, 5, 1, DIRECT);
96. PID_ATune aTune(&temperature, &duty);
97. LiquidCrystal lcd(LCD_RS, LCD_EN, LCD_D4, LCD_D5, LCD_D6, LCD_D7);
98. Button setButton = Button(BUTTON_PIN, LOW);
99.
100. // Read the Iron temperature
102.
103. // Read Setpoint value from the potentiometer
105.
106. // Check if heater start button was pressed
107. void checkButton();
108.
109. // Display PID Constants
110. void displayPid();
111.
112. // Create degree character
113. void charSetup();
114.
115. void setup() {
116.     // Autotune
117.     uint8_t autotune = OFF;
118.     uint8_t autotune_pid = 0;
119.
120.     // Enable Watchdog Timer, 1 second
121.     wdt_enable(WDTO_1S);
122.
123.     // Define the EEPROM address for Kp, Ki and Kd
128.
129.     // Set up pins
130.     pinMode(HEATER_PIN, OUTPUT);
131.     pinMode(AUTOTUNE_PIN, INPUT);
132.     digitalWrite(BUTTON_PIN, HIGH);
133.     digitalWrite(AUTOTUNE_PIN, HIGH);
134.
135.     // Set up Heater PWM
136.     Timer1.pwm(HEATER_PIN, 0, 30);
137.
138.     // Set up PID
139.     heaterPid.SetOutputLimits(0, PWM_MAX);
140.     heaterPid.SetSampleTime(50);            // Update PID every 50ms
141.     heaterPid.SetMode(AUTOMATIC);
142.
143.     // Set up LCD
144.     lcd.begin(16, 2);
145.     charSetup();
146.
147.     // Check if PID autotune button is pressed at startup
149.         autotune = ON;
151.     }
152.
153.     // Start PID autotune procedure if button was pressed
154.     if(autotune == ON) {
155.         // Configure PID autotune
156.         setpoint = AUTOTUNE_SETPOINT;
157.         duty = AUTOTUNE_START_VALUE;
158.         aTune.SetNoiseBand(AUTOTUNE_NOISEBAND);
159.         aTune.SetOutputStep(AUTOTUNE_STEP_VALUE);
160.         aTune.SetLookbackSec(AUTOTUNE_LOOKBACK);
161.         aTune.SetControlType(1);
162.
163.         // Print some autotune info
164.         lcd.clear();
165.         lcd.print("Autotuning at:");
166.         lcd.setCursor(0, 1);
167.         lcd.print((uint16_t)setpoint);
168.         lcd.print("C");
169.
170.         // Heat to the setpoint, temperature will rise above it
171.         Timer1.setPwmDuty(HEATER_PIN, duty);
173.             // Reset the watchdog timer to prevent rebooting
174.             wdt_reset();
175.         }
176.
177.         // Wait for temperature to drop to setpoint
178.         Timer1.setPwmDuty(HEATER_PIN, 0);
180.             // Reset the watchdog timer to prevent rebooting
181.             wdt_reset();
182.         }
183.
184.         // Start the autotune
185.         while(autotune == ON) {
186.             // Get the current temperature
188.
189.             // Check if the autotune is finished
190.             if(aTune.Runtime() != 0) {
191.                 autotune = OFF;
192.             }
193.             else {
194.                 Timer1.setPwmDuty(HEATER_PIN, duty);
195.             }
196.
197.             // If finished, set up the PID and EEPROM values
198.             if(autotune == OFF) {
199.                 //char string[17];
200.
201.                 // Turn off the heater
202.                 Timer1.setPwmDuty(HEATER_PIN, 0);
203.
204.                 // Get the values from autotune
205.                 kp = aTune.GetKp();
206.                 ki = aTune.GetKi();
207.                 kd = aTune.GetKd();
208.
209.                 // Write them to the EEPROM
213.
214.                 // Reset the setpoint
215.                 setpoint = 0.0;
216.             }
217.
218.             // Reset the watchdog timer to prevent rebooting
219.             wdt_reset();
220.         }
221.     }
222.
223.     // Get the PID constant values from EEPROM if autotune was run
225.
226.     if(autotune_pid == 1) {
230.     } else {
231.         kp = KP_VAL;
232.         ki = KI_VAL;
233.         kd = KD_VAL;
234.     }
235.
236.     // Set the to the PID
237.     heaterPid.SetTunings(kp,ki,kd);
238.
239.     // Clear the display
240.     lcd.clear();
241. }
242.
243. void loop() {
244.     // Get the current time
245.     uint32_t update_time = millis();
246.
247.     // Reset the watchdog timer to prevent rebooting
248.     wdt_reset();
249.
250.     // Check the Heater button
251.     checkButton();
252.
253.     // Automatic turn-off
254.     if(heater_mode == ON) {
255.         if( (millis() - on_time) >= TURN_OFF_TIME) {
256.             heater_mode = OFF;
257.         }
258.     }
259.
260.     // Read Iron temperature and Setpoint
263.
264.     // Calculate PID value
265.     heaterPid.Compute();
266.
267.     // Adjust PWM Duty based on the PID
268.     if(heater_mode == ON) {
269.         Timer1.setPwmDuty(HEATER_PIN, duty);
270.     } else {
271.         Timer1.setPwmDuty(HEATER_PIN, 0);
272.     }
273.
274.     //Check if it's time to update the LCD
275.     if(update_time - update_last > UPDATE_INTERVAL) {
276.         //char string[17];
277.
278.         // Check if autotune button is pressed, if yes display the PID constant values
280.             lcd.setCursor(0, 0);
281.             lcd.print("T: ");
282.             if(temperature < 100) {
283.                 lcd.print(' ');
284.             }
285.             lcd.print(temperature, 0);
286.             lcd.write(byte(0));
287.             lcd.print("C / ");
288.             lcd.print(setpoint, 0);
289.             lcd.write(byte(0));
290.             lcd.print('C');
291.
292.             lcd.setCursor(0, 1);
293.             if(heater_mode == ON) {
294.                 lcd.print("Heater ON ");
295.             } else {
296.                 lcd.print("Heater OFF");
297.             }
298.
299.             //Uncomment to show analog values (used to calibrate)
300.             //lcd.setCursor(13, 1);
301.             //uint16_t temp_analog = 0;
305.             //lcd.print(temp_analog/3);
306.         } else {
307.             displayPid();
308.         }
309.
310.         // Update the time variable
311.         update_last = update_time;
312.     }
313. }
314.
317.     uint16_t temp = 0;
318.
321.
322.     // Read temperature four times
327.
329.     temp = (temp >> 2);
330.
331.     // Get the value in degrees celsius (or fahrenheit)
332.     temp = (EQUATION_A*temp) + EQUATION_B;
333.
334.     return temp;
335. }
336.
337. // Read Setpoint value from the potentiometer
339.     uint16_t pot = 0;
340.
343.
344.     // Read the potentiometer four times
349.
350.     // Map the value read to the temperature range
351.     pot = map(pot, 0, 4092, 0, (MAX_TEMP-MIN_TEMP)) + MIN_TEMP;
352.
353.     return pot;
354. }
355.
356. // Check if heater start button was pressed
357. void checkButton() {
358.     setButton.listen();
359.
360.     if(setButton.onPress()) {
361.         if(heater_mode == ON) {
362.             heater_mode = OFF;
363.         } else {
364.             heater_mode = ON;
365.             on_time = millis();
366.         }
367.     }
368. }
369.
370. // Display PID Constants
371. void displayPid() {
372.     lcd.clear();
373.     lcd.print("P ");
374.     lcd.print(kp, 2);
375.     lcd.print(" I ");
376.     lcd.print(ki, 2);
377.     lcd.setCursor(0, 1);
378.     lcd.print("D ");
379.     lcd.print(kd, 2);
380. }
381.
382. // Create degree character
383. void charSetup() {
384.     byte degree[8] = {
385.         B00010,
386.         B00101,
387.         B00010,
388.         B00000,
389.         B00000,
390.         B00000,
391.         B00000,
392.     };
393.
394.     lcd.createChar(0, degree) ;
395. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy.

Top