Hey! This thing is still a Work in Progress. Files, instructions, and other stuff might change!

Filament Width Sensor with 3 LEDs, TSL1401CL, and Arduino Pro Micro

by inornate, published

Filament Width Sensor with 3 LEDs, TSL1401CL, and Arduino Pro Micro by inornate Mar 3, 2015

Thing Info

7888Views 1122Downloads Found in 3D Printer Parts
Report Thing


Movie: http://youtu.be/TVAAIxcCAu0

This is an improved version of Filament Width sensor thing #636420, based on shadow casting idea by Flipper's #454584.

Now this sensor measures the filament width in three directions: -45, 0, and 45 deg. Three LEDs are sequentially light up and the sensor measures shadows from each direction. It (hopefully) compensate out-of-round filament shape.

45deg measurement limits the maximum measurable filament width around 2.5mm, so, unfortunately, this version is only applicable to 1.75mm filament. For 3mm filament, consider upgrade the line array sensor to wider one, such as TSL1402.


  1. Download the 20150302_Filament_Width_Sensor_3LEDs.zip
  2. Prepare PCB and solder the components. (tricky and costly part!)
  3. Print case/sensorCover.stl in matt black material. ABS was better than PLA in many cases. If the material is not dark enough, paint the black inside the towers.
  4. print three case/led_cap.stl as the cover. mount 5pi LED and cover them with the cap. Connect LEDs like the picture. Aware the polarity.
  5. Upload the firmware: Filament_Widh_Sensor_3LEDsFilament_Widh_Sensor_3LEDs.ino. You need to install TimerOne library to Arduino IDE. Refer http://arduino.cc/en/pmwiki.php?n=Guide/Libraries and TimerOne-r11.zip
  6. Turn on the visualizer (TSL1401_visualizer) in Processing. (http://processing.org). Through the case, put a 2mm rod as a reference. Type [0, 1, 2] will select the LED and [j, k] will decrease and increase the LED intensity. Decrease the intensity and slowly increase them until the edge detection algorithm works just fine. The green/red lines indicate the detected edge.
    6-1. ([email protected] 26, 2016) If this step crashes and complains about size() function, replace line 31 with [ size (387, 316); ]. Current processing does not allow any variable with size() function.
  7. Type [c] to calibrate the sensor. Now you're good to go!
  8. If you need more help, type [h] in Serial [email protected] IDE. Look inside the source files.
  9. Any suggestion and additional contribution will always be welcomed.

1 x Arduino Pro Micro board
1 x PCB
1 x TSL1401 Line scan sensor
1 x 1Kohm resister (SMD 2012)
1 x 10nF ceramic capacitor (SMD 2012)
1 x 0.1uF ceramic capacitor (SMD 2012)
3 x 200ohm resister (SMD 2012)
3 x 10uF multi-layer ceramic capacitor (SMD 2012)
1 x 2x3 pin header
1 x Molex 5046 (right angle, male type mount)
1 x Molex 5051 (female type socket)
3 x High-brightness LED (5mm radius)
8 x 2mm x 8mm sheet metal screw

  • electric wires, pin header sockets, solder, ...

More from 3D Printer Parts

view more

All Apps

This App connects Thingiverse with Makeprintable, a cloud-based mesh repair service that analyzes, validates and repairs most common mesh errors that can occur when preparing a 3D design file for p...

App Info Launch App

Kiri:Moto is an integrated cloud-based slicer and tool-path generator for 3D Printing, CAM / CNC and Laser cutting. *** 3D printing mode provides model slicing and GCode output using built-in...

App Info Launch App
KiriMoto Thing App

With 3D Slash, you can edit 3d models like a stonecutter. A unique interface: as fun as a building game! The perfect tool for non-designers and children to create in 3D.

App Info Launch App

Has anyone tried running this on an Arduino Mega ? I have everything working, and I can read the analog voltage out from the sensor, but I have no data on the serial output. The serial console works, and I can raise and lower the led values, but the data in the RAW and mm fields is reading zero. I have checked all the hardware, pretty sure there is an issue with the program I am missing.

Any help or advice would be greatly appreciated.


Dave Stewart

Do you meaning that the analog voltage is reading properly (around 1.5v~2.0v) but the serial monitor prints zero?
Can you explain the symptom with more information? (possibly with a movie clip?)

14 hours ago - Modified 4 hours ago
Bigstew123 - in reply to inornate


The sketch is exactly the same as your file on Thingiverse, I have tried changing the clk pin from 3 to 11 but it makes no difference. Video shows the voltage output will vary as the sensor is covered and uncovered. The sensor is the TSL1402R and is basically the same as two of the 1401 sensors coupled together. I am trying to read one set of the 128 diode arrays in the video.

@inornate first thanks for the design, i made a little change in the rc filter (output) to make it work i use a 10uf cap instead of 10nf (with 10nf don´t work in my printer), and now work great but i can´t find a 2mm rod it's not comun in mexico, temporally i used a 2mm Graphite leads (not a great solution), and the question is how can i change the calibration in order to use a 5/64 rod instead of 2mm rod ??

Thanks in advance,

Apr 28, 2016 - Modified Apr 28, 2016
inornate - in reply to RicardoGA

@ Filament_Widh_Sensor_3LEDs.ino
You can see three calibrating lines at line #381, 382, 383.

  calibFactor[0] = averaged0 / 2.0;
  calibFactor[1] = averaged1 / 2.0;      
  calibFactor[2] = averaged2 / 2.0;      

5/64 rod is approx. 1.9844mm, therefore you need to update those lines with:

  calibFactor[0] = averaged0 / 1.9844;
  calibFactor[1] = averaged1 / 1.9844;      
  calibFactor[2] = averaged2 / 1.9844;      

thanks :)

I got an error Message with the processing file, it always says, "Please fix the size() line to continue.

I installed the recent Processing version and found the problem.

Size() function doesn't accept any variable as a parameter anymore. Therefore, the solution is...

==> Line 31: size (LINELEN, SCROLLHT + 50);
==> Line 31: size (387, 316);

What Processing version do you use?

thanks for your replie, im using the newest version 3.0.2. Downloaded it yesterday on the homepage of processing. Your Solution is working thanks

I had the same error with version 3. No problem with version 2.2.1.

[SOLVED] Problem was TSL1401R need resistor 330R on pin 3 TSL1401 to GND. At the moment I have another problem in calibration ... only one LED does not work to calibrate?You must have 3 Led's?

The source code is designed for 3 LEDs. However you might modify it for 1 LED but you need to understand what you're doing and need to modify the visualizer also.

For 1 LED design, you will interest the thing #636420. ( http://www.thingiverse.com/thing:636420 )

The circuit design is almost identical.

Filament Width Sensor with Arduino Pro Micro and TSL1401CL

[SOLVED] Problem was TSL1401R need resistor 330R on pin 3 TSL1401 to GND. At the moment I have another problem in calibration ... only one LED does not work to calibrate?You must have 3 Led's?

which program line to control the scan?

The delay function in line #501, at scanSensor().

It's commented as an "Integration time".

The discrete circuit "TSL1401C" And The "TSL1401R" has difference in the program?
I'm using "TSL1401R" DIP-8 but does not work !!!

only two red stripes !!

thank you...

Aug 14, 2015 - Modified Aug 14, 2015
inornate - in reply to ADELIMA

I think those two sensors are working in identical way.

You may try to adjust LED brightness and sensor scanning time to get a right exposure.

Aug 13, 2015 - Modified Aug 13, 2015

sorry ! "distance between sensor and LED ?","distance from the filament to the sensor?"
Thank you !

Sensor-LED distance is approx. 55mm and filament-sensor distance is approx. 0.5mm.

This comment has been deleted.
Aug 13, 2015 - Modified Aug 13, 2015
inornate - in reply to ADELIMA

Sorry ADELIMA but I can't understand your question: "I want to know what time the tubes where will the leds?"

Could you explain your question with more detail (=more specific word)? E.g., tube perimeter, LED size, distance between sensor and LED, ...

Hi @inornate, i am making this circuit but did not found 10uF ceramic capacitor can i use electrolytic capacitor or other ceramic capacitor with this.

I choose 10uF because it completely eliminates the LED flickering. However, some lower capacitance may effective.

Try a ceramic capacitor with highest capacitance available, and watch the logged image. If it doesn't have flickering issue, that's good to go.

Mar 9, 2015 - Modified Mar 9, 2015

Hi @inornate, i make a sample circuit using your 3 LED Filament Sensor,
I add a Nema 17 Stepper motor and Pololu A4988 Stepper Driver with this Arduino (Leonardo)Pro Micro for Filament Extruder Puller Assembly so Diameter can be adjust using puller motor Speed, Please have a look and tell me that i am going in a right way or not.
Here is the image of Schematic Diagram make using Fritzing.


And Fritzing Schematic File


Mar 10, 2015 - Modified Mar 10, 2015
inornate - in reply to 1990ankitjain

The schematic looks generally OK but have some concerns. Here's some advises:

  1. LED1~3 are ordered in reverse. Of cause, it is not a big deal anyway.
  2. You need to tweak timers and interrupts setup for the step pulse generation. I setup fast PWM mode for each LEDs that occupy timer 1, 3, and 4. The only remaining timer is 0 and it is assigned to pin D3. I've used this as the CLK generation however the timer function was not required in my code indeed. I suggest you to carefully check the timer and interrupt related functions and make sure that those features have no interference.

I had quite problem ordering TSL1401 to Europe for reasonable price. It took me few hours of pretty extensive searching, but I found TCD1304AP for $4 including shipping eventually, which I hope will do the same job. I will give it a try once it comes and let you know whether it worked.

I've searched about the TCD1304AP and it's resolution is 4K and master clock works in typ. 2Mhz (min. 0.8Mhz).. which seems a lot!

I'm worrying two things:

  • Arduino cannot generate 2Mhz signal. Even 0.8Mhz (=800Khz) pulse generation is almost impossible.
  • For byte array holding 4K pixel data: Arduino Pro Micro's SRAM is only 2.5K. For Atmega2560, there are 8K SRAM though.

For those reason, you may need to switch to ARM core MCU instead of 8bit Atmega chips. I wish you good luck.

I am afraid that you are right. I have been googling about that a bit just after i wrote the comment. And it was kind of late :) I believe that under-sampling it to let's say 128 values may save me (I would read every 32th value). There is one guy trying to do the same here http://www.avrfreaks.net/forum/interfacing-barcode-ccd-line-array-tcd1304ap-atmega32, but there is no result mentioned. Anyway, with that 2MHz clock I was just assuming that 16MHz processor should be able to do the job. But obviously (referring to here for instance http://forum.arduino.cc/index.php?topic=148741.0) it it not as easy :))

Mar 9, 2015 - Modified Mar 9, 2015
inornate - in reply to wenca

I thoroughly read the datasheet and I found that you don't need to generate masterclock from the MCU. You just need to setup a 2MHz (or whatever within the limit) oscillator and use electronic shutter mode. What you need to care is SH signal which operates much slower.

However the bottleneck might be ADC time, which is set to 100us (=10kHz) by default. (http://arduino.cc/en/Reference/analogRead) But, by changing the prescaler, it may boosts up with the rate of ~77kHz.

Interfacing TCD1304AP with Arduino is tricky but it seems feasible now.
Please share your result when you success.

Thanks for your findings. It seems like you have given it much more time than I have so far :) I will definitely share the result. I am still waiting for it to arrive. In the meanwhile I am working on lyman's filament extruder (http://www.thingiverse.com/thing:380987) which I am super excited of...

Lyman / Mulier Filament Extruder V5
by hlyman
Mar 9, 2015 - Modified Mar 9, 2015
inornate - in reply to wenca

I tested a quick workaround for generating 2Mhz signal.

With this code below, the highest archivable freq. was about 100kHz, which is far less than 0.8MHz=800kHz.
digitalWrite(pin, HIGH);
digitalWrite(pin, LOW);

Considering that digitalWrite is a function call that consumes bunch of assembly lines, I replaced them like below:

  PORTB = B00010000;
  PORTB = B00010000;
  PORTB = B00010000;    
  PORTB = B00010000;    
  PORTB = B00000000;
  PORTB = B00000000;

5th bit in PORTB directly manipulate the GPIO #8 on Arduino Leonardo. While loop consumes 2 clock, therefore 4 HIGH bits and 2 LOW bits consumes 8 clocks, thus it generated precise 2MHz signal.

I hope this information may help you.

Mar 9, 2015 - Modified Mar 9, 2015
inornate - in reply to wenca

Instead of skipping, you may try pixel binning technique. (try google it) It has advantage in terms of sensitivity.

With more complex code, you also may try selectively reading only edge regions with high-resolution images instead of sub-pixel interpolation like I and flipper tried. It would give a great accuracy.

This comment has been deleted.