PIC24 Support Libraries
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
reflow_operate.c
Go to the documentation of this file.
1 /*
2  * "Copyright (c) 2008 Robert B. Reese, Bryan A. Jones, J. W. Bruce ("AUTHORS")"
3  * All rights reserved.
4  * (R. Reese, reese_AT_ece.msstate.edu, Mississippi State University)
5  * (B. A. Jones, bjones_AT_ece.msstate.edu, Mississippi State University)
6  * (J. W. Bruce, jwbruce_AT_ece.msstate.edu, Mississippi State University)
7  *
8  * Permission to use, copy, modify, and distribute this software and its
9  * documentation for any purpose, without fee, and without written agreement is
10  * hereby granted, provided that the above copyright notice, the following
11  * two paragraphs and the authors appear in all copies of this software.
12  *
13  * IN NO EVENT SHALL THE "AUTHORS" BE LIABLE TO ANY PARTY FOR
14  * DIRECT, INDIRECT, SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES ARISING OUT
15  * OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION, EVEN IF THE "AUTHORS"
16  * HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
17  *
18  * THE "AUTHORS" SPECIFICALLY DISCLAIMS ANY WARRANTIES,
19  * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
20  * AND FITNESS FOR A PARTICULAR PURPOSE. THE SOFTWARE PROVIDED HEREUNDER IS
21  * ON AN "AS IS" BASIS, AND THE "AUTHORS" HAS NO OBLIGATION TO
22  * PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS, OR MODIFICATIONS."
23  *
24  * Please maintain this header in its entirety when copying/modifying
25  * these files.
26  *
27  *
28  */
29 #include "pic24_all.h"
30 #include <stdio.h>
31 #include "reflow_oven.h"
32 
33 /** \file
34 Contains the functions for executing a reflow profile
35 */
36 
37 #define MIN_WETTING_TIME 60 //seconds
38 
39 //stat variables
40 uint16_t u16_peakTime;
41 int16_t i16_maxTemp;
42 uint16_t u16_startWetting;
43 uint16_t u16_endWetting;
44 uint8_t coolingFlag;
45 uint16_t u16_startReflow;
46 uint16_t u16_endReflow;
47 
48 void resetStats(void) {
49  i16_maxTemp = 0;
50  coolingFlag = 0;
51  u16_startWetting = 0;
52  u16_endWetting = 0;
53 }
54 
55 void printStats (void) {
56  uint16_t u16_wettingTime;
57  uint16_t u16_reflowTime;
58  if (u16_endWetting == 0) u16_wettingTime = u16_tenthSeconds - u16_startWetting;
59  else u16_wettingTime = u16_endWetting - u16_startWetting;
60  if (u16_endReflow == 0) u16_reflowTime = u16_tenthSeconds - u16_startReflow;
61  else u16_reflowTime = u16_endReflow - u16_startReflow;
62 
63  printf ("\nMax temp: %u, Temp Overshoot: %d, Wetting time: %d (s), Reflow Time: %d (s), Elapsed time: %u (s)\n",
64  i16_maxTemp, i16_maxTemp - profiles[u8_currentProfile].i16_reflowTemp,
65  u16_wettingTime/10, u16_reflowTime/10, u16_tenthSeconds/10 );
66 }
67 
68 int16_t updateStats(void) {
69  int16_t i16_tempC;
70  i16_tempC = getCelsiusI16Temp();
71  if (i16_tempC > i16_maxTemp) i16_maxTemp = i16_tempC;
72  if (i16_tempC > profiles[u8_currentProfile].i16_wetTemp &&
73  u16_startWetting == 0) u16_startWetting = u16_tenthSeconds;
74  if (coolingFlag && (i16_tempC < profiles[u8_currentProfile].i16_wetTemp)
75  && u16_endWetting == 0)
76  u16_endWetting = u16_tenthSeconds;
77  if (i16_tempC > profiles[u8_currentProfile].i16_reflowTemp &&
78  u16_startReflow == 0) u16_startReflow = u16_tenthSeconds;
79  if (coolingFlag && (i16_tempC < profiles[u8_currentProfile].i16_reflowTemp)
80  && u16_endReflow == 0)
81  u16_endReflow = u16_tenthSeconds;
82  return(i16_tempC);
83 }
84 
85 uint16_t tempToPower(int16_t i16_t) {
86  uint16_t u16_i;
87 
88  for (u16_i=0; u16_i <= 100; u16_i++) {
89  if (fdata.caldata.temp[u16_i] >= i16_t) return(u16_i);
90  }
91  reportError("Reflow application error: Unable to find power setting for target temp");
92  return(0);
93 }
94 
95 void doRampUp(int16_t i16_targetTemp, uint16_t u16_targetTime) {
96  int16_t i16_tempC, i16_lastTemp;
97  uint8_t u8_endPower;
98  uint16_t u16_endTime;
99 
100  u16_endTime = u16_tenthSeconds + u16_targetTime*10; //end time does not change
101  i16_tempC = updateStats(); //get current temp;
102  u8_endPower = tempToPower(i16_targetTemp);
103  setPower(100); //need to heat this up
104  do {
105  i16_tempC = updateStats(); //get current temp;
106  printf("Current temp/time: %u %u Power: %u\n",i16_tempC,u16_tenthSeconds, getPower());
107  DELAY_MS(1000);
108  if (u16_tenthSeconds > u16_endTime) return;
109  } while ((i16_targetTemp - i16_tempC) > 10 );
110  setPower(30); // near target temp
111  i16_lastTemp = i16_tempC;
112  do {
113  DELAY_MS(1000);
114  i16_tempC = updateStats();
115  printf("Current temp/time: %u %u Power: %u\n",i16_tempC,u16_tenthSeconds, getPower());
116  if ((i16_tempC < i16_lastTemp) && (i16_tempC < i16_targetTemp ) ) {
117  //temp is decreasing
118  setPower(u8_endPower);
119  } else setPower(30);
120  i16_lastTemp = i16_tempC;
121  } while (u16_tenthSeconds < u16_endTime);
122 }
123 
124 /* Oven cools down so slowly just turn off power and wait
125  for target time */
126 #if 0
127 void doRampDown (int16_t i16_targetTemp, uint16_t u16_targetTime) {
128  int16_t i16_tempC;
129 
130  setPower(0);
131  while (u16_targetTime) {
132  i16_tempC = updateStats();
133  printf("Current temp/time: %u %u Power: %u\n",i16_tempC,u16_tenthSeconds, getPower());
134  DELAY_MS(1000);
135  u16_targetTime--;
136  }
137 }
138 #endif
139 void doRampDown(void) {
140  int16_t i16_tempC;
141  uint16_t u16_wetTime;
142  uint8_t u8_openDoorFlag;
143 
144  setPower(0);
145  u8_openDoorFlag = 0;
146  do {
147  u16_wetTime = u16_tenthSeconds - u16_startWetting;
148  if ((u16_wetTime > MIN_WETTING_TIME) && !u8_openDoorFlag) {
149  printf("\n\nWetting time is met, open door to aid cooling\n");
150  u8_openDoorFlag = 1;
151  }
152  i16_tempC = updateStats();
153  printf("Current temp/time: %u %u Power: %u\n",i16_tempC,u16_tenthSeconds, getPower());
154  DELAY_MS(1000);
155  } while (i16_tempC > 100);
156 }
157 
158 
159 void doHold (int16_t i16_targetTemp, uint16_t u16_targetTime) {
160  uint16_t u16_endTime, u16_maxExitTime;
161  int16_t i16_tempC, i16_lastTemp;
162  uint8_t u8_endPower;
163 
164  //maximum time to wait before reaching target temp
165  u16_maxExitTime = u16_tenthSeconds + u16_targetTime*10*5;
166  i16_tempC = updateStats(); //get current temp;
167  u8_endPower = tempToPower(i16_targetTemp);
168  if (i16_tempC < i16_targetTemp)setPower(100) ;
169  while (i16_tempC < i16_targetTemp) { //we need to reach the target reflow hold temperature
170  DELAY_MS(1000);
171  i16_tempC = updateStats();
172  printf("Current temp/time: %u %u Power: %u\n",i16_tempC,u16_tenthSeconds, getPower());
173  if (u16_tenthSeconds > u16_maxExitTime)return;
174  }
175  i16_lastTemp = i16_tempC;
176  u16_endTime = u16_tenthSeconds + u16_targetTime*10;
177  do {
178  DELAY_MS(1000);
179  i16_tempC = updateStats();
180  printf("Current temp/time: %u %u Power: %u\n",i16_tempC, u16_tenthSeconds, getPower());
181  if ((i16_tempC < i16_lastTemp) && (i16_tempC < i16_targetTemp ) ) {
182  //temp is decreasing
183  setPower(u8_endPower);
184  } else setPower(30);
185  i16_lastTemp = i16_tempC;
186  } while (u16_tenthSeconds < u16_endTime);
187 }
188 
189 
190 void doReflow(void) {
191 
192  uint8_t u8_rdyFlag,u8_c;
193  uint16_t i16_tempC;
194 
195  u8_rdyFlag = 0;
196  do {
197  printf("\n\nOpen door, place board in oven, close door.\n");
198  printf("Turn 'TEMP' knob to 'Toast On/Bake Off'\n");
199  printf("Ensure that end of thermocouple is not touching\n");
200  printf("the board or metal. \n");
201  printf("Enter 'y' to continue or 'n' to exit...\n");
202  u8_c = inCharEcho();
203  if (u8_c == 'n') return;
204  } while (u8_c != 'y');
205 
206  u16_tenthSeconds = 0;
207  u8_c = ZEROCROSS;
208  while (u8_c == ZEROCROSS) {
209  if (u16_tenthSeconds > 4) break;
210  doHeartbeat();
211  }
212  if (u16_tenthSeconds > 4) {
213  printf("\nExiting, power is not on to oven, cannot detect 60Hz cycling.\n");
214  return;
215  }
216  u16_tenthSeconds = 0;
217  resetStats();
218 //preheat
219  i16_tempC = getCelsiusI16Temp();
220  printf("\nStart Preheat (temp = %uC)\n",i16_tempC);
221  doRampUp(profiles[u8_currentProfile].i16_preheatTemp,
222  profiles[u8_currentProfile].u16_preheatTime);
223 //soak
224  i16_tempC = getCelsiusI16Temp();
225  printf("\nStart Soak (temp = %uC), Elapsed time: %u s\n",i16_tempC,
226  u16_tenthSeconds/10);
227  doRampUp(profiles[u8_currentProfile].i16_soakTemp,
228  profiles[u8_currentProfile].u16_soakTime);
229 //reflow
230  printf("\nStart Reflow (temp = %uC), Elapsed time: %u s\n",i16_tempC,
231  u16_tenthSeconds/10);
232  doRampUp(profiles[u8_currentProfile].i16_reflowTemp,
233  profiles[u8_currentProfile].u16_reflowTime);
234  printf("\nStart Reflow Hold (temp = %uC), Elapsed time: %u s\n",i16_tempC,
235  u16_tenthSeconds/10);
236  doHold(profiles[u8_currentProfile].i16_reflowTemp,
237  profiles[u8_currentProfile].u16_reflowHoldTime);
238 //initial cooldown
239 
240  coolingFlag = 1;
241  setPower(0);
242  printf("\nStart Cool1 (temp = %uC), Elapsed time: %u s\n",i16_tempC,
243  u16_tenthSeconds/10);
244  doRampDown();
245 #if 0
246 
247  doRampDown(profiles[u8_currentProfile].i16_coolTemp,
248  profiles[u8_currentProfile].u16_coolTime);
249 //
250 #endif
251 
252  printStats();
253 
254 }
255 
256