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


Use This Project

Give a Shout Out

If you print this Thing and display it in public proudly give attribution by printing and displaying this tag.

Print Thing Tag


Thing Statistics

12769Views 1806Downloads Found in 3D Printer Parts


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

Auto-magically prepare your 3D models for 3D printing. A cloud based 3D models Preparing and Healing solution for 3D Printing, MakePrintable provides features for model repairing, wall thickness...

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

Quickly Scale, Mirror or Cut your 3D Models

App Info Launch App
Mar 23, 2017 - Modified Mar 23, 2017

I need to use this as 1 led sensor - where just top middle led is used

so i change arduino code:
line 26:
byte leds[3] = {5, 6, 9}; to byte leds[3] = {6, 6, 6};
and line 39 - 40:
PROGMEM const double calibFactorDefault[3] = {22.271, 15.748, 22.271}; to {15.748, 15.748, 15.748};
double calibFactor[3] = {22.271, 15.748, 22.271}; to {15.748, 15.748, 15.748};
this seems to work good with all benefits of this sensor (visualizer, calibration etc.) (please tell me if there is something more that is need to change)
question is:
is there any simple way how to slow down led flashing? the one that is used, flashing 3 times faster now - as expected. everything is ok and it work, but if i can slow it down easily i want to do it :) ..
thank you

Comments deleted.
Mar 4, 2017 - Modified Mar 11, 2017

I am trying to make the 3 led filament width sensor and run into same problem with tsl1401 visualizer as ADELIMA :

  • I'm having 3 images and the brightness works fine but just 3 red stripes and the edge detection does not work no matter what the brightness be.
  • The voltage on the OUT pin seems to be around 0.006v constantly.
  • Pressing C or H in the visualizer leads to UNSYNC message in the console.
    By the way I'm using TSL1401 with the 330R resistor connecting the AO to GND.
    Any help on the issue will be much appreciated.

Hi, I am quite new to 3D printing and the board and everything.
Could you tell me where can i get the pcb and how should i make it ?

You'll need to make it by yourself.
I uploaded all the files (Gerber and Eagle CAD files) in the zip file. You may pass them directly to the PCB maker.

Elsewise, you may try home-made PCB by an etching technique. My design needs only five back-side jumpers.

thank you. ^^

Hello all,

Any plan to modify PCB and code to use it as a filament monitor to detect when filament finished ? :)

Jan 1, 2017 - Modified Jan 6, 2017

Hello, fellow 3D hobbyists.
Please PM me if you are interested the PCB for this project, I have 2 to sell. $10 including shipping in the continental US.
(See Made tab)

Great make! (and sexy PCB!)
I'm glad to hear that the PCB worked well.

Thanks! Great job for the whole project!

Sep 5, 2016 - Modified Sep 5, 2016

I recently successfully interfaced a TCD1304AP linear sensor with a teensy2++ :


As this sensor is much longer (2.9cm) it would allow you to measure 3mm filament.
It is also more precise (4um pixels), so I thought it might be of interest for you.

Looks fun and great documentation!
Great work.

Thank you for sharing!

Aug 30, 2016 - Modified Aug 30, 2016

Hi, I calibrating leds brightness (and also 2mm rod..) when connected with USB cable to PC and save (processing wrote "unsync"), but led brightness jump back to default brightness, when I (discnonnect sensor from usb first and then) connected sensor throught arduino mega/ramps1.4 aux-2 connector (lyman f.ex. v5, mackerel fw) .. why and how to correct this? ..diameter calibration is saved (but shown bad +/- 0.2 mm due to brightness differences) ..
but when I leave it connected on USB/PC and use just gnd and signal(out) connected to arduino mega/ramps aux-2 (so +5v in from mega/ramps is disconnected) everything looks ok and brightness (and diameter) stay tuned .. should i use RAW pin instead of VCC pin for +5v from mega/ramps? / or hook +5v from mega/ramps throught usb connector ? / or use regulated RAW input for calibrating stage and also for working stage with mega/ramps?/ or problem is something else ?

First) Please make sure the message "[WARNING] This sensor is not calibrated yet, applying default calibration factor" disappears after the calibration step. This message appears when you press 'h' in Arduino serial console. It should disappear after calibration. When you see this message again after reconnecting the board, your EEPROM must have been damaged. Consider replacing the Arduino board attached to the sensor.

Second) Do you mean RAW pin on Arduino Pro Micro board? No, you don't have to. I think directly connecting mega's 5v to VCC should be sufficient.

Sep 8, 2016 - Modified Sep 8, 2016
Hogo_Fogo - in reply to inornate

thnaks for quick reply.
if press H in serial console i can see that everything is calibrated and saved.
the problem, as it looks to me, is that power, that goes to leds, when sensor is powered by PC throught usb connector of arduino micro when calibrating, is different, than power going to leds throught +/-/signal pins on sensor pcb when its connected to mega/ramps. thats why i ask if some other pin should be useful as it (maybe (I dont know)) use some voltage regulation?
or another explanation of problem - when its on pc-usb and set led1 brightness to value 92 blinking is barely visible, I save it, but when connect to mega/ramps it blinks brighter - it looks like value about 103 on pc/usb (so its really noticeable brighter). it save diference between led1 and other leds, but still there is this offset (aprox. +10) for all leds ..

In that case, consider shorting J1 jumper (at the left upper side of the Arduino Micro Board). You'll need to solder them.
check) https://cdn.sparkfun.com/assets/9/c/3/c/4/523a1765757b7f5c6e8b4567.png

USB power goes through the regulator and used as VCC, will cause about some voltage drop.
J1 jumper directly connects UVCC to VCC.

Hope this helps.


yes, that helps. thank you :)

Dec 20, 2016 - Modified Dec 20, 2016
Hogo_Fogo - in reply to Hogo_Fogo

I have to change 10nf capacitor at RC filter with 10uf cap. I using sensor on lyman filament extruder v5 (running on arduino mega and Ramps1.4) and 10nf cause drops +- 0.25mm (0.5mm total) which is more than undesirable.

There is still little diferences between power from Ramps and power from computer when calibrating that causes inaccuracy, also there is some interference when sensor is powered from both sources (sensor is powered and work with running extruder, but at same time from pc-usb running visualiser for checking etc) causes that Ramps freeze. To fix both of this problems I use only power from Ramps and for visualiser and calibrating i use usb cable with interrupted +5v wire.
now everything is super fine and sensor work flawlessly :)

Hi, do you have any indication concerning led color? I'm using cold white leds, but having hard time with transparent filament.

I'm using standard 5mm red LEDs. It can detect the edge of the transparent filament, however, you may need to adjust the LED brightness for it.

I'm using 10uF Tantalum capacitor, and I'm afraid one led is interfering with other because this capacitor is making each led to stay on for a longer time. What do you think?
thanks in advance

I calculated 10uF would be sufficient to compensate flickering from the PWM signal.
Of course the led stays on for a longer time, but the delay in the program was adjusted for it.

Thanks for your answer, I figured out what has happened:
I was using a TSL1401R (Dip8) and as stated by someone here in the comments, Dip8 version needs a 330 Ohms resistor hooked from AO to Ground, I was missing this.
Then I had other issue: It only reads 64 pixels, I bought a TSL1401R but I think the aliexpress seller has shipped a TSL201R to me,
At last I used a TSL1401CL and it worked fine. Luckily I've bought 1 dip8 and 2 SMD sensors.

Happy to hear that it works!

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?)

May 31, 2016 - Modified Jun 1, 2016
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.

Jul 8, 2016 - Modified Jul 8, 2016
inornate - in reply to Bigstew123

As long as I saw in the video, check your terminal is SCROLLING up to the newest output lines.
Sorry for late response. (Actually, way too late. Sorry. I missed the comment notification alert.)

@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,

Que tal RicardoGA, soy Victor Ruiz tambien de Mexico. Como vas con tu proyecto, lograste terminarlo? Yo estoy por empezar este mismo proyecto. Platicame mas sobre tu expereincia. Un saludo.

Hola Victor, si el sensor de filamento ya quedo listo desde hace varios meses y funciona correctamente, el mayor desafió fue lograr la calibración debido a que es complicado conseguir alguna varilla de 2 mm pero después de buscar termine usando una mina de 2 mm (se usan para el dibujo y las venden en office depot) para calibrar y listo quedo funcionando al 100% y solo a requerido el mantenimiento esperado que es limpiar el sensor cuando se le llega a acumular polvo y ocasiona lecturas erróneas.

Para limpiarlo utilizo un poco de alcohol isopropilico junto con trapo de microfobra


Gracias Ricardo por tu respuesta. Que bueno que terminaste el proyecto y que esta funcionando como se esperaba. En que parte de la republica vives? Yo vivo en Guadalajara. Hay manera de platicar por e-mail o si me puedes dar tu whatssapp estaria muy bien.

Hola una disculpa por tardar en responder no me llego la notificacion de tu mensaje y hasta hoy entre a thingiverse, vivo en slp y puedes contactarme en [email protected]


Sorry, I do not understand Mexican. Would you like to ask me again in English?

Sorry inornate, whom I want to refer is to RicardoGA that he posted a question for you. But I want to put me in contact with him, taking advantage that he is mexican.
By the way, my congratulation to you for your Filament Width Sensor with 3 leds, looks very interesting. Do you have the whole project already assembled & Tested for sell?

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.

Comments 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.

Comments deleted.