Skip navigation

Arduino Projects

3 Posts authored by: balearicdynamics Top Member


This project aims to solve two issues I have experienced working with 3D printers: controlling the filament consumption while the 3D printer is working. After exploring several possible approaches I decided that the most reliable solution should be based on the weight control.

The ability to dynamically measure the plastic material (filament) in use by a 3D printer includes some interesting non-obvious aspects helpful in many phases of the 3D printing process.



On June, 30 this project has been featured on Tindie Blog | 3D Printer Filament Weight/Length Monitor


Weight vs length and vice-versa

3D printers filament is sold in weight; the most common packages are 1 or 2 Kg filament rolls. The reason is that the product format, i.e. the filament in our case is the most important aspect for the end-user but meaningless for producers. Producers just sell kilograms of plastic material (PLA or ABS); the filament is the form factor provided on the market for a specific usage. I suppose that the same company that provides PLA filament it is not excluded will also provide the same material in other formats (e.g. plates, powder, pipes, film etc. for other applications). But for a similar reason 3D printers users needs to measure their filament in length. Slicer algorithms calculate the meter of filament needed for a certain 3D printed object so it is important to know how much meters remain in the roll before starting a new object printing and how many meters are used during a print job.

We know the specific weight of the materials used for 3D printing: PLA and ABS have different specific weight and this is a constant value. We also know the filament diameter; this means that 1 Kg 1.7 mm diameter filament will be longer than 3 mm diameter filament, same weight.

Calculating the conversion between weight and length it not so difficult knowing these parameters. You can just play with an algorithm with this nice online filament calculator.


Finding and testing the load sensor (scale sensor)

The first step was to find the right weight sensor and test its sensitivity. I should thank to michaelkellett that addressed me in the right direction; I bought a first series of four scale sensors in the weight range of 0-5 Kg and about half gram sensitivity for 3$/piece including the HX711 based amplifier circuit (the IC datasheet is in attach to the bottom of this post)



Using a 3 mm MDF sheet I have created a simple test sample to see the kind of data I should expect; after writing a few lines of code to show the readings on the serial terminal from an Arduino UNO I got a satisfying result and I definitely adopted this hardware solution.


The filament roll scale design


Recycling the idea of my 3D printer filament spool holder design I have made the design of a compact scale supporting a rotating filament roll as shown in the images below. As shown in the 3D representation the filament roll lies on the four wheels that rotates free and the support is connected to the base through the scale sensor.

Scale only 01.jpgScale only 02.jpg

One support can be entirely built 3D printing 22 pieces with some M3 and M4 Allen screws and nuts at a very low price

Scale parts NoMotion.jpg


Assembling the parts

After all the 22 pieces has been printed can be easily assembled together. The top and bottom surfaces will be the filament spool support and the weight material scale at the same time. The filament is tensioned by the extruder so the roll should be free to rotate lying on the four free wheels (the orange ones). As shown in the assembly steps in the image gallery below top and bottom sides of the support are joined through the load sensor. It should be in the range 5-10 Kg max to support the filament roll that weight between 1,5 Kg and 2,5Kg (2Kg plastic rolls).


{gallery} Scale roll support parts and assembly


3D printed base


3D printed top


The free wheels supports


The free wheel supports


The free wheel supports mounted on the top part


The top part with the free wheels assembled


Free wheel detail (top support)


The base with the four calibration screws, top view


The base with the four calibration screws, bottom view


Calibration screw with spring of the base


The base with the load sensor mounted, bottom view


The base with the load sensor mounted, top view


Base and load sensor assembled


The top support mounted on the base through the load sensor


The final assembly side view



Testing the support 3D printing


Testing the support 3D printing


Some structure improvements

Testing the first version of the 3D printed scale I saw that filament rolls can have different spool dimensions, also if the same weight. To manage the different widths between spools (may depends on different providers or different production batches) the top base design has been update; now it is possible to set the position of the four free wheels supports as shown in the images below.

IMG_20170612_091713.jpg IMG_20170612_091718.jpg

IMG_20170612_092704.jpg IMG_20170612_092712.jpg

IMG_20170612_093404.jpg IMG_20170612_093411.jpg

The wires coming from the load sensor are very thin and delicate so I decided that it was too risky to add a connector do I decided to include in the scale building also the HX711 filter adding two holes to the bottom part to fix the small IC board.

IMG_20170612_094140.jpg IMG_20170612_094150.jpg IMG_20170612_094826.jpg

IMG_20170612_091731.jpg IMG_20170612_100247.jpg IMG_20170612_100254.jpg

IMG_20170612_100721.jpg IMG_20170613_142926.jpg IMG_20170615_193450.jpg


Circuit and wiring

The image below shows the functional design of the circuit and the interface

Screen Shot 2017-06-24 at 21.18.49.png

As the filament is usually available in two different dimensions, 1.75 and 3 mm diameter, the rolls are available in different weights and we should consider using at least two kinds of materials it was necessary to provide a three dip switch to select these three settings before starting the system. Making the first experiments I saw tat it was impossible to distinguish automatically the three phases when a 3D print job starts:


1. Power the system and initialise it (calculating the empty tare without the filament)

IMG_20170615_193117 (1).jpg

2. Place the filament roll and wait the weight stabilises

IMG_20170615_193146 (1).jpg

3. Start reading the usage (material load)

(consumption can be expressed in grams or centimeters)

IMG_20170615_193403 (1).jpg IMG_20170615_193450.jpg

I have added two push buttons; an action button to manually set the three phases and a measure unit switch to select the visualisation on the display: filament units in grams or in centimeters/meters.

To have a complete status of the hardware a 3mm orange LED blink during every weight reading cycle while for the display I have used a shift register display (the full documented project is in these two articles: Enrico Miglino on  and Arduino 16x2 LCD Shift Register Library - Part 2 ) based on 74HC595 shift-in register I have built in past to reduce the usage of Arduino pins.

As the MC711 already generates a digital signal only two pins are needed to connect it to the Arduino board.


The project in action

The video below shows the first prototype and the final building in action after software filtering calculations have been included in the building.

The initial part of the video shows how connecting the sensor only without controls, due to unpredictable weight fluctuations it is almost impossible to control the three phases mentioned above while the second part shows the final version accordingly with the wiring scheme.


The software

The Arduino sketch is built in two parts for better readability: an header file defining all the constants used by the calculations as well as the pin settings and the source functions in the .ino file. All the project is distributed under the LGPL 3.0 license and is available on GitHub:

Additional libraries added to the sketch are the bodge MX711 library fo manage the scale IC and the updated library for the shift-LCD fixed compatible with the last versions of Arduino IDE, available in attach to this post.

What is ?

From a server to a SBC (Single Board Computer) or the board of your last robotic project it is not rare nor strange the need to keep the system and the container box under control avoiding excessive shocking vibrations, too much heating, adding a reliable digital power on/off system or reset automatically the entire device under certain conditions, as well as the availability of constantly updated parameters like the internal device temperature, the buttons pressed by the user (or state of some external digital input or sensor), the number of hours the system is up e.g. to test the battery durability or battery level.


The Circuit health control Arduino compatible is based on a previous project ( Microcontroller Health Status Controller Board based on AVR328p ) developed to control a SBC server. Then with some modifications to the original circuit based on the Atmel AVR328pAVR328p this board become general purpose, easy customizable and compatible with most of the popular Arduino boards.


Note: the board can be used together with any kind of device as it runs independently but the controlled device.

The board kit is available now on! (don't forget the special Element14 users 10% discount code: W0E49MYQ when buying)


Arduino compatibility features

Not only this board is based on the ATMega328p micro controller IC, the same hosted on the Arduino UNO boards, but the firmware has been developed including the Arduino bootloader. This means that the software can be opened as a normal Arduino sketch with the Arduino IDE (compatibility starts from the version 1.6.x of the IDE).


The Circuit health control is provided natively with a booloader version of the firmware as explained in this article; the software, released as Open Source under the Apache license can be cloned from the github repository and customized following the user needs. As the on-board IC micro controller include the Arduino bootloader the board can be programmed by any user with... another Arduino ! When programming the board firmware a USB powered Arduino UNO is sufficient to power the connected board without any extra power source.



How does it works?

The following video shows the main features of the work on the testing bench.


The components

The system consists of the control board and a set of accessories processing external data, plus the connection with the controlled system if needed.


LCD display


The 16x2 alphanumeric LCD display continuously monitor the system health status by default: temperature, fan percentage speed, up-time in hrs, min, sec. When an alarm condition occur (shock risk or overheating) the display shows the alarm condition. The display is also used to show message feedback to the user interaction.


Temperature sensor


The temperature sensor is based on the IC LM35. The internal calculations for the read values have one decimal C precision while the display only shows integer values. By default the maximum temperature working value without overheating risk is 60C and the minimum temperature value to start the fan (10% of the max speed) is 30C. These values can be set as well, depending on the environment where the board is used and where the sensor is positioned.


Vibration sensor


The vibration sensor sensitivity can be regulated with the trimmer on the board; the regulation should be done to trim the vibration alarm in different conditions depending on the environment where it is installed. The sensor generates a digital signal every received vibration in the sensitivity range.

By default the board firmware react to the first detected vibration generating a shock risk warning on the display. If the  vibrations continue for five seconds the warning become an alarm; then the board can automatically power off the controlled device.


Cooler fan


The cooler fan is controlled as direct feedback by the temperature sensor. Depending on the instant detected temperature with a resolution of about 0.5C the fan speed is updated between 10% and 100% or 0% (stopped when the temperature is under the minimum of the configured range). The fine tuning of the fan response to the temperature depends on the respective position of the sensor and the fan, the size of the environment where the control board is installed and the heating of the system when it is running. The control board can support different fan sizes working at a voltage between 6 and 24V. The Fan power VCC is separated by the control board power.


Note: the fan speed control uses the PWM but works with cheap fan devices without the PWM control line; the shown used model is a 12V fan motor with two power cables only.


User programmable buttons


The two user programmable buttons can be associated to any action of the controller. Typically the two buttons can be used for reset and power on/off where the action on the controlled board is managed by the controller, for example sending a long press for power-on or a press sequence to reach certain results.


Programmable digital output signals


The board provide two digital output signals. These can be used to simulate a button-press or a button-sequence. The two signals are amplified by a couple of  2N22222N2222 acting as switch The signals can also be connected to a 5V coil relais to manage higher currents


Separate power lines


The board is provided with two separate power lines: a 5V to power the board (can be replaced by the Arduino board while programming the micro controller) and a power line for the cooler fan.


Schematics and layout

The two images below shows the circuit schematics and the PCB layout.

Circuit Health Control Schematics.png Circuit Health Control Layout.png

... and the board on the test bench connected to the Arduino ISP programmer




The Circuit health control is provided with a pre-installed firmware including the Arduino bootloader. This makes the original sketch available to any customisation and configuration. The main source is divided in four parts.


1. Application definitions

This includes the parameter constants that can be changed to change the behavior of the board in the different conditions

//! Minimum PWM frequency to start fan
#define FANSPEED_MIN 60
//! Maximum PWM frequency to reach
#define FANSPEED_MAX 255
//! Minimum temperature to start fan
#define TEMP_MIN 30
//! Maximum temperature before overheating error
#define TEMP_MAX 90

//! Loop update frequency
#define UPDATE_FREQ 10
//! Fan full speed test during initialisation
#define FAN_TEST_MS 2500

//! PWM Pin conntrolling the fan speed
#define PWM_FAN 3
//! Analog pin controlling the temperature
#define ANALOG_TEMP 0
//! Reset button pin
#define RESET_BUTTON 2
//! Power on/off button pin
#define POWER_BUTTON 7
//! Vibration sensor pin
//! Server control power simulated button pin
//! Server control reset simulated button pin

#define SERVER_ON  1    ///< Server powered on
#define SERVER_OFF 2    ///< Server powered off
#define SERVER_RESET 3  ///< Server restarting after reset
#define SERVER_POWER_TIME  10000   ///< msec for server going up (power On and Reset)
#define SERVER_POWEROFF_TIME 5000  ///< msec for server goind down
#define SERVER_RESET_TIME 5000    ///< msec for server goind down
#define BUTTON_PRESS_TIMEOUT 5000  ///< msec Timeout when a button remain pressed
#define POWER_ON_DELAY 5000    ///< Power on message delay before starting server
#define ALARM_TIMEOUT 5000     ///< If shock alarm is longer, the system is shutdown
#define FIRST_SHOCK_DELAY 1000    ///< ms before checking the alaram persistance
#define SENSOR_READINGS 500       ///< Number of vibration sensors reading for persistance check
#define PRESS_POWER_FIRST 1    ///< Power button has been pressed
#define PRESS_POWER_SECOND 2   ///< Power button pressed again to confirm (Only for shutdown)
#define PRESS_RESET_FIRST 3    ////< Reset button pressed
#define PRESS_RESET_SECOND 4   ///< Reset button pressed again to confirm
#define BUTTON_PRESS_NONE 0    ///< No buttons has been pressed
#define MIN_FANSPEED_PERC 10   ///< Minimum fan speed PWM percentage to start the fan motor
#define RESET_CYCLE_DURATION 500      ///< ms the simulated server reset button should remain pressed
#define POWERON_CYCLE_DURATION 500    ///< ms the simulated server power button should remain pressed to power off
#define POWEROFF_CYCLE_DURATION 5000  ///< ms the simulated server power button should remain pressed to power off


2. Setup and main loop

Defines the logic of the board in the various conditions

//! Main loop application
void loop(void) {
  // ==============================
  // Check the schock risk status
  // ==============================
  // Shock alarm is checked only when the server is running
  if( (digitalRead(VIBRATION_SENSOR) == HIGH) && (serverStatus != SERVER_OFF) ){
    // Shock alarm - Initialise the count
    // wait a few second(s) to reduce the sensor sensitivity before checking
    // for risk condition persistance. This value is calibrated experimentally
    shockAlarmTimeout = millis();
    int numberShock; // counter of the detected vibrations
    // Exit from the alarm loop only when the alarm ends or the system shutdown process is started.
    boolean alarmSet = true;
    numberShock = 0;
    while(alarmSet) {
      // Read 100 times the sensor.
      for(int j = 0; j < SENSOR_READINGS; j++)  {
        if(digitalRead(VIBRATION_SENSOR) == HIGH)
      } // vibration counter loop
      // If alarm condition persists, update the display
      // to create a blinking effect at the end of every loop
      if(numberShock > 0)
      // Check for alarm timeout
      if( (millis() - shockAlarmTimeout) > ALARM_TIMEOUT)
        alarmSet = false; // just exit from the loop
    } // alarm timeout loop
    // If alarm condition persisted for too much time, the server is
    // powered off, else restore the normal conditions
    if(numberShock > 0) {
      serverStatus = SERVER_OFF;
      buttonPressed = BUTTON_PRESS_NONE;
    else {
      // Restore the normal condition
      buttonPressed = BUTTON_PRESS_NONE;
      serverStatus = SERVER_ON;
  } // end vibration alarm check

  // ==============================
  // Check the state of the buttons
  // ==============================
  // Manage Reset button ------------------------------------------
  if (checkPushReleaseButton(RESET_BUTTON) == LOW) {
      // Reset button
      if( (buttonPressed == PRESS_RESET_FIRST) && (serverStatus == SERVER_RESET) ){
        buttonPressed = PRESS_RESET_SECOND;
      } // Second button accepted
    else {
      if(serverStatus == SERVER_ON) {
        buttonPressed = PRESS_RESET_FIRST;
      } // Server on, can reset
      else {
        buttonPressed = BUTTON_PRESS_NONE;
      } // Server off, reset impossible
    } // First press
  } // Reset button pressed

  // Manage Power on/off button -----------------------------------
  else if(checkPushReleaseButton(POWER_BUTTON) == LOW) {
    if( (buttonPressed == PRESS_POWER_FIRST) && (serverStatus == SERVER_ON) ) {
        buttonPressed = PRESS_POWER_SECOND;
    } // First button already pressed with server on
    else {
      // Power on the server
        buttonPressed = PRESS_POWER_FIRST;
  } // Power Button pressed

  // =========================================
  // Process the current buttons status action
  // =========================================
  switch(buttonPressed) {

    // No action request, check health status and go ahead
    startTimeSec = millis(); // Initialise the timeout counter

    if( (millis() - startTimeSec) > BUTTON_PRESS_TIMEOUT) {
      buttonPressed = BUTTON_PRESS_NONE;
      } // First button timeout
    else {
      if(serverStatus == SERVER_OFF) {
        delay(SERVER_POWER_TIME);  // Wait for server power on and start
        serverStatus = SERVER_ON;
        buttonPressed = BUTTON_PRESS_NONE;
      else {
        // Ask for confirmation to start poweroff sequence
    } // No timeout

    serverStatus = SERVER_OFF;
    buttonPressed = BUTTON_PRESS_NONE;

    if( (millis() - startTimeSec) > BUTTON_PRESS_TIMEOUT) {
      serverStatus = SERVER_ON;
      buttonPressed = BUTTON_PRESS_NONE;
    } // First button timeout
    else {
      serverStatus = SERVER_RESET;

    // Reset sequence
    serverStatus = SERVER_ON;
    buttonPressed = BUTTON_PRESS_NONE;



3 & 4. Management functions and Display functions

This part of the main sketch includes all the functions and methods used to display the different status and the methods to manage the hardware, sensor reading, I/O setting etc.


Software repository

The last updated firmware version can be downloaded from the GitHub repository at the following address: alicemirror/CHC

25 Seconds

The first full working time-lapse shooting created with TIltPan Arduino Shield

In the following video you see an example of time-lapse video with some scene movement created with the first prototype of the TiltPan Arduino Shield. There are three main scenes: curve diagonal movement from the bottom-left side to the upper-right, then the camera moves to the left pointing to reach the middle of the rotation horizontal plane. The last is a fixed scene pointing the sky.

The entire sequence has been created with a total of 654 frames from images captured in time-lapse by the TiltPan Arduino Shield and the mechanics module with a frame interval of 4 seconds. The shield can be programmed to manage multiple sequences to create complex time-lapse sets. The total execution time of the time-lapse capture session needed about 41 minutes.


A note on the project

The TiltPan Arduino Shield is a board + mechanics to control a micro camera through Arduino. Better using Arduino UNO but works fine also with Duemilanove and Diecimila. At the actual date it is finished, a first draft of the software documentation has been published as a preview with other posts on the same argument on my blog BalearicDynamics here in Element14

In the document


Tilt-Pan Low Cost MicroCamera


under Arduino section where are shown the main prototypinng phases documented by images.

The resulting object controlled by the Arduino Shield TiltPan is shown in the image below.