Browse Source

Real-time filament diameter measurement and control

This feature allows the printer to read the filament diameter
automatically and adjust the printer in real time.  Added code to read
an analog voltage that represents a filament diameter measurement.  This
measurement is delayed in a ring buffer to compensate for sensors that
are a distance away from the extruder.  The measurement is used to
adjust the volumetric_multiplier for the extruder.  Some additional g
codes (M404, M405, M406, M407) are used to set parameters and turn
on/off the control. g code M221 is updated.  Pins for RAMPS1.4, RAMBO,
and Printrboard are identified for analog input.  The configuration file
is updated with relevant user parameters.
Filip Mulier 10 years ago
parent
commit
85649a4549
7 changed files with 289 additions and 7 deletions
  1. 30
    0
      Marlin/Configuration.h
  2. 10
    0
      Marlin/Marlin.h
  3. 83
    1
      Marlin/Marlin_main.cpp
  4. 16
    0
      Marlin/pins.h
  5. 31
    0
      Marlin/planner.cpp
  6. 111
    6
      Marlin/temperature.cpp
  7. 8
    0
      Marlin/temperature.h

+ 30
- 0
Marlin/Configuration.h View File

@@ -755,6 +755,36 @@ const bool Z_MAX_ENDSTOP_INVERTING = true; // set to true to invert the logic of
755 755
 //#define SERVO_ENDSTOPS {-1, -1, 0} // Servo index for X, Y, Z. Disable with -1
756 756
 //#define SERVO_ENDSTOP_ANGLES {0,0, 0,0, 70,0} // X,Y,Z Axis Extend and Retract angles
757 757
 
758
+/**********************************************************************\
759
+ * Support for a filament diameter sensor
760
+ * Also allows adjustment of diameter at print time (vs  at slicing)
761
+ * Single extruder only at this point (extruder 0)
762
+ * 
763
+ * Motherboards
764
+ * 34 - RAMPS1.4 - uses Analog input 5 on the AUX2 connector 
765
+ * 81 - Printrboard - Uses Analog input 2 on the Aux 2 connector
766
+ * 301 - Rambo  - uses Analog input 3
767
+ * Note may require analog pins to be defined for different motherboards
768
+ **********************************************************************/
769
+#define FILAMENT_SENSOR
770
+#define FILAMENT_SENSOR_EXTRUDER_NUM	0  //The number of the extruder that has the filament sensor (0,1,2)
771
+#define MEASUREMENT_DELAY_CM			14  //measurement delay in cm.  This is the distance from filament sensor to middle of barrel
772
+
773
+#define DEFAULT_NOMINAL_FILAMENT_DIA  3.0  //Enter the diameter (in mm) of the filament generally used (3.0 mm or 1.75 mm).  Used for sensor reading validation
774
+#define MEASURED_UPPER_LIMIT          3.30  //upper limit factor used for sensor reading validation in mm
775
+#define MEASURED_LOWER_LIMIT          1.90  //lower limit factor for sensor reading validation in mm
776
+#define MAX_MEASUREMENT_DELAY			20  //delay buffer size in bytes (1 byte = 1cm)- limits maximum measurement delay allowable (must be larger than MEASUREMENT_DELAY_CM  and lower number saves RAM)
777
+
778
+//defines used in the code
779
+#define DEFAULT_MEASURED_FILAMENT_DIA  DEFAULT_NOMINAL_FILAMENT_DIA  //set measured to nominal initially 
780
+#define STANDARD_DIA					1.12837915  //The diameter of filament that has a cross sectional area of 1 square mm.  This dia should be used in the slicer software settings
781
+
782
+
783
+
784
+
785
+
786
+
787
+
758 788
 #include "Configuration_adv.h"
759 789
 #include "thermistortables.h"
760 790
 

+ 10
- 0
Marlin/Marlin.h View File

@@ -229,6 +229,16 @@ extern int EtoPPressure;
229 229
 extern unsigned char fanSpeedSoftPwm;
230 230
 #endif
231 231
 
232
+#ifdef FILAMENT_SENSOR
233
+  extern volatile float filament_width_nominal;  //holds the theoretical filament diameter ie., 3.00 or 1.75 
234
+  extern volatile bool filament_sensor;  //indicates that filament sensor readings should control extrusion  
235
+  extern float filament_width_meas; //holds the filament diameter as accurately measured 
236
+  extern signed char measurement_delay[];  //ring buffer to delay measurement
237
+  extern int delay_index1, delay_index2;  //index into ring buffer
238
+  extern float delay_dist; //delay distance counter
239
+  extern int meas_delay_cm; //delay distance
240
+#endif
241
+
232 242
 #ifdef FWRETRACT
233 243
 extern bool autoretract_enabled;
234 244
 extern bool retracted[EXTRUDERS];

+ 83
- 1
Marlin/Marlin_main.cpp View File

@@ -157,6 +157,10 @@
157 157
 // M400 - Finish all moves
158 158
 // M401 - Lower z-probe if present
159 159
 // M402 - Raise z-probe if present
160
+// M404 - N<dia in mm> Enter the nominal filament width (3mm, 1.75mm ) or will display nominal filament width without parameters
161
+// M405 - Turn on Filament Sensor extrusion control.  Optional D<delay in cm> to set delay in centimeters between sensor and extruder 
162
+// M406 - Turn off Filament Sensor extrusion control 
163
+// M407 - Displays measured filament diameter 
160 164
 // M500 - stores parameters in EEPROM
161 165
 // M501 - reads parameters from EEPROM (if you need reset them after you changed them temporarily).
162 166
 // M502 - reverts to the default "factory settings".  You still need to store them in EEPROM afterwards if you want to.
@@ -296,6 +300,18 @@ int EtoPPressure=0;
296 300
 
297 301
 bool cancel_heatup = false ;
298 302
 
303
+#ifdef FILAMENT_SENSOR
304
+  //Variables for Filament Sensor input 
305
+  volatile float filament_width_nominal=DEFAULT_NOMINAL_FILAMENT_DIA;  //Set nominal filament width, can be changed with M404 
306
+  volatile bool filament_sensor=false;  //M405 turns on filament_sensor control, M406 turns it off 
307
+  float filament_width_meas=DEFAULT_MEASURED_FILAMENT_DIA; //Stores the measured filament diameter 
308
+  signed char measurement_delay[MAX_MEASUREMENT_DELAY+1];  //ring buffer to delay measurement  store extruder factor after subtracting 100 
309
+  int delay_index1=0;
310
+  int delay_index2=0;  //index into ring buffer
311
+  float delay_dist=0; //delay distance counter  
312
+  int meas_delay_cm = MEASUREMENT_DELAY_CM;  //distance delay setting
313
+#endif
314
+
299 315
 //===========================================================================
300 316
 //=============================Private Variables=============================
301 317
 //===========================================================================
@@ -2317,7 +2333,13 @@ void process_commands()
2317 2333
           }
2318 2334
         } else {
2319 2335
           //reserved for setting filament diameter via UFID or filament measuring device
2320
-          break;
2336
+        	if(active_extruder == FILAMENT_SENSOR_EXTRUDER_NUM){
2337
+        		radius = analog2widthFil() * 0.5;
2338
+        		area = M_PI * pow(radius, 2);
2339
+        	}else{
2340
+        		area = 1.0;
2341
+        	}
2342
+          
2321 2343
         }
2322 2344
         tmp_extruder = active_extruder;
2323 2345
         if(code_seen('T')) {
@@ -2771,6 +2793,66 @@ void process_commands()
2771 2793
     }
2772 2794
     break;
2773 2795
 #endif
2796
+
2797
+#ifdef FILAMENT_SENSOR
2798
+case 404:  //M404 Enter the nominal filament width (3mm, 1.75mm ) N<3.0> or display nominal filament width 
2799
+    {
2800
+    #if (FILWIDTH_PIN > -1) 
2801
+    if(code_seen('N')) filament_width_nominal=code_value();
2802
+    else{
2803
+    SERIAL_PROTOCOLPGM("Filament dia (nominal mm):"); 
2804
+    SERIAL_PROTOCOLLN(filament_width_nominal); 
2805
+    }
2806
+    #endif
2807
+    }
2808
+    break; 
2809
+    
2810
+    case 405:  //M405 Turn on filament sensor for control 
2811
+    {
2812
+    
2813
+    
2814
+    if(code_seen('D')) meas_delay_cm=code_value();
2815
+       
2816
+       if(meas_delay_cm> MAX_MEASUREMENT_DELAY)
2817
+       	meas_delay_cm = MAX_MEASUREMENT_DELAY;
2818
+    
2819
+    filament_sensor = true ; 
2820
+    int temp_ratio = widthFil_to_size_ratio(); 
2821
+    
2822
+    for (delay_index1=0; delay_index1<(MAX_MEASUREMENT_DELAY+1); ++delay_index1 ){
2823
+              measurement_delay[delay_index1]=temp_ratio-100;  //subtract 100 to scale within a signed byte
2824
+        }
2825
+    delay_index1=0;
2826
+    delay_index2=0;
2827
+              
2828
+    //SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); 
2829
+    //SERIAL_PROTOCOL(filament_width_meas); 
2830
+    //SERIAL_PROTOCOLPGM("Extrusion ratio(%):"); 
2831
+    //SERIAL_PROTOCOL(extrudemultiply); 
2832
+    } 
2833
+    break; 
2834
+    
2835
+    case 406:  //M406 Turn off filament sensor for control 
2836
+    {      
2837
+    filament_sensor = false ; 
2838
+    } 
2839
+    break; 
2840
+  
2841
+    case 407:   //M407 Display measured filament diameter 
2842
+    { 
2843
+     
2844
+    filament_width_meas = code_value(); 
2845
+    
2846
+    SERIAL_PROTOCOLPGM("Filament dia (measured mm):"); 
2847
+    SERIAL_PROTOCOLLN(filament_width_meas);   
2848
+    } 
2849
+    break; 
2850
+    #endif
2851
+    
2852
+
2853
+
2854
+
2855
+
2774 2856
     case 500: // M500 Store settings in EEPROM
2775 2857
     {
2776 2858
         Config_StoreSettings();

+ 16
- 0
Marlin/pins.h View File

@@ -558,6 +558,15 @@
558 558
     #define E1_DIR_PIN         34
559 559
     #define E1_ENABLE_PIN      30
560 560
 
561
+#if MOTHERBOARD == 34  //FMM added for Filament Extruder
562
+#ifdef FILAMENT_SENSOR
563
+	  //define analog pin for the filament width sensor input
564
+	  //Use the RAMPS 1.4 Analog input 5 on the AUX2 connector
565
+      #define FILWIDTH_PIN        5
566
+#endif
567
+#endif
568
+
569
+
561 570
     #if MOTHERBOARD == 68
562 571
       #define E2_STEP_PIN        23
563 572
       #define E2_DIR_PIN         25
@@ -1692,6 +1701,9 @@
1692 1701
   #define Z_STOP_PIN         36
1693 1702
   #define TEMP_0_PIN          1  // Extruder / Analog pin numbering
1694 1703
   #define TEMP_BED_PIN        0  // Bed / Analog pin numbering
1704
+  #ifdef FILAMENT_SENSOR
1705
+   #define FILWIDTH_PIN        2
1706
+  #endif //FILAMENT_SENSOR
1695 1707
 #endif
1696 1708
 
1697 1709
 #define TEMP_1_PIN         -1
@@ -2326,6 +2338,10 @@ DaveX plan for Teensylu/printrboard-type pinouts (ref teensylu & sprinter) for a
2326 2338
   #endif
2327 2339
 #endif //ULTRA_LCD
2328 2340
 
2341
+#ifdef FILAMENT_SENSOR
2342
+  //Filip added pin for Filament sensor analog input 
2343
+  #define FILWIDTH_PIN        3
2344
+#endif //FILAMENT_SENSOR
2329 2345
 
2330 2346
 #endif
2331 2347
 

+ 31
- 0
Marlin/planner.cpp View File

@@ -117,6 +117,10 @@ static long x_segment_time[3]={MAX_FREQ_TIME + 1,0,0};     // Segment times (in
117 117
 static long y_segment_time[3]={MAX_FREQ_TIME + 1,0,0};
118 118
 #endif
119 119
 
120
+#ifdef FILAMENT_SENSOR
121
+ static char meas_sample; //temporary variable to hold filament measurement sample
122
+#endif
123
+
120 124
 // Returns the index of the next block in the ring buffer
121 125
 // NOTE: Removed modulo (%) operator, which uses an expensive divide and multiplication.
122 126
 static int8_t next_block_index(int8_t block_index) {
@@ -737,6 +741,33 @@ block->steps_y = labs((target[X_AXIS]-position[X_AXIS]) - (target[Y_AXIS]-positi
737 741
   block->nominal_speed = block->millimeters * inverse_second; // (mm/sec) Always > 0
738 742
   block->nominal_rate = ceil(block->step_event_count * inverse_second); // (step/sec) Always > 0
739 743
 
744
+#ifdef FILAMENT_SENSOR
745
+  //FMM update ring buffer used for delay with filament measurements
746
+    
747
+    if(filament_sensor && (extruder==0))  //only for extruder 0
748
+  	  {
749
+    delay_dist = delay_dist + delta_mm[E_AXIS];  //increment counter with next move in e axis
750
+    if (delay_dist> (10*(MAX_MEASUREMENT_DELAY+1)))  //check if counter is over max buffer size in mm
751
+      	  delay_dist = delay_dist - 10*(MAX_MEASUREMENT_DELAY+1);  //loop around the buffer
752
+      if(delay_dist<0)
753
+    	  delay_dist = delay_dist + 10*(MAX_MEASUREMENT_DELAY+1); //loop around the buffer
754
+    delay_index1=delay_dist/10;  //calculate index
755
+    if(delay_index1 != delay_index2)  //moved index
756
+  	  {
757
+    	meas_sample=widthFil_to_size_ratio()-100;  //subtract off 100 to reduce magnitude - to store in a signed char
758
+  	  }
759
+    while( delay_index1 != delay_index2)
760
+  	  {
761
+  	  delay_index2 = delay_index2 + 1;
762
+  	if(delay_index2>MAX_MEASUREMENT_DELAY)
763
+  			  delay_index2=delay_index2-(MAX_MEASUREMENT_DELAY+1);  //loop around buffer when incrementing
764
+  	  measurement_delay[delay_index2]=meas_sample;
765
+  	  }
766
+    
767
+  	  } 
768
+#endif
769
+
770
+
740 771
   // Calculate and limit speed in mm/sec for each axis
741 772
   float current_speed[4];
742 773
   float speed_factor = 1.0; //factor <=1 do decrease speed

+ 111
- 6
Marlin/temperature.cpp View File

@@ -71,7 +71,10 @@ unsigned char soft_pwm_bed;
71 71
 #ifdef BABYSTEPPING
72 72
   volatile int babystepsTodo[3]={0,0,0};
73 73
 #endif
74
-  
74
+
75
+#ifdef FILAMENT_SENSOR
76
+  int current_raw_filwidth = 0;  //Holds measured filament diameter - one extruder only
77
+#endif  
75 78
 //===========================================================================
76 79
 //=============================private variables============================
77 80
 //===========================================================================
@@ -158,6 +161,9 @@ unsigned long watchmillis[EXTRUDERS] = ARRAY_BY_EXTRUDERS(0,0,0);
158 161
 #define SOFT_PWM_SCALE 0
159 162
 #endif
160 163
 
164
+#ifdef FILAMENT_SENSOR
165
+  static int meas_shift_index;  //used to point to a delayed sample in buffer for filament width sensor
166
+#endif
161 167
 //===========================================================================
162 168
 //=============================   functions      ============================
163 169
 //===========================================================================
@@ -601,6 +607,21 @@ void manage_heater()
601 607
       }
602 608
     #endif
603 609
   #endif
610
+  
611
+//code for controlling the extruder rate based on the width sensor 
612
+#ifdef FILAMENT_SENSOR
613
+  if(filament_sensor) 
614
+	{
615
+	meas_shift_index=delay_index1-meas_delay_cm;
616
+		  if(meas_shift_index<0)
617
+			  meas_shift_index = meas_shift_index + (MAX_MEASUREMENT_DELAY+1);  //loop around buffer if needed
618
+		  
619
+		  //get the delayed info and add 100 to reconstitute to a percent of the nominal filament diameter
620
+		  //then adjust as a factor to the Standard Diameter (has an area of 1mm squared)
621
+		  //then square it to get an area
622
+		  volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = pow((float)(100+measurement_delay[meas_shift_index])/filament_width_nominal*STANDARD_DIA/100.0,2);
623
+	}
624
+#endif
604 625
 }
605 626
 
606 627
 #define PGM_RD_W(x)   (short)pgm_read_word(&x)
@@ -702,6 +723,40 @@ static void updateTemperaturesFromRawValues()
702 723
     CRITICAL_SECTION_END;
703 724
 }
704 725
 
726
+
727
+// For converting raw Filament Width to milimeters 
728
+#ifdef FILAMENT_SENSOR
729
+float analog2widthFil() { 
730
+return current_raw_filwidth/16383.0*5.0; 
731
+//return current_raw_filwidth; 
732
+} 
733
+ 
734
+// For converting raw Filament Width to an volumetric ratio 
735
+int widthFil_to_size_ratio() { 
736
+ 
737
+float temp; 
738
+   
739
+#if (FILWIDTH_PIN > -1)    //check if a sensor is supported 
740
+filament_width_meas=current_raw_filwidth/16383.0*5.0; 
741
+#endif   
742
+ 
743
+temp=filament_width_meas;
744
+if(filament_width_meas<MEASURED_LOWER_LIMIT)
745
+	temp=filament_width_nominal;  //assume sensor cut out
746
+else if (filament_width_meas>MEASURED_UPPER_LIMIT)
747
+	temp= MEASURED_UPPER_LIMIT;
748
+
749
+
750
+return(filament_width_nominal/temp*100); 
751
+
752
+
753
+} 
754
+#endif
755
+
756
+
757
+
758
+
759
+
705 760
 void tp_init()
706 761
 {
707 762
 #if (MOTHERBOARD == 80) && ((TEMP_SENSOR_0==-1)||(TEMP_SENSOR_1==-1)||(TEMP_SENSOR_2==-1)||(TEMP_SENSOR_BED==-1))
@@ -797,6 +852,17 @@ void tp_init()
797 852
     #endif
798 853
   #endif
799 854
   
855
+  //Added for Filament Sensor 
856
+  #ifdef FILAMENT_SENSOR
857
+   #if defined(FILWIDTH_PIN) && (FILWIDTH_PIN > -1) 
858
+	#if FILWIDTH_PIN < 8 
859
+       	   DIDR0 |= 1<<FILWIDTH_PIN;  
860
+	#else 
861
+       	   DIDR2 |= 1<<(FILWIDTH_PIN - 8);  
862
+	#endif 
863
+   #endif
864
+  #endif
865
+  
800 866
   // Use timer0 for temperature measurement
801 867
   // Interleave temperature interrupt with millies interrupt
802 868
   OCR0B = 128;
@@ -1109,7 +1175,7 @@ ISR(TIMER0_COMPB_vect)
1109 1175
   static unsigned long raw_temp_1_value = 0;
1110 1176
   static unsigned long raw_temp_2_value = 0;
1111 1177
   static unsigned long raw_temp_bed_value = 0;
1112
-  static unsigned char temp_state = 8;
1178
+  static unsigned char temp_state = 10;
1113 1179
   static unsigned char pwm_count = (1 << SOFT_PWM_SCALE);
1114 1180
   static unsigned char soft_pwm_0;
1115 1181
   #if (EXTRUDERS > 1) || defined(HEATERS_PARALLEL)
@@ -1122,6 +1188,10 @@ ISR(TIMER0_COMPB_vect)
1122 1188
   static unsigned char soft_pwm_b;
1123 1189
   #endif
1124 1190
   
1191
+  #if defined(FILWIDTH_PIN) &&(FILWIDTH_PIN > -1)
1192
+   static unsigned long raw_filwidth_value = 0;  //added for filament width sensor
1193
+  #endif
1194
+  
1125 1195
   if(pwm_count == 0){
1126 1196
     soft_pwm_0 = soft_pwm[0];
1127 1197
     if(soft_pwm_0 > 0) { 
@@ -1248,10 +1318,39 @@ ISR(TIMER0_COMPB_vect)
1248 1318
       #if defined(TEMP_2_PIN) && (TEMP_2_PIN > -1)
1249 1319
         raw_temp_2_value += ADC;
1250 1320
       #endif
1251
-      temp_state = 0;
1252
-      temp_count++;
1321
+      temp_state = 8;//change so that Filament Width is also measured
1322
+      
1253 1323
       break;
1254
-    case 8: //Startup, delay initial temp reading a tiny bit so the hardware can settle.
1324
+    case 8: //Prepare FILWIDTH 
1325
+     #if defined(FILWIDTH_PIN) && (FILWIDTH_PIN> -1) 
1326
+      #if FILWIDTH_PIN>7 
1327
+         ADCSRB = 1<<MUX5;
1328
+      #else
1329
+         ADCSRB = 0; 
1330
+      #endif 
1331
+      ADMUX = ((1 << REFS0) | (FILWIDTH_PIN & 0x07)); 
1332
+      ADCSRA |= 1<<ADSC; // Start conversion 
1333
+     #endif 
1334
+     lcd_buttons_update();       
1335
+     temp_state = 9; 
1336
+     break; 
1337
+    case 9:   //Measure FILWIDTH 
1338
+     #if defined(FILWIDTH_PIN) &&(FILWIDTH_PIN > -1) 
1339
+     //raw_filwidth_value += ADC;  //remove to use an IIR filter approach 
1340
+      if(ADC>102)  //check that ADC is reading a voltage > 0.5 volts, otherwise don't take in the data.
1341
+        {
1342
+    	raw_filwidth_value= raw_filwidth_value-(raw_filwidth_value>>7);  //multipliy raw_filwidth_value by 127/128
1343
+        
1344
+        raw_filwidth_value= raw_filwidth_value + ((unsigned long)ADC<<7);  //add new ADC reading 
1345
+        }
1346
+     #endif 
1347
+     temp_state = 0;   
1348
+      
1349
+     temp_count++;
1350
+     break;      
1351
+      
1352
+      
1353
+    case 10: //Startup, delay initial temp reading a tiny bit so the hardware can settle.
1255 1354
       temp_state = 0;
1256 1355
       break;
1257 1356
 //    default:
@@ -1260,7 +1359,7 @@ ISR(TIMER0_COMPB_vect)
1260 1359
 //      break;
1261 1360
   }
1262 1361
     
1263
-  if(temp_count >= OVERSAMPLENR) // 8 * 16 * 1/(16000000/64/256)  = 131ms.
1362
+  if(temp_count >= OVERSAMPLENR) // 10 * 16 * 1/(16000000/64/256)  = 164ms.
1264 1363
   {
1265 1364
     if (!temp_meas_ready) //Only update the raw values if they have been read. Else we could be updating them during reading.
1266 1365
     {
@@ -1276,6 +1375,12 @@ ISR(TIMER0_COMPB_vect)
1276 1375
 #endif
1277 1376
       current_temperature_bed_raw = raw_temp_bed_value;
1278 1377
     }
1378
+
1379
+//Add similar code for Filament Sensor - can be read any time since IIR filtering is used 
1380
+#if defined(FILWIDTH_PIN) &&(FILWIDTH_PIN > -1)
1381
+  current_raw_filwidth = raw_filwidth_value>>10;  //need to divide to get to 0-16384 range since we used 1/128 IIR filter approach 
1382
+#endif
1383
+    
1279 1384
     
1280 1385
     temp_meas_ready = true;
1281 1386
     temp_count = 0;

+ 8
- 0
Marlin/temperature.h View File

@@ -31,6 +31,14 @@
31 31
 void tp_init();  //initialize the heating
32 32
 void manage_heater(); //it is critical that this is called periodically.
33 33
 
34
+#ifdef FILAMENT_SENSOR
35
+// For converting raw Filament Width to milimeters 
36
+ float analog2widthFil(); 
37
+ 
38
+// For converting raw Filament Width to an extrusion ratio 
39
+ int widthFil_to_size_ratio();
40
+#endif
41
+
34 42
 // low level conversion routines
35 43
 // do not use these routines and variables outside of temperature.cpp
36 44
 extern int target_temperature[EXTRUDERS];  

Loading…
Cancel
Save