3D Printing Hardware/Firmware/Software 101

From SoliWiki
Jump to: navigation, search

Understanding how 3D printers work can be very daunting for a novice, and fortunately most users can get by without a deep understanding of the various elements involved. If you suddenly want to poke around in your printer’s firmware or even tweak the electronics by adding a component, you will need to appreciate how everything works to avoid disaster. Consider this a guide for a beginner based on a decent working knowledge. If you are an expert in this area, feel free to edit in corrections or additions.


[edit] Hardware: Electronics

The most basic element in your printer is the hardware, which is actually the electronics. At the simplest level, your printer is made up of a combination of simple parts, all wired together. You have resistors, which oppose the flow of electrons, transistors which either switch a signal or amplify it and LEDs, which emit a light when current passes through them. The heater for your hot end is just a special type of wire which gets hot when electricity flows through it.

Most of these elements could be wired up to work independently. Consider a simple circuit with a battery, a resistor and an LED. Connect it up and the LED will glow. But what if we want to control the light to come on only when it is dark?

To achieve this we need to add some thinking capability. An integrated circuit is a small chip with the ability to perform certain functions when other components are connected to its pins. The integrated circuit used in the Clifford the Cricket does exactly this, by taking the output of a light sensitive resistor and using it to switch on and off a set of LEDs and a buzzer. Many integrated circuits exist to perform a specific function, and dynamic circuits can be built from using them.

Microcontrollers in various sizes

The next step up from this is the microcontroller, which is a user programmable version of an integrated circuit. The programmer can write code to the chip so that inputs can be read and then appropriate outputs triggered depending on the result. At the heart of every 3D printer is a microcontroller doing just this.

[edit] Firmware: The code Running on the Microcontroller

The scripts and programs the user uploads to the microcontroller, is called the firmware. When you update your firmware, you are using your computer to update the scripts contained on the chip. Most consumer electronics will have some sort of firmware on them. Consider your television or Blu Ray player. The on screen graphics and menus are all examples of firmware installed on the hardware.

[edit] Arduino: A User Friendly Microcontroller and Firmware System

An older model Arduino board

Usually, programming a microcontroller requires a special programmer. Using a microcontroller in a circuit requires a custom PCB to be designed and made to hold the microcontroller and the other electronics, with conductive tracks connecting the components to the correct microcontroller pins. An arduino board takes care of both of these things.

Firstly, components on the board interface between the microcontroller and your computer so that your computer can upload firmware directly through a USB cable. This removes the need for a special programmer. The bootloader is a section of the firmware that resides on the microcontroller, and allows this functionality. Its job is to interface with the computer and assist with overwriting the firmware if the computer makes the request. If the bootloader is ever damaged or removed, the microcontroller will not be able to be reprogrammed without the specialist tool. The program on the microcontroller will however run perfectly well.

Secondly, Arduino boards have nicely laid out sockets that are connected to each pin so that LEDs, heaters and other components can be plugged in easily.

The popularity of Arduino stems from the simplicity and affordability users enjoy while working with microcontrollers. Another bonus is the availability of 'shields' which are PCBs holding specialist hardware that piggy back onto the Arduino board. Imagine the ease of using an LCD screen when you simply plug it straight in and use the example firmware provided as a starting point. Multiple shields can be stacked to easily add more and more functionality.

Arduino clones are simply boards which do the exact same thing, but are made by a different manufacturer. Often, small changes are made which often required minimal software tweaks to get working. Examples of Arduino clones are Freetronics and Sanguino.

[edit] Understanding Firmware – A Basic Arduino Sketch

The job of the firmware is to tell the microcontroller what is connected to each pin and then what to do with them. The name Arduino uses for such a script is called a sketch. The firmware scripts used in Marlin and other firmware contain around fifty files, and are incredibly complex. Despite this, each part of the code is still built on the same principles found in the following basic sketch.

The 'Blink' sketch, with images and diagrams.

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:
int led = 13;

// the setup routine runs once when you press reset:
void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

The blink sketch is the ‘hello world’ of Arduino, and simply blinks an LED on and off every second. Let’s look through it bit by bit.

// Pin 13 has an LED connected on most Arduino boards.
// give it a name:

Any line starting with // is a comment and is ignored by the microcontroller and is simply there to make the sketch easier to understand for humans. Sometimes features can be turned on and off by commenting a line. Consider a single line that launches other code. Commenting it out will stop the other code from executing. This is how support for LCD screens and SD card readers is toggled in Marlin from the same sketch.

int led = 13;

Here a variable is declared. Variables are values which change as the program is running. The temperature of the bed and the X/Y?z coordinates of the print head are all variables found in our 3D printer firmware. Each pin that hardware is connected to is declared as a variable. Here the LED is assigned to pin 13, and given the name ‘led’. If we later decide to connect the LED to pin 12, we simply change this one line instead of going through the code to change it everywhere else it’s mentioned. The ‘int’ at the start tells the microcontroller what type of variable is being declared. It likes to know if it will be text, a whole number, true/false (Boolean) or decimal so it can allocate enough memory to store the value without error.

void setup() {                
  // initialize the digital pin as an output.
  pinMode(led, OUTPUT);     

Every sketch must have a setup() function. This is automatically run when the power is first connected. In this example a single line ofcode tells the microcontroller that the led pin (13) is to be treated as an output. Therfore it will be something to be turned on and off, not read from (input). Our 3D printer firmware does the same thing, with the hot end heater being an output and the attached thermistor being an input used to read the hot end temperature.

// the loop routine runs over and over again forever:
void loop() {
  digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
  delay(1000);               // wait for a second
  digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
  delay(1000);               // wait for a second

Every sketch must also have a loop() function. After the setup() finishes, this function runs over and over again until the power is turned off. For our 3D printers, other more complicated functions might be executed from the main loop, such as checking the extruder temperature. The loop in the example above simply toggles 5V and 0V output to the LED, turning it on and off every second. One other important function is an interrupt. Certain Arduino pins can be setup so that when a change is detected, the main loop is paused to run a specified piece of code. This is how end stops work. When a change is detected from them, the loop will be paused and a piece of code will run to potentially protect the printer. Imagine if the main kept going until the end before registering an end stop touch. By then some damage might have been done.

[edit] 3D Printing Firmware

As well as controlling temperatures and monitoring end stops, firmware such as Marlin performs many other tasks specific to 3D printing. One of the key functions is to compute stepper motor rotation to get the print head from point A to point B. Compared to the blink sketch, Marlin and other firmware is massively complex. Just imagine all of the inputs and outputs that must be managed, as well as the mathematics involved in calculating movement.

[edit] Specialist 3D Printing Hardware

3D printing electronics are all based on Arduino, but some are more obvious than others. The RAMPS board is a factory Arduino mega board with a shield on top that has all of the appropriate hardware and connectors for 3D printing. The 'P' stands for Pololu (stepper motor driver), which is a piece of hardware that translates signals from the microcontroller to those required for the stepper motors. You could easily unplug the RAMPS shield and reprogram the firmware on the mega for something else.

Boards such as the Sanguinololu go a step further. They still have a microcontroller running Arduino firmware, but the PCB has been designed to incorporate the appropriate hardware and connectors, negating the need for a shield. The name comes from the fact that the basis of the board is a Sanguino (Arduino clone), and it has Pololu stepper motor drivers in place. These boards could still be reprogrammed with non 3D printing firmware, but it would be hard to connect other hardware to them because they are so specialised. Marlin is able to cater for many different types of board due to the pins.h file. Elsewhere, a variable is set for the board type, and then the firmware matches this variable in pins.h to assign the correct hardware to the correct pins.

The microcontroller on the Sanguinololu has enough pins that not all of them are used. This leaves a small amount left for adding SD card readers, fans and/or a Panelolu. Adding something else is a matter of assigning the spare pin to the new hardware in pins.h and then having a function in the main loop (or somewhere more appropriate) run some code that uses the pins.

[edit] Configuration.h

Configuration.h (and configuration_adv.h) are files in Marlin that set all of the specific details of the printer. Each of these is set as a variable which is read by the functions during printer operation. For example, the direction of the end stops can be set here. By defining which direction it is in, the firmware knows whether the print head is at the left or right hand side when the end stop is triggered. In this example you can see that if the firmware was setup for another printer, the print head might try to keep going and smash into something, because it had its direction backwards.

Let’s examine some key lines in configuration.h for the Solidoodle version of Marlin.

#define BAUDRATE 250000

The baud is the speed at which the firmware tries to talk to the computer through the usb cable. It must match in the firmware and the software.

#define MOTHERBOARD 62

This line sets our board to Sanguinololu, which will load the correct set of pin variables in pins.h.

#define TEMP_SENSOR_0 6
#define TEMP_SENSOR_1 0
#define TEMP_SENSOR_2 0

This section specifies the temperature sensors installed on the machine. The thermistortables.h contains values that the firmware will use to read the correct temperature, depending on the sensor. Here we define the hot end and bed sensors as ‘100k EPCOS’. If you upgraded your heated bed to another with a different sensor, you would change the 6 to another number. Marlin is nicely commented with details of what each number equates to.

Note the middle two lines are for the second and third extruders, which don’t exist, so they are set as 0 (‘not used’).

#define HEATER_0_MAXTEMP 215
#define HEATER_1_MAXTEMP 275
#define HEATER_2_MAXTEMP 275
#define BED_MAXTEMP 150

Here the maximum allowed values for the extruder and bed are specified. If the user slips and enters 2150, the firmware will reject the value to protect the printer.

#define PIDTEMP
#define PID_MAX 255 // limits current to nozzle; 255=full current
#ifdef PIDTEMP
  //#define PID_DEBUG // Sends debug data to the serial port. 
  //#define PID_OPENLOOP 1 // Puts PID in open loop. M104/M140 sets the output power from 0 to PID_MAX
  #define PID_INTEGRAL_DRIVE_MAX 255  //limit for the integral term
  #define K1 0.95 //smoothing factor withing the PID
  #define PID_dT ((16.0 * 8.0)/(F_CPU / 64.0 / 256.0)) //sampling period of the
// If you are using a preconfigured hotend then you can use one of the value sets by uncommenting it
// Ultimaker
    #define  DEFAULT_Kp 22.2
    #define  DEFAULT_Ki 1.08  
    #define  DEFAULT_Kd 114  
// Makergear
//    #define  DEFAULT_Kp 7.0
//    #define  DEFAULT_Ki 0.1  
//    #define  DEFAULT_Kd 12  
// Mendel Parts V9 on 12V    
//    #define  DEFAULT_Kp 63.0
//    #define  DEFAULT_Ki 2.25
//    #define  DEFAULT_Kd 440
#endif // PIDTEMP

This section deals with the PID temperature control. PID is an algorithm that aims to smoothly and accurately control the temperature. The alternative is ‘bang bang’, which simply turns the heater on or off for five seconds and then rechecks the temperature before repeating. PID avoids the slow response that bang bang gives, where in the five seconds the temperature continues to rise or fall out of the desired window, fluctuating wildly. The bed, however, is much slower to react and therefore bang bang works fine for it. In five seconds, it’s only likely to change a couple of degrees, so over shooting is not really an issue.

Note that only the Ultimaker P, I and D variables are uncommented. If we wanted, we could test the Solidoodle hot end and chnage these values to offer more accurate control, but the Ultimaker ones seem to work pretty well.

//#define PIDTEMPBED

Note that this line is commented out, leaving PID disabled for the heated bed. If a user were to upgrade to a faster heating bed, they might need to enable PID to achieve reliable control.

//if PREVENT_DANGEROUS_EXTRUDE is on, you can still disable (uncomment) very long bits of extrusion separately.
#define EXTRUDE_MAXLENGTH (X_MAX_LENGTH+Y_MAX_LENGTH) //prevent extrusion of very large distances.

These lines setup safety controls for extrusion. In the case that a line of g-code asked the extruder to extrude plastic for 1km, this will prevent this from happening. Note also the minimum temperature of 170. Below this, the firmware will prevent the extruder stepper from turning so the filament doesn’t strip and/or jam.

// The pullups are needed if you directly connect a mechanical endswitch between the signal and ground pins.
const bool X_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. 
const bool Y_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops. 
const bool Z_ENDSTOPS_INVERTING = false; // set to true to invert the logic of the endstops.

Depending on the end stops fitted, this value may need to be changed to true. The Solidoodle can keep them at false.

#define INVERT_X_DIR false    // for Mendel set to false, for Orca set to true
#define INVERT_Y_DIR false    // for Mendel set to true, for Orca set to false
#define INVERT_Z_DIR false     // for Mendel set to false, for Orca set to true
#define INVERT_E0_DIR false   // for direct drive extruder v9 set to true, for geared extruder set to false
#define INVERT_E1_DIR false    // for direct drive extruder v9 set to true, for geared extruder set to false
#define INVERT_E2_DIR false   // for direct drive extruder v9 set to true, for geared extruder set to false

If for some reason an axis was moving in the wrong direction, after checking the wiring you could invert the logic here.

// Sets direction of endstops when homing; 1=MAX, -1=MIN
#define X_HOME_DIR 1
#define Y_HOME_DIR 1
#define Z_HOME_DIR -1

This is really important setting, as discussed in the example at the top of this section. Getting this wrong will cause the print head to slam into the printer frame.

// Travel limits after homing
#define X_MAX_POS 159
#define X_MIN_POS 0
#define Y_MAX_POS 150
#define Y_MIN_POS 0
#define Z_MAX_POS 150
#define Z_MIN_POS 0

Here we set the coordinates of the print head after homing each axis. Assuming we count the front left corner as 0, 0, the printer knows that it’s in the top right of the bed at 159, 0 after the end stop is triggered. This setting was determined by Ian Johnson and allows the Solidoodle to be used with Repetier-Host.

#define HOMING_FEEDRATE {50*60, 50*60, 4*60, 0}  // set the homing speeds (mm/min)

This setting sets how fast the print head travels when homing. The values are in of X, Y, Z and E (extruder).

#define DEFAULT_AXIS_STEPS_PER_UNIT   {88,88,2268,138}  // default steps per unit for ultimaker 
#define DEFAULT_MAX_FEEDRATE          {500, 500, 5, 45}    // (mm/sec)    
#define DEFAULT_MAX_ACCELERATION      {9000,9000,100,10000}    // X, Y, Z, E maximum start speed for accelerated moves. E default values are good for skeinforge 40+, for older versions raise them a lot.
#define DEFAULT_HYSTERESIS_MM         0, 0, 0, 0  // X, Y, Z, E hysteresis in mm. These are the extra distances that are performed when an axis changes direction to compensate for any mechanical hysteresis your printer has.
#define DEFAULT_ACCELERATION          3000    // X, Y, Z and E max acceleration in mm/s^2 for printing moves 
#define DEFAULT_RETRACT_ACCELERATION  3000   // X, Y, Z and E max acceleration in mm/s^2 for r retracts

These are some of the most important settings. The top line sets how many steps the steppers need to turn to achieve a certain distance. If these are incorrect, the dimensions of the print will not the match the STL file. Max feed rate is the maximum travel speed for the print head to move around.

Acceleration is the rate at which the print head aims to reach top speed. Acceleration is one of the best features of Marlin, and offers good performance with mechanical sympathy. The various settings tweak different elements of the acceleration. The hysteresis setting comes from Neil Martin’s code, and can be tuned to compensate for backlash in any of the four axes.


An EEPROM is an integrated circuit that acts like a tiny hard drive. That is, it can store small amounts of data after power to the machine is cut. By leaving this defined, settings can be stored on the EEPROM so that calibration can be achieved without constantly uploading tweaked firmware.

//Uncomment the line below if you are adding the SDSL SD card reader
//#define SDSUPPORT // Enable SD Card Support in Hardware Console


//Uncomment the line below if you are adding the Panelolu / SD card reader combo
//#define ULTIPANEL

These lines enable support for the extra features, being an SD Card reader and Panelolu respectively. The Solidoodle Marlin firmware has been setup so that if either of these have been added and wired correctly, the single line is uncommented to enable them.

Configuration_adv.h also contains settings, but they are generally more obscure and can be ignored by most users.

[edit] Software

As Arduino microcontrollers are very underpowered compared to a proper computer, software is used to do a lot of the heavy lifting. The Arduino firmware and hardware is simply not up to the task of rotating, placing, scaling and slicing STL files.

Marlin and other firmware is therefore setup to accept commands over the USB serial connection, and send feedback in the same way. Software such as Pronterface, ReplicatorG and Repetier-Host are designed to connect to the printer (remember the baud?) and send and receive data. Technically, software to control the printer is not needed if you have a Panelolu, as physical control of the print head is available, as well temperature control and the ability to load g-code and print from an SD card. Good software makes the whole job easier of course.

The Arduino IDE is another piece of key software, as it is used to upload updated firmware to the microcontroller. To get the Arduino IDE to recognise Arduino clone boards such as the Sanguino, files with configuration information must be dropped into the 'hardware' folder.

It is also important to mention that there are different versions of the Arduino IDE. Marlin requires version 022, which is not the most current. Attempting to update the printer firmware with version 1.0.1 will only yield errors and frustration.

[edit] Marlin Features

As well as the previously discussed acceleration, Marlin offers some great functionality such as look ahead. Instead of reading and then completing g-code based movements one at a time, look ahead loads the next ten commands into a buffer to smooth out operation. This minimises pauses and therefore blobbing, allowing a smoother printed surface.

Another key feature of Marlin is the built in support of LCD screens and SD card readers. By default these are disabled to keep the sketch size down, but can be enabled easily. Alternative firmware such as Repetier is said to have improvements in other areas, but for those needing the LCD support, it’s simply not an option.

Makerbot firmware is different enough to other RepRap firmware to be a headache. The g-code command codes are different for some functions, and the hardware is different too. This means adapting Makerbot or Sailfish firmware is much harder.

[edit] Conclusion

Hopefully this text helps people understand the magic behind 3D printers a little more. It is quite long, but then again there are a lot of aspects to the system. The revelation comes when you realize that the system is made up of smaller, much simpler parts. Every time you understand an individual part, the bigger picture becomes a little clearer. The best thing to do to really get a grasp on the electronics is to start playing with Arduino boards and build projects documented on the web. After this, the language and functions used in the 3D printer firmware become a lot easier to understand and modify.

Personal tools