Просмотр исходного кода

Merge pull request #244 from markfinn/pidbed

PID for heated bed
ErikZalm 11 лет назад
Родитель
Сommit
36a746d7d5
6 измененных файлов: 230 добавлений и 273 удалений
  1. 39
    1
      Marlin/Configuration.h
  2. 1
    4
      Marlin/Configuration_adv.h
  3. 31
    3
      Marlin/Marlin.pde
  4. 138
    50
      Marlin/temperature.cpp
  5. 10
    4
      Marlin/temperature.h
  6. 11
    211
      README.md

+ 39
- 1
Marlin/Configuration.h Просмотреть файл

@@ -98,7 +98,7 @@
98 98
 #define PID_MAX 255 // limits current to nozzle; 255=full current
99 99
 #ifdef PIDTEMP
100 100
   //#define PID_DEBUG // Sends debug data to the serial port. 
101
-  //#define PID_OPENLOOP 1 // Puts PID in open loop. M104 sets the output power in %
101
+  //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
102 102
   #define PID_INTEGRAL_DRIVE_MAX 255  //limit for the integral term
103 103
   #define K1 0.95 //smoothing factor withing the PID
104 104
   #define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the
@@ -120,6 +120,44 @@
120 120
 //    #define  DEFAULT_Kd 440
121 121
 #endif // PIDTEMP
122 122
 
123
+// Bed Temperature Control
124
+// Select PID or bang-bang with PIDTEMPBED.  If bang-bang, BED_LIMIT_SWITCHING will enable hysteresis
125
+//
126
+// uncomment this to enable PID on the bed.   It uses the same ferquency PWM as the extruder. 
127
+// If your PID_dT above is the default, and correct for your hardware/configuration, that means 7.689Hz,
128
+// which is fine for driving a square wave into a resistive load and does not significantly impact you FET heating.
129
+// This also works fine on a Fotek SSR-10DA Solid State Relay into a 250W heater. 
130
+// If your configuration is significantly different than this and you don't understand the issues involved, you proabaly 
131
+// shouldn't use bed PID until someone else verifies your hardware works.
132
+// If this is enabled, find your own PID constants below.
133
+//#define PIDTEMPBED
134
+//
135
+//#define BED_LIMIT_SWITCHING
136
+
137
+// This sets the max power delived to the bed, and replaces the HEATER_BED_DUTY_CYCLE_DIVIDER option.
138
+// all forms of bed control obey this (PID, bang-bang, bang-bang with hysteresis)
139
+// setting this to anything other than 255 enables a form of PWM to the bed just like HEATER_BED_DUTY_CYCLE_DIVIDER did,
140
+// so you shouldn't use it unless you are OK with PWM on your bed.  (see the comment on enabling PIDTEMPBED)
141
+#define MAX_BED_POWER 255 // limits duty cycle to bed; 255=full current
142
+
143
+#ifdef PIDTEMPBED
144
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
145
+//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, argressive factor of .15 (vs .1, 1, 10)
146
+    #define  DEFAULT_bedKp 10.00
147
+    #define  DEFAULT_bedKi .023
148
+    #define  DEFAULT_bedKd 305.4
149
+
150
+//120v 250W silicone heater into 4mm borosilicate (MendelMax 1.5+)
151
+//from pidautotune
152
+//    #define  DEFAULT_bedKp 97.1
153
+//    #define  DEFAULT_bedKi 1.41
154
+//    #define  DEFAULT_bedKd 1675.16
155
+
156
+// FIND YOUR OWN: "M303 E-1 C8 S90" to run autotune on the bed at 90 degreesC for 8 cycles.
157
+#endif // PIDTEMPBED
158
+
159
+
160
+
123 161
 //this prevents dangerous Extruder moves, i.e. if the temperature is under the limit
124 162
 //can be software-disabled for whatever purposes by
125 163
 #define PREVENT_DANGEROUS_EXTRUDE

+ 1
- 4
Marlin/Configuration_adv.h Просмотреть файл

@@ -5,13 +5,10 @@
5 5
 //=============================Thermal Settings  ============================
6 6
 //===========================================================================
7 7
 
8
-// Select one of these only to define how the bed temp is read.
9
-//
10
-//#define BED_LIMIT_SWITCHING
11 8
 #ifdef BED_LIMIT_SWITCHING
12 9
   #define BED_HYSTERESIS 2 //only disable heating if T>target+BED_HYSTERESIS and enable heating if T>target-BED_HYSTERESIS
13 10
 #endif
14
-#define BED_CHECK_INTERVAL 5000 //ms
11
+#define BED_CHECK_INTERVAL 5000 //ms between checks in bang-bang control
15 12
 
16 13
 //// Heating sanity check:
17 14
 // This waits for the watchperiod in milliseconds whenever an M104 or M109 increases the target temperature

+ 31
- 3
Marlin/Marlin.pde Просмотреть файл

@@ -115,6 +115,7 @@
115 115
 // M301 - Set PID parameters P I and D
116 116
 // M302 - Allow cold extrudes
117 117
 // M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
118
+// M304 - Set bed PID parameters P I and D
118 119
 // M400 - Finish all moves
119 120
 // M500 - stores paramters in EEPROM
120 121
 // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).  
@@ -986,10 +987,13 @@ void process_commands()
986 987
         SERIAL_ERROR_START;
987 988
         SERIAL_ERRORLNPGM(MSG_ERR_NO_THERMISTORS);
988 989
       #endif
989
-      #ifdef PIDTEMP
990
+
990 991
         SERIAL_PROTOCOLPGM(" @:");
991 992
         SERIAL_PROTOCOL(getHeaterPower(tmp_extruder));  
992
-      #endif
993
+
994
+        SERIAL_PROTOCOLPGM(" B@:");
995
+        SERIAL_PROTOCOL(getHeaterPower(-1));  
996
+
993 997
         SERIAL_PROTOCOLLN("");
994 998
       return;
995 999
       break;
@@ -1386,6 +1390,24 @@ void process_commands()
1386 1390
       }
1387 1391
       break;
1388 1392
     #endif //PIDTEMP
1393
+    #ifdef PIDTEMPBED
1394
+    case 304: // M304
1395
+      {
1396
+        if(code_seen('P')) bedKp = code_value();
1397
+        if(code_seen('I')) bedKi = code_value()*PID_dT;
1398
+        if(code_seen('D')) bedKd = code_value()/PID_dT;
1399
+        updatePID();
1400
+        SERIAL_PROTOCOL(MSG_OK);
1401
+		SERIAL_PROTOCOL(" p:");
1402
+        SERIAL_PROTOCOL(Kp);
1403
+        SERIAL_PROTOCOL(" i:");
1404
+        SERIAL_PROTOCOL(Ki/PID_dT);
1405
+        SERIAL_PROTOCOL(" d:");
1406
+        SERIAL_PROTOCOL(Kd*PID_dT);
1407
+        SERIAL_PROTOCOLLN("");
1408
+      }
1409
+      break;
1410
+    #endif //PIDTEMP
1389 1411
     case 240: // M240  Triggers a camera by emulating a Canon RC-1 : http://www.doc-diy.net/photo/rc-1_hacked/
1390 1412
      {
1391 1413
       #ifdef PHOTOGRAPH_PIN
@@ -1418,8 +1440,14 @@ void process_commands()
1418 1440
     case 303: // M303 PID autotune
1419 1441
     {
1420 1442
       float temp = 150.0;
1443
+      int e=0;
1444
+      int c=5;
1445
+      if (code_seen('E')) e=code_value();
1446
+			if (e<0)
1447
+				temp=70;
1421 1448
       if (code_seen('S')) temp=code_value();
1422
-      PID_autotune(temp);
1449
+      if (code_seen('C')) c=code_value();
1450
+      PID_autotune(temp, e, c);
1423 1451
     }
1424 1452
     break;
1425 1453
     case 400: // M400 finish all moves

+ 138
- 50
Marlin/temperature.cpp Просмотреть файл

@@ -57,6 +57,15 @@ int current_raw_bed = 0;
57 57
     float Kc=DEFAULT_Kc;
58 58
   #endif
59 59
 #endif //PIDTEMP
60
+
61
+#ifdef PIDTEMPBED
62
+  // used external
63
+  float pid_setpoint_bed = { 0.0 };
64
+  
65
+  float bedKp=DEFAULT_bedKp;
66
+  float bedKi=(DEFAULT_bedKi*PID_dT);
67
+  float bedKd=(DEFAULT_bedKd/PID_dT);
68
+#endif //PIDTEMPBED
60 69
   
61 70
   
62 71
 //===========================================================================
@@ -64,9 +73,6 @@ int current_raw_bed = 0;
64 73
 //===========================================================================
65 74
 static volatile bool temp_meas_ready = false;
66 75
 
67
-static unsigned long  previous_millis_bed_heater;
68
-//static unsigned long previous_millis_heater;
69
-
70 76
 #ifdef PIDTEMP
71 77
   //static cannot be external:
72 78
   static float temp_iState[EXTRUDERS] = { 0 };
@@ -82,7 +88,22 @@ static unsigned long  previous_millis_bed_heater;
82 88
   // static float pid_output[EXTRUDERS];
83 89
   static bool pid_reset[EXTRUDERS];
84 90
 #endif //PIDTEMP
91
+#ifdef PIDTEMPBED
92
+  //static cannot be external:
93
+  static float temp_iState_bed = { 0 };
94
+  static float temp_dState_bed = { 0 };
95
+  static float pTerm_bed;
96
+  static float iTerm_bed;
97
+  static float dTerm_bed;
98
+  //int output;
99
+  static float pid_error_bed;
100
+  static float temp_iState_min_bed;
101
+  static float temp_iState_max_bed;
102
+#else //PIDTEMPBED
103
+	static unsigned long  previous_millis_bed_heater;
104
+#endif //PIDTEMPBED
85 105
   static unsigned char soft_pwm[EXTRUDERS];
106
+  static unsigned char soft_pwm_bed;
86 107
   
87 108
 #ifdef WATCHPERIOD
88 109
   int watch_raw[EXTRUDERS] = { -1000 }; // the first value used for all
@@ -122,7 +143,7 @@ static unsigned long  previous_millis_bed_heater;
122 143
 //=============================   functions      ============================
123 144
 //===========================================================================
124 145
 
125
-void PID_autotune(float temp)
146
+void PID_autotune(float temp, int extruder, int ncycles)
126 147
 {
127 148
   float input;
128 149
   int cycles=0;
@@ -134,32 +155,55 @@ void PID_autotune(float temp)
134 155
   long t_high;
135 156
   long t_low;
136 157
 
137
-  long bias=PID_MAX/2;
138
-  long d = PID_MAX/2;
158
+  long bias, d;
139 159
   float Ku, Tu;
140 160
   float Kp, Ki, Kd;
141 161
   float max, min;
142
-  
162
+
163
+	if ((extruder > EXTRUDERS)
164
+  #if (TEMP_BED_PIN <= -1)
165
+		||(extruder < 0)
166
+	#endif
167
+	){
168
+  	SERIAL_ECHOLN("PID Autotune failed. Bad extruder number.");
169
+  	return;
170
+	}
171
+	
143 172
   SERIAL_ECHOLN("PID Autotune start");
144 173
   
145 174
   disable_heater(); // switch off all heaters.
146
-  
147
-  soft_pwm[0] = PID_MAX/2;
148
-    
149
-  for(;;) {
175
+
176
+	if (extruder<0)
177
+	{
178
+	 	soft_pwm_bed = (MAX_BED_POWER)/2;
179
+		bias = d = (MAX_BED_POWER)/2;
180
+  }
181
+	else
182
+	{
183
+	  soft_pwm[extruder] = (PID_MAX)/2;
184
+		bias = d = (PID_MAX)/2;
185
+  }
186
+
187
+
188
+
189
+
190
+ for(;;) {
150 191
 
151 192
     if(temp_meas_ready == true) { // temp sample ready
152 193
       CRITICAL_SECTION_START;
153 194
       temp_meas_ready = false;
154 195
       CRITICAL_SECTION_END;
155
-      input = analog2temp(current_raw[0], 0);
156
-      
196
+      input = (extruder<0)?analog2tempBed(current_raw_bed):analog2temp(current_raw[extruder], extruder);
197
+
157 198
       max=max(max,input);
158 199
       min=min(min,input);
159 200
       if(heating == true && input > temp) {
160 201
         if(millis() - t2 > 5000) { 
161 202
           heating=false;
162
-          soft_pwm[0] = (bias - d) >> 1;
203
+					if (extruder<0)
204
+						soft_pwm_bed = (bias - d) >> 1;
205
+					else
206
+						soft_pwm[extruder] = (bias - d) >> 1;
163 207
           t1=millis();
164 208
           t_high=t1 - t2;
165 209
           max=temp;
@@ -172,8 +216,8 @@ void PID_autotune(float temp)
172 216
           t_low=t2 - t1;
173 217
           if(cycles > 0) {
174 218
             bias += (d*(t_high - t_low))/(t_low + t_high);
175
-            bias = constrain(bias, 20 ,PID_MAX-20);
176
-            if(bias > PID_MAX/2) d = PID_MAX - 1 - bias;
219
+            bias = constrain(bias, 20 ,(extruder<0?(MAX_BED_POWER):(PID_MAX))-20);
220
+            if(bias > (extruder<0?(MAX_BED_POWER):(PID_MAX))/2) d = (extruder<0?(MAX_BED_POWER):(PID_MAX)) - 1 - bias;
177 221
             else d = bias;
178 222
 
179 223
             SERIAL_PROTOCOLPGM(" bias: "); SERIAL_PROTOCOL(bias);
@@ -210,7 +254,10 @@ void PID_autotune(float temp)
210 254
               */
211 255
             }
212 256
           }
213
-          soft_pwm[0] = (bias + d) >> 1;
257
+					if (extruder<0)
258
+						soft_pwm_bed = (bias + d) >> 1;
259
+					else
260
+						soft_pwm[extruder] = (bias + d) >> 1;
214 261
           cycles++;
215 262
           min=temp;
216 263
         }
@@ -221,17 +268,26 @@ void PID_autotune(float temp)
221 268
       return;
222 269
     }
223 270
     if(millis() - temp_millis > 2000) {
224
-      temp_millis = millis();
225
-      SERIAL_PROTOCOLPGM("ok T:");
226
-      SERIAL_PROTOCOL(degHotend(0));   
271
+			int p;
272
+			if (extruder<0){
273
+	      p=soft_pwm_bed;       
274
+	      SERIAL_PROTOCOLPGM("ok B:");
275
+			}else{
276
+	      p=soft_pwm[extruder];       
277
+	      SERIAL_PROTOCOLPGM("ok T:");
278
+			}
279
+			
280
+      SERIAL_PROTOCOL(input);   
227 281
       SERIAL_PROTOCOLPGM(" @:");
228
-      SERIAL_PROTOCOLLN(getHeaterPower(0));       
282
+      SERIAL_PROTOCOLLN(p);       
283
+
284
+      temp_millis = millis();
229 285
     }
230 286
     if(((millis() - t1) + (millis() - t2)) > (10L*60L*1000L*2L)) {
231 287
       SERIAL_PROTOCOLLNPGM("PID Autotune failed! timeout");
232 288
       return;
233 289
     }
234
-    if(cycles > 5) {
290
+    if(cycles > ncycles) {
235 291
       SERIAL_PROTOCOLLNPGM("PID Autotune finished ! Place the Kp, Ki and Kd constants in the configuration.h");
236 292
       return;
237 293
     }
@@ -246,18 +302,19 @@ void updatePID()
246 302
      temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;  
247 303
   }
248 304
 #endif
305
+#ifdef PIDTEMPBED
306
+  temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;  
307
+#endif
249 308
 }
250 309
   
251 310
 int getHeaterPower(int heater) {
311
+	if (heater<0)
312
+		return soft_pwm_bed;
252 313
   return soft_pwm[heater];
253 314
 }
254 315
 
255 316
 void manage_heater()
256 317
 {
257
-#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
258
-  static int bed_needs_heating=0;
259
-  static int bed_is_on=0;
260
-#endif
261 318
 
262 319
   #ifdef USE_WATCHDOG
263 320
     wd_reset();
@@ -298,12 +355,16 @@ void manage_heater()
298 355
           temp_iState[e] += pid_error[e];
299 356
           temp_iState[e] = constrain(temp_iState[e], temp_iState_min[e], temp_iState_max[e]);
300 357
           iTerm[e] = Ki * temp_iState[e];
358
+
301 359
           //K1 defined in Configuration.h in the PID settings
302 360
           #define K2 (1.0-K1)
303 361
           dTerm[e] = (Kd * (pid_input - temp_dState[e]))*K2 + (K1 * dTerm[e]);
304 362
           temp_dState[e] = pid_input;
363
+
305 364
           pid_output = constrain(pTerm[e] + iTerm[e] - dTerm[e], 0, PID_MAX);
306 365
         }
366
+    #else 
367
+          pid_output = constrain(pid_setpoint[e], 0, PID_MAX);
307 368
     #endif //PID_OPENLOOP
308 369
     #ifdef PID_DEBUG
309 370
     SERIAL_ECHOLN(" PIDDEBUG "<<e<<": Input "<<pid_input<<" Output "<<pid_output" pTerm "<<pTerm[e]<<" iTerm "<<iTerm[e]<<" dTerm "<<dTerm[e]);  
@@ -338,42 +399,58 @@ void manage_heater()
338 399
     }
339 400
   #endif
340 401
   
341
-#ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
342
-  if (bed_needs_heating){
343
-    if (bed_is_on==0)
344
-        WRITE(HEATER_BED_PIN,HIGH);
345
-    if (bed_is_on==1)
346
-        WRITE(HEATER_BED_PIN,LOW);
347
-    bed_is_on=(bed_is_on+1) % HEATER_BED_DUTY_CYCLE_DIVIDER;
348
-  }
349
-#endif
350 402
 
403
+		#ifndef PIDTEMPBED
351 404
   if(millis() - previous_millis_bed_heater < BED_CHECK_INTERVAL)
352 405
     return;
353 406
   previous_millis_bed_heater = millis();
354
-  
407
+    #endif
408
+
355 409
   #if TEMP_BED_PIN > -1
356 410
   
357
-    #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
358
-    bed_needs_heating=0;
359
-    #endif
411
+		#ifdef PIDTEMPBED
412
+    pid_input = analog2tempBed(current_raw_bed);
360 413
 
361
-    #ifndef BED_LIMIT_SWITCHING
414
+    #ifndef PID_OPENLOOP
415
+		  pid_error_bed = pid_setpoint_bed - pid_input;
416
+		  pTerm_bed = bedKp * pid_error_bed;
417
+		  temp_iState_bed += pid_error_bed;
418
+		  temp_iState_bed = constrain(temp_iState_bed, temp_iState_min_bed, temp_iState_max_bed);
419
+		  iTerm_bed = bedKi * temp_iState_bed;
420
+
421
+		  //K1 defined in Configuration.h in the PID settings
422
+		  #define K2 (1.0-K1)
423
+		  dTerm_bed= (bedKd * (pid_input - temp_dState_bed))*K2 + (K1 * dTerm_bed);
424
+		  temp_dState_bed = pid_input;
425
+
426
+		  pid_output = constrain(pTerm_bed + iTerm_bed - dTerm_bed, 0, MAX_BED_POWER);
427
+
428
+    #else 
429
+      pid_output = constrain(pid_setpoint_bed, 0, MAX_BED_POWER);
430
+    #endif //PID_OPENLOOP
431
+
432
+	  if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) 
433
+	  {
434
+	    soft_pwm_bed = (int)pid_output >> 1;
435
+	  }
436
+	  else {
437
+	    soft_pwm_bed = 0;
438
+	  }
439
+
440
+    #elif not defined BED_LIMIT_SWITCHING
362 441
       // Check if temperature is within the correct range
363 442
       if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
364 443
         if(current_raw_bed >= target_raw_bed)
365 444
         {
366
-          WRITE(HEATER_BED_PIN,LOW);
445
+					soft_pwm_bed = 0;
367 446
         }
368 447
         else 
369 448
         {
370
-          #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
371
-          bed_needs_heating=1;
372
-          #endif
373
-          WRITE(HEATER_BED_PIN,HIGH);
449
+					soft_pwm_bed = MAX_BED_POWER>>1;
374 450
         }
375 451
       }
376 452
       else {
453
+					soft_pwm_bed = 0;
377 454
         WRITE(HEATER_BED_PIN,LOW);
378 455
       }
379 456
     #else //#ifdef BED_LIMIT_SWITCHING
@@ -381,18 +458,16 @@ void manage_heater()
381 458
       if((current_raw_bed > bed_minttemp) && (current_raw_bed < bed_maxttemp)) {
382 459
         if(current_raw_bed > target_bed_high_temp)
383 460
         {
384
-          WRITE(HEATER_BED_PIN,LOW);
461
+					soft_pwm_bed = 0;
385 462
         }
386 463
         else 
387 464
           if(current_raw_bed <= target_bed_low_temp)
388 465
         {
389
-          #ifdef HEATER_BED_DUTY_CYCLE_DIVIDER
390
-          bed_needs_heating=1;
391
-          #endif
392
-          WRITE(HEATER_BED_PIN,HIGH);
466
+					soft_pwm_bed = MAX_BED_POWER>>1;
393 467
         }
394 468
       }
395 469
       else {
470
+					soft_pwm_bed = 0;
396 471
         WRITE(HEATER_BED_PIN,LOW);
397 472
       }
398 473
     #endif
@@ -568,6 +643,10 @@ void tp_init()
568 643
     temp_iState_min[e] = 0.0;
569 644
     temp_iState_max[e] = PID_INTEGRAL_DRIVE_MAX / Ki;
570 645
 #endif //PIDTEMP
646
+#ifdef PIDTEMPBED
647
+    temp_iState_min_bed = 0.0;
648
+    temp_iState_max_bed = PID_INTEGRAL_DRIVE_MAX / bedKi;
649
+#endif //PIDTEMPBED
571 650
   }
572 651
 
573 652
   #if (HEATER_0_PIN > -1) 
@@ -728,6 +807,7 @@ void disable_heater()
728 807
 
729 808
   #if TEMP_BED_PIN > -1
730 809
     target_raw_bed=0;
810
+    soft_pwm_bed=0;
731 811
     #if HEATER_BED_PIN > -1  
732 812
       WRITE(HEATER_BED_PIN,LOW);
733 813
     #endif
@@ -832,6 +912,7 @@ ISR(TIMER0_COMPB_vect)
832 912
   static unsigned char soft_pwm_0;
833 913
   static unsigned char soft_pwm_1;
834 914
   static unsigned char soft_pwm_2;
915
+  static unsigned char soft_pwm_b;
835 916
   
836 917
   if(pwm_count == 0){
837 918
     soft_pwm_0 = soft_pwm[0];
@@ -844,6 +925,10 @@ ISR(TIMER0_COMPB_vect)
844 925
     soft_pwm_2 = soft_pwm[2];
845 926
     if(soft_pwm_2 > 0) WRITE(HEATER_2_PIN,1);
846 927
     #endif
928
+    #if HEATER_BED_PIN > -1
929
+    soft_pwm_b = soft_pwm_bed;
930
+    if(soft_pwm_b > 0) WRITE(HEATER_BED_PIN,1);
931
+    #endif
847 932
   }
848 933
   if(soft_pwm_0 <= pwm_count) WRITE(HEATER_0_PIN,0);
849 934
   #if EXTRUDERS > 1
@@ -852,6 +937,9 @@ ISR(TIMER0_COMPB_vect)
852 937
   #if EXTRUDERS > 2
853 938
   if(soft_pwm_2 <= pwm_count) WRITE(HEATER_2_PIN,0);
854 939
   #endif
940
+  #if HEATER_BED_PIN > -1
941
+  if(soft_pwm_b <= pwm_count) WRITE(HEATER_BED_PIN,0);
942
+  #endif
855 943
   
856 944
   pwm_count++;
857 945
   pwm_count &= 0x7f;

+ 10
- 4
Marlin/temperature.h Просмотреть файл

@@ -46,11 +46,15 @@ extern int current_raw_bed;
46 46
   extern int target_bed_low_temp ;  
47 47
   extern int target_bed_high_temp ;
48 48
 #endif
49
-extern float Kp,Ki,Kd,Kc;
50 49
 
51 50
 #ifdef PIDTEMP
51
+  extern float Kp,Ki,Kd,Kc;
52 52
   extern float pid_setpoint[EXTRUDERS];
53 53
 #endif
54
+#ifdef PIDTEMPBED
55
+  extern float bedKp,bedKi,bedKd;
56
+  extern float pid_setpoint_bed;
57
+#endif
54 58
   
55 59
 // #ifdef WATCHPERIOD
56 60
   extern int watch_raw[EXTRUDERS] ;
@@ -88,7 +92,9 @@ FORCE_INLINE void setTargetHotend(const float &celsius, uint8_t extruder) {
88 92
 FORCE_INLINE void setTargetBed(const float &celsius) {  
89 93
   
90 94
   target_raw_bed = temp2analogBed(celsius);
91
-  #ifdef BED_LIMIT_SWITCHING
95
+	#ifdef PIDTEMPBED
96
+  pid_setpoint_bed = celsius;
97
+  #elif defined BED_LIMIT_SWITCHING
92 98
     if(celsius>BED_HYSTERESIS)
93 99
     {
94 100
     target_bed_low_temp= temp2analogBed(celsius-BED_HYSTERESIS);
@@ -163,7 +169,7 @@ FORCE_INLINE void autotempShutdown(){
163 169
  #endif
164 170
 }
165 171
 
166
-void PID_autotune(float temp);
172
+void PID_autotune(float temp, int extruder, int ncycles);
167 173
 
168 174
 #endif
169
-
175
+

+ 11
- 211
README.md Просмотреть файл

@@ -1,222 +1,22 @@
1 1
 WARNING: 
2 2
 --------
3
-THIS IS RELEASE CANDIDATE 2 FOR MARLIN 1.0.0
3
+This is an experimental modification to allow PID on your bed heater.
4 4
 
5
-The configuration is now split in two files
6
-Configuration.h for the normal settings
7
-Configuration_adv.h for the advanced settings
5
+This will run at the same frequency as the main PID loop.  Make sure you heater FET or SSR can do this. I use a fotek SSR-10DA and it's fine
8 6
 
9
-Gen7T is not supported.
7
+add something like this to you configuration (pulling this branch will get you this
10 8
 
11
-Quick Information
12
-===================
13
-This RepRap firmware is a mashup between <a href="https://github.com/kliment/Sprinter">Sprinter</a>, <a href="https://github.com/simen/grbl/tree">grbl</a> and many original parts.
9
+~~~~~~~~~~~~~~~~~~~~
10
+#define PIDTEMPBED
14 11
 
15
-Derived from Sprinter and Grbl by Erik van der Zalm.
16
-Sprinters lead developers are Kliment and caru.
17
-Grbls lead developer is Simen Svale Skogsrud. Sonney Jeon (Chamnit) improved some parts of grbl
18
-A fork by bkubicek for the Ultimaker was merged, and further development was aided by him.
19
-Some features have been added by:
20
-Lampmaker, Bradley Feldman, and others...
12
+//from FOPDT model - kp=.39 Tp=405 Tdead=66, Tc set to 79.2, argressive factor of .15 (vs .1, 1, 10)
13
+    #define  DEFAULT_bedKp 10.00
14
+    #define  DEFAULT_bedKi .023
15
+    #define  DEFAULT_bedKd 305.4
16
+~~~~~~~~~~~~~~~~~~~~
21 17
 
22 18
 
23
-Features:
24
-
25
-*   Interrupt based movement with real linear acceleration
26
-*   High steprate
27
-*   Look ahead (Keep the speed high when possible. High cornering speed)
28
-*   Interrupt based temperature protection
29
-*   preliminary support for Matthew Roberts advance algorithm 
30
-    For more info see: http://reprap.org/pipermail/reprap-dev/2011-May/003323.html
31
-*   Full endstop support
32
-*   SD Card support
33
-*   SD Card folders (works in pronterface)
34
-*   SD Card autostart support
35
-*   LCD support (ideally 20x4) 
36
-*   LCD menu system for autonomous SD card printing, controlled by an click-encoder. 
37
-*   EEPROM storage of e.g. max-velocity, max-acceleration, and similar variables
38
-*   many small but handy things originating from bkubicek's fork.
39
-*   Arc support
40
-*   Temperature oversampling
41
-*   Dynamic Temperature setpointing aka "AutoTemp"
42
-*   Support for QTMarlin, a very beta GUI for PID-tuning and velocity-acceleration testing. https://github.com/bkubicek/QTMarlin
43
-*   Endstop trigger reporting to the host software.
44
-*   Updated sdcardlib
45
-*   Heater power reporting. Useful for PID monitoring.
46
-*   PID tuning
47
-*   CoreXY kinematics (www.corexy.com/theory.html)
48
-
49
-The default baudrate is 250000. This baudrate has less jitter and hence errors than the usual 115200 baud, but is less supported by drivers and host-environments.
50
-
51
-
52
-Differences and additions to the already good Sprinter firmware:
53
-================================================================
54
-
55
-*Look-ahead:*
56
-
57
-Marlin has look-ahead. While sprinter has to break and re-accelerate at each corner, 
58
-lookahead will only decelerate and accelerate to a velocity, 
59
-so that the change in vectorial velocity magnitude is less than the xy_jerk_velocity.
60
-This is only possible, if some future moves are already processed, hence the name. 
61
-It leads to less over-deposition at corners, especially at flat angles.
62
-
63
-*Arc support:*
64
-
65
-Slic3r can find curves that, although broken into segments, were ment to describe an arc.
66
-Marlin is able to print those arcs. The advantage is the firmware can choose the resolution,
67
-and can perform the arc with nearly constant velocity, resulting in a nice finish. 
68
-Also, less serial communication is needed.
69
-
70
-*Temperature Oversampling:*
71
-
72
-To reduce noise and make the PID-differential term more useful, 16 ADC conversion results are averaged.
73
-
74
-*AutoTemp:*
75
-
76
-If your gcode contains a wide spread of extruder velocities, or you realtime change the building speed, the temperature should be changed accordingly.
77
-Usually, higher speed requires higher temperature.
78
-This can now be performed by the AutoTemp function
79
-By calling M109 S<mintemp> T<maxtemp> F<factor> you enter the autotemp mode.
80
-
81
-You can leave it by calling M109 without any F.
82
-If active, the maximal extruder stepper rate of all buffered moves will be calculated, and named "maxerate" [steps/sec].
83
-The wanted temperature then will be set to t=tempmin+factor*maxerate, while being limited between tempmin and tempmax.
84
-If the target temperature is set manually or by gcode to a value less then tempmin, it will be kept without change.
85
-Ideally, your gcode can be completely free of temperature controls, apart from a M109 S T F in the start.gcode, and a M109 S0 in the end.gcode.
86
-
87
-*EEPROM:*
88
-
89
-If you know your PID values, the acceleration and max-velocities of your unique machine, you can set them, and finally store them in the EEPROM.
90
-After each reboot, it will magically load them from EEPROM, independent what your Configuration.h says.
91
-
92
-*LCD Menu:*
93
-
94
-If your hardware supports it, you can build yourself a LCD-CardReader+Click+encoder combination. It will enable you to realtime tune temperatures,
95
-accelerations, velocities, flow rates, select and print files from the SD card, preheat, disable the steppers, and do other fancy stuff.
96
-One working hardware is documented here: http://www.thingiverse.com/thing:12663 
97
-Also, with just a 20x4 or 16x2 display, useful data is shown.
98
-
99
-*SD card folders:*
100
-
101
-If you have an SD card reader attached to your controller, also folders work now. Listing the files in pronterface will show "/path/subpath/file.g".
102
-You can write to file in a subfolder by specifying a similar text using small letters in the path.
103
-Also, backup copies of various operating systems are hidden, as well as files not ending with ".g".
104
-
105
-*SD card folders:*
106
-
107
-If you place a file auto[0-9].g into the root of the sd card, it will be automatically executed if you boot the printer. The same file will be executed by selecting "Autostart" from the menu.
108
-First *0 will be performed, than *1 and so on. That way, you can heat up or even print automatically without user interaction.
109
-
110
-*Endstop trigger reporting:*
111
-
112
-If an endstop is hit while moving towards the endstop, the location at which the firmware thinks that the endstop was triggered is outputed on the serial port.
113
-This is useful, because the user gets a warning message.
114
-However, also tools like QTMarlin can use this for finding acceptable combinations of velocity+acceleration.
115
-
116
-*Coding paradigm:*
117
-
118
-Not relevant from a user side, but Marlin was split into thematic junks, and has tried to partially enforced private variables.
119
-This is intended to make it clearer, what interacts which what, and leads to a higher level of modularization.
120
-We think that this is a useful prestep for porting this firmware to e.g. an ARM platform in the future.
121
-A lot of RAM (with enabled LCD ~2200 bytes) was saved by storing char []="some message" in Program memory.
122
-In the serial communication, a #define based level of abstraction was enforced, so that it is clear that
123
-some transfer is information (usually beginning with "echo:"), an error "error:", or just normal protocol,
124
-necessary for backwards compatibility.
125
-
126
-*Interrupt based temperature measurements:*
127
-
128
-An interrupt is used to manage ADC conversions, and enforce checking for critical temperatures.
129
-This leads to less blocking in the heater management routine.
130
-
131
-
132
-Non-standard M-Codes, different to an old version of sprinter:
133
-==============================================================
134
-Movement:
135
-
136
-*   G2  - CW ARC
137
-*   G3  - CCW ARC
138
-
139
-General:
140
-
141
-*   M17  - Enable/Power all stepper motors. Compatibility to ReplicatorG.
142
-*   M18  - Disable all stepper motors; same as M84.Compatibility to ReplicatorG.
143
-*   M30  - Print time since last M109 or SD card start to serial
144
-*   M42  - Change pin status via gcode
145
-*   M80  - Turn on Power Supply
146
-*   M81  - Turn off Power Supply
147
-*   M114 - Output current position to serial port 
148
-*   M119 - Output Endstop status to serial port
149
-
150
-Movement variables:
151
-
152
-*   M202 - Set max acceleration in units/s^2 for travel moves (M202 X1000 Y1000) Unused in Marlin!!
153
-*   M203 - Set maximum feedrate that your machine can sustain (M203 X200 Y200 Z300 E10000) in mm/sec
154
-*   M204 - Set default acceleration: S normal moves T filament only moves (M204 S3000 T7000) im mm/sec^2  also sets minimum segment time in ms (B20000) to prevent buffer underruns and M20 minimum feedrate
155
-*   M206 - set home offsets.  This sets the X,Y,Z coordinates of the endstops (and is added to the {X,Y,Z}_HOME_POS configuration options (and is also added to the coordinates, if any, provided to G82, as with earlier firmware)
156
-*   M220 - set build speed mulitplying S:factor in percent ; aka "realtime tuneing in the gcode". So you can slow down if you have islands in one height-range, and speed up otherwise.
157
-*   M221 - set the extrude multiplying S:factor in percent
158
-*   M400 - Finish all buffered moves.
159
-
160
-Temperature variables:
161
-*   M301 - Set PID parameters P I and D
162
-*   M302 - Allow cold extrudes
163
-*   M303 - PID relay autotune S<temperature> sets the target temperature. (default target temperature = 150C)
164
-
165
-Advance:
166
-
167
-*   M200 - Set filament diameter for advance
168
-*   M205 - advanced settings:  minimum travel speed S=while printing T=travel only,  B=minimum segment time X= maximum xy jerk, Z=maximum Z jerk
169
-
170
-EEPROM:
171
-
172
-*   M500 - stores paramters in EEPROM. This parameters are stored:  axis_steps_per_unit,  max_feedrate, max_acceleration  ,acceleration,retract_acceleration,
173
-  minimumfeedrate,mintravelfeedrate,minsegmenttime,  jerk velocities, PID
174
-*   M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).  
175
-*   M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
176
-*   M503 - print the current settings (from memory not from eeprom)
177
-
178
-MISC:
179
-
180
-*   M240 - Trigger a camera to take a photograph
181
-*   M999 - Restart after being stopped by error
182
-
183
-Configuring and compilation:
184
-============================
185
-
186
-Install the arduino software IDE/toolset v22
187
-   http://www.arduino.cc/en/Main/Software
188
-
189
-For gen6 and sanguinololu the Sanguino directory in the Marlin dir needs to be copied to the arduino environment.
190
-  copy Marlin\sanguino <arduino home>\hardware\Sanguino
191
-
192
-Install Ultimaker's RepG 25 build
193
-    http://software.ultimaker.com
194
-For SD handling and as better substitute (apart from stl manipulation) download
195
-the very nice Kliment's printrun/pronterface  https://github.com/kliment/Printrun
196
-
197
-Copy the Ultimaker Marlin firmware
198
-   https://github.com/ErikZalm/Marlin/tree/Marlin_v1
199
-   (Use the download button)
200
-
201
-Start the arduino IDE.
202
-Select Tools -> Board -> Arduino Mega 2560    or your microcontroller
203
-Select the correct serial port in Tools ->Serial Port
204
-Open Marlin.pde
205
-
206
-Click the Verify/Compile button
207
-
208
-Click the Upload button
209
-If all goes well the firmware is uploading
210
-
211
-Start Ultimaker's Custom RepG 25
212
-Make sure Show Experimental Profiles is enabled in Preferences
213
-Select Sprinter as the Driver
214
-
215
-Press the Connect button.
216
-
217
-KNOWN ISSUES: RepG will display:  Unknown: marlin x.y.z
218
-
219
-That's ok.  Enjoy Silky Smooth Printing.
19
+Autotune works for the bed.  Give it an "M303 E-1 C8 S90" to run autotune on the bed at 90 degrees for 8 cycles.
220 20
 
221 21
 
222 22
 

Загрузка…
Отмена
Сохранить