Marlin: FILAMENT SENSOR

Created on 7 Mar 2016  Â·  30Comments  Â·  Source: MarlinFirmware/Marlin

Good afternoon! I have successfully assembled filament sensor that outputs a voltage proportional to the diameter - 1 mm - 1V. But there is a problem in Marlin.

The MEASUREMENT_DELAY_CM works with a value of up to 5 cm. Moreover, during operation, the delay time randomly varies from 1 cm to 5 cm. And I have a "Bowden" - 69 cm !!!

Marlin - 1.1.0-RC3 - 01 December 2015 (the only version, which once earned the sensor).
Motherboards
34 - RAMPS1.4
The attachment settings
Video work:
https://youtu.be/W93dFxF425s

Please, HELP!!!!!!
I apologize for bad English.

default

Confirmed !

Most helpful comment

Thanks, it works!!!

All 30 comments

Submitting Configuration.h

CONFIGURATION.docx

@olegmorgun which delay ? LCD display delay ?

The delay in the change of "dia" and "factor" on the screen. "factor" coincide with the actual extrusion. And a compelling cost a maximum of 5-6 cm (took it by the number of wheel revolutions of the extruder)

The screen updates are "rare", the machine holds in its internals a more updated number than the one showing on screen.. just take a look at the XYZ coordinates, they all have delay in relation to the nozzle.

When printing, I manually sharply inflated diameter of 2 mm. Extrusion decreased in 1-2 seconds?

Extrusion and the "real" (seen on the model) and the screen

Perhaps with "MEASUREMENT DELAY CM" - 10-12 cm, and change "DIA" 1.7-1.8mm -. It is not noticeable.
But with a diameter of 1.5 - 1.9 mm and Bowden 69cm - all just awful!

I quickly looked into the code and this is where it calculates the delay.

https://github.com/MarlinFirmware/Marlin/blob/5a54204f723f7fd110b57d19f0de01cecd8d47e7/Marlin/temperature.cpp#L675

I didn't do the maths but maybe the MAX_MEASUREMENT_DELAY value is messing
the results?

Btw, will you share details on how to build a sensor like that, I'd like to
try it out. :)

-Nando
Sent from my Sinclair ZX81

On 9 March 2016 at 18:27, olegmorgun [email protected] wrote:

Perhaps with "MEASUREMENT DELAY CM" - 10-12 cm, and change "DIA" 1.7-1.8mm
-. It is not noticeable.
But with a diameter of 1.5 - 1.9 mm and Bowden 69cm - all just awful!

—
Reply to this email directly or view it on GitHub
https://github.com/MarlinFirmware/Marlin/issues/3106#issuecomment-194437125
.

Yes

There is a construction - http://forums.reprap.org/read.php?1,636034

Here's all the code that deals with the filament sensor. I'm placing this here for reference, so we can see it all in one convenient place.

Marlin_main.cpp :: gcode_M405:

inline void gcode_M405() {
  if (code_seen('D')) meas_delay_cm = code_value();
  NOMORE(meas_delay_cm, MAX_MEASUREMENT_DELAY);

  if (delay_index2 == -1) { //initialize the ring buffer if it has not been done since startup
    int temp_ratio = widthFil_to_size_ratio();

    for (delay_index1 = 0; delay_index1 < MAX_MEASUREMENT_DELAY + 1; ++delay_index1)
      measurement_delay[delay_index1] = temp_ratio - 100;  //subtract 100 to scale within a signed byte

    delay_index1 = delay_index2 = 0;
  }

  filament_sensor = true;

  //SERIAL_PROTOCOLPGM("Filament dia (measured mm):");
  //SERIAL_PROTOCOL(filament_width_meas);
  //SERIAL_PROTOCOLPGM("Extrusion ratio(%):");
  //SERIAL_PROTOCOL(extruder_multiplier[active_extruder]);
}

planner.cpp :: plan_buffer_line:

//FMM update ring buffer used for delay with filament measurements

if (extruder == FILAMENT_SENSOR_EXTRUDER_NUM && delay_index2 > -1) {  //only for extruder with filament sensor and if ring buffer is initialized

  const int MMD = MAX_MEASUREMENT_DELAY + 1, MMD10 = MMD * 10;

  delay_dist += delta_mm[E_AXIS];  // increment counter with next move in e axis
  while (delay_dist >= MMD10) delay_dist -= MMD10; // loop around the buffer
  while (delay_dist < 0) delay_dist += MMD10;

  delay_index1 = delay_dist / 10.0;  // calculate index
  delay_index1 = constrain(delay_index1, 0, MAX_MEASUREMENT_DELAY); // (already constrained above)

  if (delay_index1 != delay_index2) { // moved index
    meas_sample = widthFil_to_size_ratio() - 100;  // Subtract 100 to reduce magnitude - to store in a signed char
    while (delay_index1 != delay_index2) {
      // Increment and loop around buffer
      if (++delay_index2 >= MMD) delay_index2 -= MMD;
      delay_index2 = constrain(delay_index2, 0, MAX_MEASUREMENT_DELAY);
      measurement_delay[delay_index2] = meas_sample;
    }
  }
}

temperature.cpp :: manage_heater:

// Control the extruder rate based on the width sensor
if (filament_sensor) {
  meas_shift_index = delay_index1 - meas_delay_cm;
  if (meas_shift_index < 0) meas_shift_index += MAX_MEASUREMENT_DELAY + 1;  //loop around buffer if needed

  // Get the delayed info and add 100 to reconstitute to a percent of
  // the nominal filament diameter then square it to get an area
  meas_shift_index = constrain(meas_shift_index, 0, MAX_MEASUREMENT_DELAY);
  float vm = pow((measurement_delay[meas_shift_index] + 100.0) / 100.0, 2);
  NOLESS(vm, 0.01);
  volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = vm;
}

temperature.cpp :: ISR:

case Prepare_FILWIDTH:
  #if HAS_FILAMENT_SENSOR
    START_ADC(FILWIDTH_PIN);
  #endif
  lcd_buttons_update();
  temp_state = Measure_FILWIDTH;
  break;
case Measure_FILWIDTH:
  #if HAS_FILAMENT_SENSOR
    // raw_filwidth_value += ADC;  //remove to use an IIR filter approach
    if (ADC > 102) { //check that ADC is reading a voltage > 0.5 volts, otherwise don't take in the data.
      raw_filwidth_value -= (raw_filwidth_value >> 7); //multiply raw_filwidth_value by 127/128
      raw_filwidth_value += ((unsigned long)ADC << 7); //add new ADC reading
    }
  #endif
  temp_state = PrepareTemp_0;
  temp_count++;
  break;

. . .

if (temp_count >= OVERSAMPLENR) { // 10 * 16 * 1/(16000000/64/256)  = 164ms.
  ...
  current_raw_filwidth = raw_filwidth_value >> 10;  // Divide to get to 0-16384 range since we used 1/128 IIR filter approach
  ...
}

And some helpful functions in temperature.cpp…

static void updateTemperaturesFromRawValues() {
  ...
  filament_width_meas = analog2widthFil();
  ...
}
// Convert raw Filament Width to millimeters
float analog2widthFil() {
  return current_raw_filwidth / 16383.0 * 5.0;
  //return current_raw_filwidth;
}

// Convert raw Filament Width to a ratio
int widthFil_to_size_ratio() {
  float temp = filament_width_meas;
  if (temp < MEASURED_LOWER_LIMIT) temp = filament_width_nominal;  //assume sensor cut out
  else NOMORE(temp, MEASURED_UPPER_LIMIT);
  return filament_width_nominal / temp * 100;
}

This may be due to the temperature?
I use experimental "bed" - heating up to 100% restrict manually.
Tomorrow I will try normal mode.

No. Is independent of temperature:
https://youtu.be/5r7S8iTHB24
(Marlin settings according to the first post).

I spent more than 100 tests, and it seems to have understood the reason.
Delay Buffer "reset" after each "retract" !!!!!
After setting the "retract" = 0. it worked.
But with these settings to print a "Bowden" is not possible.

You mean the G92 E0 ?
if so have you tried the option Use relative E distances on the slicer ?

Slicer to put "Length" = 0. (Retraction)
And it worked.
Very good on the "simple" models.
Used filament diameter 1.45-1.80 mm

"Use relative E distances" - I not tried. Try?

When you set Retraction = 0 it means to disable retraction.
When you have the "standard" retraction options the slicer will do this:

G1 X48.995 Y121.066 E30.11655 ; movement -- take notice of the E value
G1 X48.995 Y121.780 E30.14652 ; movement -- E increasing
G1 X49.220 Y122.005 E30.15991 ; movement -- E increasing
G1 E28.15991 F2400.00000 ; Retract 28 < 30
G92 E0 ; Reset the extrusion counter
G1 X48.600 Y122.400 F7800.000 ; movement
G1 X44.600 Y118.400 F7800.000 ; movement
G1 X45.220 Y118.005 F7800.000 ; movement
G1 E2.00000 F2400.00000 ; start extruding again
G1 X44.995 Y117.780 E2.01338 F1800.000; movement -- take notice of the E value
G1 X44.995 Y117.066 E2.04336 ; movement -- E increasing
G1 X45.934 Y118.005 E2.09913 ; movement -- E increasing

I do believe activating Use relative E distances will stop the slicer from resetting the E counter by sending G92 E0 and use relative distance for every move.

I Tried.
"Length" = 6
"Use relative E distances" - Included
Does not work....resets...I do not know why

Reset as in printer reboot/reset ?

No. buffer reset.

@jbrazio So do you think reverse E movement is implicated here?

I searched into history and found 85649a4549bc0a3613f675149997210ad5ab26da which seems to be when it was merged into Marlin. Not much has change since then, I saw some reworks under your name but nothing fancy that at first sight could have broken the feature. Do you know if the feature was reliable since day one ? I find the feature's implementation code a bit odd but can't really put a finger on it. Nevertheless there are some points to consider that were introduced during the code rework.

temperature.cpp L713-L716

Before

volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] =
  pow((float)(100+measurement_delay[meas_shift_index])/filament_width_nominal*STANDARD_DIA/100.0,2);

After

meas_shift_index = constrain(meas_shift_index, 0, MAX_MEASUREMENT_DELAY);
float vm = pow((measurement_delay[meas_shift_index] + 100.0) / 100.0, 2);
NOLESS(vm, 0.01);
volumetric_multiplier[FILAMENT_SENSOR_EXTRUDER_NUM] = vm;

Where the filament_width_nominal*STANDARD_DIA part was lost.

planner.cpp L876-L878

if(delay_index2>MAX_MEASUREMENT_DELAY)
  delay_index2=delay_index2-(MAX_MEASUREMENT_DELAY+1);
measurement_delay[delay_index2]=meas_sample;

After

if (++delay_index2 >= MMD) delay_index2 -= MMD;
delay_index2 = constrain(delay_index2, 0, MAX_MEASUREMENT_DELAY);
measurement_delay[delay_index2] = meas_sample;

There was no constrain() which means we could have negative values.
extern signed char measurement_delay[];

@jbrazio The change in planner.cpp is fine. The only difference is that the index into the array is constrained. The values returned from the array can still be negative.

The change to temperature.cpp is more interesting. Some of that is presaged in these changes http://code.atxhs.org/MjrTom/marlin/commit/62db9848d3f9ffcfe73e74cc7069fb4fe2b63b64 – and one of the issues was that STANDARD_DIA was never defined.

Anyway, I will look again at the code more closely. If retraction is causing the problem, hopefully it's easy to patch….

It does appear that E going backward is not totally compatible with this feature. The block in temperature.cpp beginning with if (delay_index1 != delay_index2) { will sometimes be invoked on retraction, and then the code within that block will store a new measurement, and it might do some odd things (like overwrite the entire ring buffer). So it looks like the solution is to only get a new width measurement when the filament has moved forward, past the point where the previous measurement was taken.

Ok, so #3415 should make it work better. With these changes, measurement will only occur when E has moved forward past the point where the last measurement was taken. This is only my first draft, so give it a try and see if it actually fixes the issue.

Merged #3415 for your consideration.

Thanks, it works!!!

Great! Thanks for helping to find and fix this issue!

I greatly pity.
Your version stops after about 7-12 hours (all "hangs" - had not been on any firmware).
I went back to my solution to this problem - it is very necessary to print.
https://youtu.be/JUD4F3lGDD8
Besides us, the problem is or who is not interested?

@olegmorgun What the what now? Would you like to report a new issue and help us fix a bug? Please provide the following helpful bullet points:

  • Expected behavior
  • Observed behavior
  • Steps required to reproduce the behavior
  • Version of Arduino used to build

Did you just download RCBugFix last night?

Arduino - 1.6.5
"Did you just download RCBugFix last night?" - no, Version: Marlin - 1.1.0-RC3 - 01 December 2015 - changed code manually.
Today try - Marlin 1.1.0-RC5 - 01 April 2016

PS. A very long time to check possible errors, waiting for more than 8 hours.

The Marlin 1.1.0-RC5 - 01 April 2016 there is no change?
Today used the "Marlin - 1.1.0-RC3 - 01 December 2015" with your patches
(http://www.ex.ua/990427655623).
Print 7:00 - successfully.
It is suspected that the failure was due to overheating mega 2560

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Glod76 picture Glod76  Â·  3Comments

Ciev picture Ciev  Â·  3Comments

Matts-Hub picture Matts-Hub  Â·  3Comments

W8KDB picture W8KDB  Â·  4Comments

Tamonir picture Tamonir  Â·  3Comments