What is this TTL/PWM stuff about?

The reason for writing this article is the post about me building a laser engraver. I decided to make this an article of its own, because it might be interesting enough for other purposes.


Digging in a bit further when investigating why my laser module claims to support both TTL and PWM (how two?) I found that TTL is just a digital signal with 5 volt being HIGH and 0 volt being LOW.

Well, that’s actually oversimplifying things, in reality there are some thresholds like anything up to 0,4 volt being LOW and anything above 2,4 volts being HIGH or something along those lines according to wikipedia. At least conceptually however, 0 volt is LOW and 5 volt is HIGH.

Translating this to a laser it would mean that providing it with 0 volts would have it turned off and providing it with 5 volts would turn it on.


PWM is a way to modulate intensity using a digital signal when controlling for example an LED or a motor or something else I haven’t imagined. It will definitely not work for all devices, but motors and LED’s are good examples of what works.

Basically PWM allows you to drive the brightness of an LED or the speed of a motor. It does so using a digital signal that is turned LOW or HIGH over time and hence you could say that it uses TTL (at least when the voltage is 5 volt, for other voltages I guess it is not TTL in a pure sense?).

If we want an LED to be completely lit we will supply it the HIGH voltage. When we want it completely turned off we supply the LOW voltage (0 volt). If we want to control the brightness we give a signal that varies between LOW and HIGH over time. So if we want a brightness of 50% that means we give it a signal that is LOW 50% of the time and HIGH the other 50% of the time. This works because we repeat this really fast. The process of turning it on and off is in a very small time frame.

To illustrate what PWM does I have created a simulation using tinkercad. It shows an LED fading from off to on. On the right side of the LED it shows the signal on a simulated oscilloscope, which is a square wave. ezgif-3-3b780b172ec6

By ranging the width of the block in the square wave we control the amount of time it is LOW or HIGH and thus when it is on or off. By doing this really fast we can control brightness, speed or other stuff I haven’t imagined.

The code for the Arduino is:

int led_port = 9;   // the PWM pin the LED is attached to
int brightness = 0; // how bright the LED is
int fadeAmount = 1; // how many points to fade the LED by

void setup() {
  pinMode(led_port, OUTPUT);

void loop() {
  analogWrite(led_port, brightness);

  brightness = brightness + fadeAmount;
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;


Building a Laser Engraver

In 2019 I started building a laser engraver. Here I will document some of the joys and  problems I faced in the process.

Base Design

A friend of mine pointed me to a 3D printable laser engraver design (here), which I used as a starting point. The design uses some 2020/2040 aluminium profile and 3D printed parts as a base. Part of the design is to shove the aluminium profiles in some of the 3D printed parts to join them at the corners and create a rectangular shaped base.

After printing the parts and trying to assemble it, some printed parts immediately broke. I immediately disliked this part of the design and didn’t quite understand why one would take this approach when 2040 aluminium can be bolted together easily, which is way more solid and wouldn’t lead to breaking 3D printed parts. So I decided to modify that part of the design and simply bolt the aluminium and design some new ‘feet’ for the construction. This helped and I could mostly use the rest of the original design.

Modifying the Design

I had to design some new 3D printable parts and made good progress in getting the base together. By base I mean the whole construction with the stepper motors and the timing belt used to drive a laser on two axes.

In the first months I was able to create a base that I liked and get the mechanical parts working. I had the stepper motors working and could drive the position of the laser using G-CODE, so I could basically use any laser engraving software to control the device. This was the fun and satisfying part. The hard part came when I had to drive the laser itself.

Controller Board

Another part about the design that I wanted to modify is the controller. I didn’t want to use an Arduino Uno and after reading about a controller board built by Bart Dring, I decided to go with that because it uses an ESP32 microcontroller.

When receiving the board it looked like this:


And after installing the ESP32 microcontroller and the stepper drivers it looks like this:


The X,Y and Z-axis stepper motors each have their own driver and SpinPWM is the port that controls the laser. Because an ESP32 is the microcontroller it has WIFI and Bluetooth, which is pretty cool. It also has an SD card slot and it has some connections for limiters (end stops) and other things that I may not fully grasp yet. But that is something for the future.

Driving the Laser

I ordered the strongest diode laser I could find on AliExpress, a 15 watt laser module, because why settle for less?

According to its specifications it would operate on 12 volts and take a PWM or TTL signal at 5 volts. This confused the hell out of me to be honest. PWM or TTL? Is that the same then? I understand what PWM (Pulse Width Modulation) is and does, but to be honest I have no clue about how TTL (Transistor-Transistor Logic) works.

I had hooked up the laser to the SpinPWM port and after hooking things up, nothing worked. So I used my cheap multimeter to measure the voltage and was a bit surprised, it was so low (not sure what it was anymore, but at most around 3.3 volts). At this point I couldn’t be sure what was going on.

At this point I realized I didn’t have the right tools for the job, because I wasn’t quite sure what the signal was giving me and a simple multimeter will not help me figure it out. At this moment I decided to let this whole project rest for a bit and order myself a cheap oscilloscope (a DSO138).

When the oscilloscope and some spare time came along it was time to do some investigation. Like, what is this TTL/PWM stuff about?

Calibrating the Extruder

There are plenty of sources explaining how to calibrate the extruder of a Bowden extruder with the Marlin firmware, but they are usually a bit lengthy for my taste and I’m way too impatient for all that, so here’s the short version. If you are already familiar with the process and just need the formula go straight to formula.

Calibrating the Extruder

Marlin will not allow you to control the extruder motor if it is not heated by default, or at least with the firmware configured like I have. So go to Prepare > Preheat PLA and wait for it to heat up to 180 °C.

Next go to Prepare > Move Axis > Move 1mm > Extruder.

Extrude a certain amount of filament (I used 120mm) and measure the length of the filament coming out. I now got 131mm which is not the 120mm I expected. The problem is my configuration. Here’s an excerpt from my configuration.h in Marlin:

// @section motion

// default settings
#define DEFAULT_AXIS_STEPS_PER_UNIT   {80,80,4000,107}

The latter value is of 107 needs to be adjusted. We will call this value E0 and calulate the right value using the formula following now.

The Formula

E0 = (desired length / actual length) * E0.

So that is the desired length of 120mm divided by the actual length of 131mm and multiplying the result of that with the configuration value E0, which is 107. In this example you end up with (120/131) * 107 = 98. These values are just an example. The real value I calculated ended up being 102, but I don’t remember the values I was working with.

Replace the value in the config file and flash Marlin again and it should be feeding the desired length of filament. Measure again and repeat if needed.

Burning a bootloader (OptiBoot) on an Arduino Pro Mini using an Arduino Uno

The other day I got asked to look into burning a smaller bootloader (Optiboot) onto an Arduino Pro Mini to save some space on it for actual program code. I used an Arduino Uno as in-system-programmer (ISP) to get the job done. I think there are plenty of sources that document this, but I wanted to keep track of my progress and share my findings.

SPOILER : It turned out to be simple to burn the Optiboot bootloader on the Pro Mini once you understand that it is the default bootloader for the Arduino Uno board. You simply need to burn the Arduino Uno bootloader on the Arduino Pro Mini. So in this case that means burning the Arduino Uno bootloader on an Arduino Pro Mini using an Arduino Uno. Are you still with me? I’ll explain the ride below.

Programming the Arduino Uno to Serve as ISP

The first thing to do is set up the Arduino Uno as an ISP. To do so connect the Arduino Uno to your PC (I’m on Windows) as you normally would and in the examples section open ArduinoISP.


In Tools -> Board select Arduino/Genuino Uno and upload as you would upload any other script to the Uno.


The Arduino Uno is now an in-system-programmer you can connect with any AVR compatible microcontroller (like the Arduino Pro Mini or other Arduinos) to program it.


In my case I had to solder some headers onto the Arduino Pro Mini to be able to connect the pins I need to connect, which are: VCC, GND, RST, MISO, MOSI.


VCC and GND are for power, RST is the reset line, SCK is a clock line (Serial Clock) and MISO and MOSI are for hooking up the Pro mini as a slave device of the Uno. MISO stands for: Master Input Slave Output and MOSI stands for Master Output Slave Input.

Burning a Bootloader (Not Optiboot)

Once the wiring is done the following settings need to be made to flash a bootloader to the Pro Mini:

  • Under Tools -> Board select Arduino Pro or Pro Mini.
  • Under Tools -> Processor select ATmega328 (5V, 16MHz).
  • Under Tools -> Programmer select Arduino as ISP (NOT ArduinoISP!!!)

Now you can burn the bootloader using Tools -> Burn Bootloader.

The question is however: which bootloader was burned to the Pro Mini? I needed a specific bootloader (Optiboot) to save up space and had no idea which bootloader I just burned to the Pro Mini. I guess the default one, but which is that? I figured out later that the first step is where I was going wrong. If you are here to get an answer on how to burn the Optiboot bootlaoder you can skip the following section and head to Burn Optiboot onto the Pro Mini.

The following section serves only as a bit of background that was part of my process in figuring out what bootloader I burned. It didn’t get me there directly, but is still interesting.


Having burned the default Pro Mini bootloader I realized Arduino IDE simply calls AVRDude to do so and I hoped to find an answer as to which bootloader I had now burned. I enabled more verbose logging in Arduino IDE to find out how it calls AVRDude.

I went to File ->  Preferences and enabled verbose output during both compilation and upload:


I now burned the bootloader again using Tools -> Burn Bootloader to find the following log output (excerpt):

C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude -CC:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf -v -patmega328p -cstk500v1 -PCOM5 -b19200 -e -Ulock:w:0x3F:m -Uefuse:w:0xFD:m -Uhfuse:w:0xDA:m -Ulfuse:w:0xFF:m 

avrdude: Version 6.3, compiled on Jan 17 2017 at 12:00:53
         Copyright (c) 2000-2005 Brian Dean, http://www.bdmicro.com/
         Copyright (c) 2007-2014 Joerg Wunsch

         System wide configuration file is "C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf"

         Using Port                    : COM5
         Using Programmer              : stk500v1
         Overriding Baud Rate          : 19200
         AVR Part                      : ATmega328P
         Chip Erase delay              : 9000 us

Here you can clearly see that it simply runs avrdude with some of the settings we provided in Arduino IDE along with a reference to some configuration file named avrdude.conf. This is interesting, but the command itself doesn’t tell me which bootloader I just burned nor does the configuration file it references.

I figured that I could modify the avrdude command provided in the log to specify a specific bootloader should get the job done. After some quick googling I found something along these lines should work for a hex file named filename.hex:

"C:\Program Files (x86)\Arduino\hardware\tools\avr/bin/avrdude" -C"C:\Program Files (x86)\Arduino\hardware\tools\avr/etc/avrdude.conf" -v -p atmega328p -c arduino -P COM5 -b 115200 -D -U flash:w:filename.hex:i

I had to wrap the file path in double quotes because of space in the path and even though I didn’t have any hex file named filename.hex I would see the following in the output (excerpt):

Reading | ################################################## | 100% 0.01s

avrdude: Device signature = 0x1e950f (probably m328p)
avrdude: safemode: hfuse reads as 0
avrdude: safemode: efuse reads as 0
avrdude: reading input file "filename.hex"
avrdude: can't open input file filename.hex: No such file or directory

This seemed promising. Apparently I’m able to upload a hex file this way using the command line by running avrdude.exe with different arguments. However, when trying to flash the bootloader of choice (OptiBoot) I would end up with some verification errors for reasons not obvious to me. I was probably doing something wrong on the command line or using a wrong hex file.

Interestingly there are tools that basically do the same thing: simply run avrdude.exe with some arguments, yet provide a Graphical User Interface to do so because command line interfaces suck if you don’t use them in an automated fashion.

An example of such a tool is XLoader, but that one didn’t work out for me when I tried. Arduino IDE also seems to be doing the same thing: run avrdude.exe to flash the bootloader, so there must be some way to specify which bootloader in it. As it turns out there is a way to do this, but it isn’t very obvious.

Burn Optiboot onto the Pro Mini

The bootloader I wanted to burn is called OptiBoot and can be found at https://github.com/Optiboot/optiboot. It turns that it is even the default for the Arduino Uno, so all I had to do differently when Burning a Bootloader is select the Arduino Uno as board. The first step becoming:

  • Under Tools -> Board select Arduino/Genuino Uno

So to sum it up:

  • Under Tools -> Board select Arduino/Genuino Uno.
  • Under Tools -> Processor select ATmega328 (5V, 16MHz).
  • Under Tools -> Programmer select Arduino as ISP

 (EDIT: These last two steps that I have striked through are not available in Arduino IDE. I seem to have made an error while documenting these steps. Please refer to the comment section at the end to see what is up. Over there Daniel gives some feedback indicating the mistake. Sorry for any inconvenience)

Now you can burn the bootloader using Tools -> Burn Bootloader.

So, that is it right? Well, I’m not really satisified even though the job is done. If you look at the documentation the answers are there, but what is up with this magic about what bootloader is flashed on what board in the first place?

Boards Configuration

I dug a bit deeper and learned that there is a place where all the boards are defined. On my system I found the file in:

c:\program files(x86)\Arduino\hardware\arduino\avr\boards.txt

This is where Arduino IDE specifes which hex file to upload as bootloader and gives a whole new meaning to the boards section in Arduino IDE for me. Let’s look at an excerpt of the configuration for the board we have now selected, the Arduino/Genuino Uno:


uno.name=Arduino/Genuino Uno





It specifies the hex file right there under the uno.bootloader.file configuration value.

At least I found a match between the board and the bootloader, explaining why it works with this board selected. This also gives an opportunity to change the hex file and thus changing which bootloader is uploaded to a specific board. I could go to the config section for the Pro Mini and set this bootloader as the default and not deal with this in the future. Too bad for me this was a one-time job and I don’t care about future calls, but at least it was educational and I got to write this blog post.

Z-Axis problems

The Cherry 3D printer I’m building is an awesome design that I like a lot. However, the mechanics for the Z-axis is something I have less love for and has given me quite a headache.

Unlike the X and Y axes the Z-axis is driven by two separate stepper motors. The Z-axis needs to move up and down on the same speed. This seems asking for problems to me because if one of the motors doesn’t have enough torque for some reason, e.g. because it is blocked, you have a big problem. Unless you happen to notice and stop it in time it will basically tear itself apart.

It somehow seems to be perfectly accepted to drive an axis using two stepper motors in 3D printing land. The controller that drives the whole thing even has a dual output for the Z-axis, allowing you to drive both steppers using a single driver.


Below you can see the RAMPS 1.4 board that is the controller board for the printer. It sits on top of Arduino 2560 to drive the motors, extruder, heated bed and LCD display for a 3D printer or similar device. I may even be forgetting some other features it has, but that basically sums it up.

ramps motor pins.png

Notice the five headers marked (E0, E1, X, Y, Z) which are the outputs for the stepper motors. Each stepper motor is driven by a so-called driver module that is situated close to each output. The driver modules are the little modules with the heatsink on top of them.

Every header is for a four-wired connector that can be connected to a single stepper motor, except the one for the Z-axis which supports connecting two stepper motors.  So, it seems perfectly normal to hook up two stepper drivers on a single driver when it comes to the Z-axis. I have also read about other designs doing the same for other axes.

I had the  X and Y axis working in no-time, but the Z-axis I never really got to work like intended. I had most of the printer done and it seemed it just wouldn’t have enough torque to make it work.

Finding the Culprit

My first hunch was there would be something wrong mechanically. If the motors just didn’t have enough torque because it required too much force to move along the axis on either side of the Z-axis that would be a very valid reason for it to fail. I didn’t see any mechanical reason so my next hunch was a power problem of sorts.

The motor drivers have a little potentiometer on them that allow you to control how much current can run through the stepper, so I thought cranking this up might be a solution, but alas it did not work. One of the people of the 3D printing club that helps me to make this printer even tried hooking up only the stepper motors without them driving anything mechanical and the problem would be the same. Clearly wasn’t a mechanical problem. It must be a power problem of sorts.

Solving the Problem

I thought about what it means to hook up two steppers on one driver. Basically, the steppers are driven in parallel. What would happen if I would connect them in series instead of parallel? I created this little prototype board that would allow me to connect the motors in series instead of in parallel. I would hook this up to a single output for the Z-axis and then have it connect two steppers in series instead of parallel, following this wiring schema.


It seemed to do the trick! That is, until I tested it extensively to find that it wasn’t reliable enough and therefore one in the category of: close, but no sigar! It would at least be able to drive two motors unlike in parallel, but it would still fail occasionally.

I tried for quite a while to figure out wat was going on, but I got fed up along the way.  The whole thing that bugged me is that others at the 3D printer club supporting me kept claiming that they had the same controller, drivers and even motors and it would just work. Not for me. So it was time for a different solution.

I gave up on the problem and decided that at least I should be able to drive the two steppers with a separate output for each. There are two outputs for extruders and I only have one extruders, so I could live with sacrificing this extra output for the second Z-axis stepper. The Marlin firmware has support for this so I decided to go with that.

Later on when other people started finishing their construction of the Cherry 3D some would have the exact same problem, while for other it would just work. Everyone who knew anything was scratching their heads. The best guess is that I and a few other are so unlucky to have a production problem somehow. It could be anything from the Arduino to the Ramps, the drivers or the steppers.

Building a Cherry 3D Printer

Recently I started building my own 3D printer with the help of some awesome people I got to know at “De Jonge Onderzoekers” in my home town Groningen. Over there they have a 3D printing club where people build their own printers and share knowledge. At some point they offered others the possibility to build a printer with their support and this is where I started as well.

Although some small modifications are made it is basically the Cherry 3D (https://www.instructables.com/id/Cherry-60-3D-Printer/). Apparently, the design is built by a 16-year-old kid. Very impressive.  It also is a pretty interesting design because a lot of parts for it are 3D printed, so to some extent you could say it is a 3D printed 3D printer!


I made a lot of progress at this point, but I a haven’t printed anything yet. The X and Y axes are working perfectly. The Z-axis works as well now, but that one has given me enough trouble to describe in a seperate blog post.