Bus Servo Draw Bot

I wanted to complete a start to finish project with the LX-16A bus servos to do a complete review of their viability for the type of mechatronics projects I do. The low price of the LewanSoul bus servos make them a competitive option over digital servos. I chose to do a remake of the Line-Us clone drawing machine because I would not need to spend too much design time and it would be a good 1:1 comparison with digital servos. Since the bus servos are quite a bit larger, I decided to scale up the machine by 1.5x.

Made My Own Brackets.

I started by buying one servo and it came with brackets. When I went to get more, I noticed the price was lower. I did not realize I was getting these without brackets. These are the brackets you get with the more complete kit.

I requested some 3D models from LewanSoul. They were only able to provide 2D DXF files, but they were easy to convert in Fusion 360. This allowed me to 3D print some brackets. It actually worked out quite well because I was able to thicken up the brackets and integrate some captive square nuts.

They mounted easily to the servos and were plenty strong for this project.

Servo Arms

I made two arms and one short cam for the Z. They were about 4mm thick and had a little pocket that slid over the standard round actuator. They screwed on with the screws that come with the servos. Before mounting anything I turned on the servos and moved them to the center of the range. This put the arms at a known angle.

Support Bracket and Base

The support bracket holds all three servos and there are 2 pockets on the bottom for some shaft bushings.

The base has two shafts pressed into it.

The shafts slide into the bushings and there is a spring to hold the parts together.  The spring prevents the pieces from separating and also provides a little extra pull down force in case the shafts bind a little. The cam provides about 6mm of lift.

Final Assembly

The servos are mounted to the support bracket.

The wires are connected to the servos. They just daisy chain from one servo to the next.

The remaining links are then connected.


Here is a video of the first run.


I think these are a good alternative to digital servos. They are very strong, easy to mount and accurate. Depending on the design of the controller, using a simple UART might be easier than having multiple PWM signals or extra hardware. The servo’s size might be larger than some machines need but that comes with the higher power.


LewanSoul Lobot LX-16A Serial Servo Review

I stumbled upon these LewanSoul LX-16A Servos the other day on Amazon while searching for standard digital servos. These servos are digital serial bus servos. That means they use a serial protocol on a bus rather than a PWM signal. I have used bus servos before, but the $12 price got my attention. That competes well with plain old PWM servos.

Serial bus servos have some real advantages over standard PWM servos.

  • Wiring: The wiring can be a lot simpler because you can put all your servos on a single 3 wire bus. Each servo has 2 connectors to make daisy chaining easier.
  • Higher resolution: The resolution is typically higher. It depends on the way they sense position. These use a high accuracy potentiometer and list 0.24° as the resolution.
  • You can set the speed: You can set a destination and speed for each move.
  • Set the range: You can limit the range of the servo. This is great if the using the full range would crash a joint on your machine.
  • Continuous turn mode: There is a speed adjustable continuous rotation mode on these, but absolute distance moves cannot be done.
  • Motor On/Off: Turn the motor off for manual movement.
  • Feedback: The communication is bi-directional so you can query a servo for…
    • Position: If you manually move a servo, you get its position. This is great for recording “poses” or setting range limits.
    • Temperature: You can read the current temperature of the motors.

Compared to Robotis

I have used the Robotis Dynamixel XL320 servos before but these are a lot stronger and the XL-320 has a weird, plastic rivet, mounting systems that I am not fond of.

Here is a size comparison with a XL-320.


Spec LX-16A XL-320
Max. Torque 17 kg-cm 4 kg-cm
Resolution 0.24° 0.29°
Range 240° and Continuous Rotation 300° and Continuous Rotation
Speed 62 RPM 114 RPM
Weight 52g 16.7g


To use the servos you need to use one of their controllers. The most basic controller just converts a USB or TTL serial signal to their protocol. The controller is small and low cost ($10). You can send commands via a USB (Com Port) or via the TTL pins.

Setup Program.

They have a setup program.  The program is Windows only and I had to run it in Administrator mode to get it to work. This makes setting up the servos easy, but you could write your own program if you don’t want to use theirs.

TTL Control

They also provide some Arduino Sketches. They worked fine and are a good place to grab some code if you are writing your own program.  The sketches use the Arduino hardware TX and RX pins. That conflicts with uploading, so you need to disconnect the controller every time you upload. I edited the sketch to use SoftwareSerial on some other pins and that made playing with the code a lot easier.

First Impressions

I found the servos very easy to use and they appear to be strong and responsive. I think they will be a good option for my on my machines.

Next Steps

I want to test these in a real machine. I thought I might try to make a slightly larger version of my Line-Us clone. That would be a good comparison of accuracy. I might try one day build on it tomorrow.  I can probably get a machine designed and built in a day, but the controller programming would need more time.


Pen/Laser Bot Controller

This a CNC controller I designed for small laser engravers and drawing machines. It is for sale on Tindie. It is designed for machines that are primarily 2 axis, but may use a servo for the Z axis.  The controller is designed for use with Grbl firmware running on on an Arduino Nano controller. It uses plug in modules (not included) for the micro controller and stepper drivers. This keeps costs down and gives the user more options. Everything is pinned out for the default configuration of Grbl. This is compatible with all of my recent projects.


  • Power Connector: A standard barrel connector for motor power for the stepper drivers. Typically this will be 12V, but can be run up to 24V if your parts are compatible with higher voltages.
  • Controller: Arduino Nano Footprint.
  • 2 Stepper Drivers: Pololu Footprint
  • Servo Connector: The connector is the standard pinout for most servos.
  • 5V Power Supply: 1 Amp power supply to power the servo.
  • Laser Connectors: There are 2 connectors. One is power and ground for the laser. The other is for the PWM signal to fire the laser.
  • Aux Power Connectors: There is a connector with the primary motor power. This can be used for fans, relays, etc.
  • Limit Switch Connector: X and Y limit switches are available on the connector with convenient ground pins.
  • Control Switch Connector: Feed hold and start switches can be connected to this.
  • Raspberry Pi Interface: This is an optional interface to plug in a Raspberry Pi or any compatible controller that shares the  standard header connector.


The footprint is designed for an Arduino Nano. These are available from many sources and can cost as little as less than $4. Be sure to install it in the correct orientation. The controller is typically powered by the USB cable, but will automatically switch to the 5V power supply is the USB is removed.

There are several other controllers that share the same footprint. They can be used, but you might need to change a few components if the voltage is not 5V. Make sure you plug it in correctly. While the pinout is the same it might need to be rotated 180 degrees. Contact me directly if you have questions regarding alternate controllers.

Use this view to confirm the orientation (note the pin labels on the Nano. Click to enlarge)

Stepper Drivers

This is designed to use Pololu compatible stepper drivers. The pinout is shown below. Insert them correctly or you could destroy them and possibly other items. There are dozens of compatible designs.  Pololu makes very good ones, but much cheaper version can be found on eBay and Amazon.

Servo Connection

Std Grbl does not support Servos

Limit and Control Switches

Laser Connection

Note: Lasers are very dangerous and no system is completely safe. The firmware is not fail safe and the laser could fire at any time power is available to it. Use safety glasses at all times power is applied. Enclose the laser with an interlock to remove power if covers or doors are open. Evaluate the entire circuit including this controller to determine if it provides the safety you need. If this controller is part of a laser you built, you are responsible for all aspects of safety.

The lower white connector is for the laser power. It is labeled VMot and Gnd. VMot is the voltage that is supplied on the barrel connector. Make sure you have the right power for your laser module.

The upper white connector is for the laser on/off control.  Pulse is the signal and there is a ground pin if you need it.


Raspberry Pi (Optional)

This can work as a HAT for a Raspberry Pi. It connects the hardware UART on the Pi to the Nano.

Solder in the supplied connector on the bottom of the board. It is not installed by default to allow more mounting flexibility if you don’t use a Raspberry Pi.

Setup the Raspberry pi to use the serial port. By default the port is used as a serial console. You need to stop that and free it up for your use. See this post for more information.

Do not use the USB while a power Pi is connected or the there will be two things trying to talk to the controller. This includes uploading firmware.

Note: Arduinos use a trick with a DTR control line in the USB-UART on the Arduino. This forces a reboot every time a connection is made. The Raspberry Pi cannot do this. Some senders are expecting Grbl to reboot when connected to and can be a little confused at startup. If you connect a serial terminal you will notice there is a no Grbl startup string at connection. Just type $I (with carriage return) to see the Grbl version info.

Open Source



A Polar Pre-Processor for the Pen Bot Written in Python

I got a little push back on the Cartesian to Polar gcode processor because it was a Windows, Visual Studio C# program. I rewrote it in Python, to make it more accessible to other operating systems.

I don’t do much Python programming, so I probably did some thing in a very non Python style, but here is is.

Usage: The program will accept 1 or two command line arguments. The first is the file you want to convert. The second the the output file name.  If you skip the second, it will just append “_polar” to the input file name.  For example box.gcode will be converted and output as box_polar.gcode.

PolarPreProcessor.zip (python file)

Before and After Example GCode

Here is the gcode for the logo if you want to test.

Visual Examples

To get a feel for what the translation looks like, here is what a simple square looks like in gcode before translation.

And here is is after translation

Here is what that python logo in the first image looks like in gcode after translation.


Here is a video of it drawing the Python logo.


The Polar Coaster – A Drink Coaster Drawing Machine

I designed this machine to draw custom, round drink coasters. I already have a laser cutter for square coasters and I wanted to try something unique for round coaster.

The Base

The base of the machine has two stacked 5mm bearings in the center for the bed to rotate on. There are (3) 3mm bearings on the bed perimeter that provide support and keep it level. They have little shafts that snap into the base.

The Bed

The bed is  a 156 tooth GT2 pulley. It has little springy fingers that grip the coaster when it is on the bed. The bed connects to the motor pulley with a closed loop belt.

The Radial Arm.

This is a belt driven, cantilevered arm that uses 6mm shafts and linear bearings. The belt is a cut pieces with the ends clamped at the carriage. It has a slotted mounting hole that lets the arm rotate. The pen must be adjustable to get to the exact center of the coaster or the drawing will be distorted. There is a limit switch on the top.  This is the only axis that needs to be homed. To setup the machine you home it and jog the pen until it is exactly over the center of the bed. You then set the work zero for X (Gcode: “G10 L20 P0 X0”). This only needs to be done once. If you use different types of pens, the center should be rechecked.

The Z Axis

The Z axis uses a micro servo and a cam to control the height of the pen. The firmware is setup to only have (2) Z positions, pen up and pen down. It uses 3mm rods and tiny little 3mm linear bearings.  There is a compression spring on one of the rods that applies a little pressure to the pen, and allows the pen to float a little on uneven coasters.

The Controller

I used my Grbl HAT controller. It is a bit overkill for this project but works perfectly.  It is attached to a Raspberry Pi in this photo, but I have not been using the Pi in this project yet. I just connect directly via USB.

Kinematics and Pre-Processin

See this blog post on how it was done. The pre-processor is written in C#, but it is rather simple and you could probably read the source file and convert if you cannot deal with C# on Windows.


I use a modified version of Grbl 1.1f.  Grbl does not support servos, so I needed to hack that in.  I used the PWM that is normally used for the spindle speed to control the servo. I turned off the variable speed spindle option and streamlined the spindle functions to the bare minimum I thought Grbl needed.  I adjusted the PWM parameters for use with a servo and added pen_up() and pen_down() functions. I tried to put as much of the custom code into one file spindle_control.c. I had to add a few lines in stepper.c to look at the current machine Z height and apply the correct pen up/down function.


You can use anything to generate the gcode that works with Grbl. The pen will go up when the Z is above zero and down when it is below zero. Therefore, you want the Z movement as short as possible to speed up the drawing and not have the pen dwell on the material and bleed.  I make the depth of cut 1mm and the z clearance 3mm.

CAD Files.

The design was done using PTC CREO 3.0.  A STEP version of the design is linked at the end of the post.


It does a great job. Here a recent coaster. This was done from a rasterized bitmap image found online (searched: circular Celtic braid).

Here is a Fat Tire beer themed coaster.

Coasters are made to be super absorbent, so larger tipped felt pens tend to bleed a little too much. I like to sketch with Micron pens and the thinner ones really work well on this machine.

Build You Own?

The build is not difficult, but covers a lot of areas. You should know how to work with STEP files and compile firmware.

The design is open source with no commercial restrictions, so feel free to use any part of my work. I found most of the parts on Amazon and eBay. I bought the belt from Stock Drive Products. The polar motor pulley is 36 tooth and the arm pulley is 20 tooth.  Cutting the shafts requires an abrasive cutoff wheel.

Please post any questions in the comments section and I will try to address them.







Polar Pen Machine Kinematics

When you have a round work piece like a drink coaster, it makes sense to have a round work area.  A round work area works best with a polar coordinate system. A polar coordinate system uses an angle and a distance from a center point to define a point in 2D.

The problem is that most drawing and CAM programs work in Cartesian (X,Y,Z) coordinate systems. My machine controller firmware, Grbl, also works in normal linear X,Y, and Z. The process of converting one system to another uses Kinematics.


The Firmware

The firmware is side is actually quite easy. I defined the X axis as the distance in mm from the center (the radius). The Y axis will control the angle. The Y axis is setup so that millimeters will equal degrees. If I tell the Y to move 360mm, it will actually rotate the work area by 360°.  I could have used radians, but my brain works a lot slower in radians.

The machine will only need to home on the X axis. It needs to know where the exact center of the work area is. The starting angle does not matter because the coaster is a circle.

The conversion from X, Y to polar is probably won’t fit in into the firmware, so the X, Y conversion is done in a preprocessor software program. The X,Y gcode is output from normal CAM programs, then run through a conversion program.

The Conversion Program

The program reads the X,Y gcode, converts any X or Y coordinates into polar coordinates and outputs a new gcode file. The sender simply sends the new files.  The math is actually quite simple.

Typical Gcode sends line data by giving the end points of lines. You simply draw from one point to the next, unfortunately this creates a few problems with a non linear machine.

The basic non-linearity problem

If we were trying to draw the green square centered on the work area, the generated gcode would basically send the corner points. Each corner point has an equal radius to the center. Therefore, the pen will never change radius when going to the next point. This will result in a circle. We want the green square, but we get the red circle.

We need to calculate each point along the way to stay on the desired path. The preprocessor divides the line into tiny segments. Each segment has the same problem, but at a scale you won’t be able to see.

The Spiral Problem

If we are drawing a shape that crosses the 0° angle we don’t want the angle to spin the wrong way. If a point is at 350° and the next point is 10° (crosses over 0) we don’t want it to spin backwards from 350° to 10°. We want it to go to 370°.  It happens anywhere the angle difference between 2 points is greater than 180°. The program will choose the shortest direction even if that means going above 360° or below 0° degrees.

The Feed Rate Problem

Feed rate, in CNC terms, is the speed of the tool across the material. The CAM software is setting the feed rate as if this were a Cartesian machine. On this machine, if you were drawing a circle, you would simply move 360 units in Y. Without compensating feed rate, the pen would move across the work piece faster for larger diameter circles. I want to do some sort of compensation to help with this. The coasters are very absorbent, so the  lines look thicker if the speed is slower. A consistent speed will help the quality of the work.

Since the lines are all very short, the easiest way to compensate for feed rate is to use the current radius. With a simple circle, Grbl thinks the machine moved 360mm. The real distance is easy to to calculate from the perimeter of that circle.

We can compare it to the 360mm (full circle) and apply the ratio to the desired feed rate from the CAM program.

polarFeedrate = cartesianFeedrate * 360 / (2 * pi * radius)



Here is a video of it. The machine is rerunning a file to see the repeatability.

Next Steps.

I would like to automate the preprocessor.  I think a Raspberry pi, might be an easy way to do this.  It would sit between the sender and the controller.




Coasty Update

Here is a quick update on Coasty. Several people have asked if I am releasing the source files or selling a kit. I am adjusting the design to make that more viable.  The original version was made with parts I had laying about and not necessarily the best design choices for an open source project.

X Axis.

Originally I used an TR8-8 ACME thread lead screw. It was mounted to the motor by drilling a hole in the lead screw and epoxying it to the motor shaft. This worked well, but you needed a lathe to drill the hole and a special low backlash nut. The axis was also a little loud with and all metal design.

I changed to use a GT2 open belt cut to length.  Belts and pulley are really easy to get and don’t cost too much.


Need to shorten some wires after testing.

There were some issues with the EleksMaker electronics that I did not like. The laser circuit did not appear to have a pull down on the signal and it tended to fire if the Arduino was not pulling it low. This would happen during reboot and other scary times. The wiring was also quite a pain. There were no connectors for the limit switches so you had to directly solder to the Arduino Nano.

I changed to use a custom PCB that is the entire rear panel. This contains all of the circuits including the limit switches. Building a Coasty was a little like building a ship in a bottle. Now the bottle has no bottom and there are less parts inside.

Front Door.

The front door now has a window. This makes the machine more fun to watch and no glasses are required.

Next Steps.

I have one build and am testing it for a while. If all goes well, I will release the source files and consider a kit.


Using The Grbl HAT

Getting the Kit

The kit is available in my Tindie shop.

Getting the plug-in modules

The kit does not come with the stepper drivers or Arduino Nano modules. The point of the design was to keep costs low by using modules. At this time I cannot sell the modules anywhere close to what you find them for at other retailers. You must get them on your own.

  • Stepper drivers: I think the company that first set this form factor is Pololu. There is also an open source version call the StepStick. They typically use the A4988 driver chip from Allegro, but compatible modules with other chips are also available. You should search Pololu, Amazon, eBay or AliExpress for StepStick or A4988.  Make sure it has the pinout shown below (as viewed from top) and will work at 12V. You should be able to find them for around $3 each. It is best to get ones with heatsinks, so they can run at higher currents.

  • Arduino Nano: The Arduino Nano is a small version of the Arduino Uno.  It uses the same microcontroller chip as the Arduino Uno (ATMega328p). You will need a USB cable, so make sure you have one. Depending where you buy the Nano, it could have a mini or micro USB connector. You can often find them for less than $4.

Arduino Nano

  • Power Supply. You need a 12V-24V power supply that can output at least 5A. The connector should be a 5.5mm x 2.1mm barrel connector. The center pin should be the positive voltage.

Assembling the Kit

All of the surface mount parts ship already assembled. You only need to solder the through hole parts.  It typically takes only a few minutes to solder them. Here are some assembly tips.

  • I find it best to just tack one pin of each connector first. You can flip over the board and see if the connector is mounted straight. If not, you just heat the pin again and straighten the connector.
  • I like to assemble the parts shortest to tallest. You can insert the components, then flip the board. The weight of the board will keep the parts inserted.
  • Raspberry Pi Connector: The connector is mounted to the back side (not silkscreen side), so it is probably best to do it first, so you don’t forget the side.
  • Male Headers. Insert all the male headers on the top side. Place a small piece of cardboard on top of the connectors then flip over the PCB onto a table. Solder one pin per connector, inspect the straightness, then finish all soldering.
  • Female Headers: Repeat the last step with female headers.
  • Power connector. Solder this on the top side.

Install Grbl firmware on the Nano.

With the Nano not attached to the PCB install Grbl. You can get it here and there are instruction. Be sure to select Nano in the Arduino IDE Tools…Boards: menu

PCB Setup.

  • Determine the microstepping: Use the jumper blocks provided to set the microstepping level. You should look up the documentation on the driver chips to see how the settings work.
  • Install the Nano with the USB facing the edge of the board. See images.
  • Install the stepper drivers: Be sure to get the orientation right. Most will have the pins labeled. Match them up with the labels on the controller board.
  • Plug in your power supply.
  • Set the current: Most drivers will come with the current preset to a good value, but the pot on the driver can be used to fine tune that. You will need to use a meter and read the instructions where you got the driver.

I/O Connector

  • Limit and Probe Switches: The switches should all be setup as normally open and close to ground. A ground connection is provided for each switch to make wiring easier.
  • Control Switches (Start, Hold, Grbl Reset): These also should be normally open switches that close to ground. Grbl reset is a Grbl function to reset the planner, it is not a reset of the controller.
  • Spindle: This output is a TTL signal for a relay or speed controller. It cannot provide any power to run a motor or directly drive a relay.  That will break your Arduino Nano. Whether you use a relay or a variable speed spindle, I suggest Grbl be setup as a variable speed spindle (the default).
    • Variable Speed Spindle:
    • On/Off Spindle: Connect the output pin to the relay control circuit.  This can be used to control AC routers like a Dewalt 611.
  • Flood & Mist coolant: These should be connected to a relay control circuit. If you are using multiple relays, it is easiest to buy a multiple relay PCB like this one.



Stepper Connectors.

See the schematic to attach the servos, if you need (2) Y motors to turn in different directions just swap the (2) wires of one coil on one motor. You can also just rotate the connector of the motor you want to reverse by 180 degrees. If you want a different axis to use the 2 ganged motors you can change some setting in Grbl’s cpu_map.h file.  Here is the section of the file you change. The ganged drivers use pins 3 and 6.  Swap them with the axis you want.

// Define step pulse output pins. NOTE: All step bit pins must be on the same port.
#define X_STEP_BIT 2 // Uno Digital Pin 2
#define Y_STEP_BIT 3 // Uno Digital Pin 3
#define Z_STEP_BIT 4 // Uno Digital Pin 4
#define STEP_MASK ((1<<X_STEP_BIT)|(1<<Y_STEP_BIT)|(1<<Z_STEP_BIT)) // All step bits

// Define step direction output pins. NOTE: All direction pins must be on the same port.
#define X_DIRECTION_BIT 5 // Uno Digital Pin 5
#define Y_DIRECTION_BIT 6 // Uno Digital Pin 6
#define Z_DIRECTION_BIT 7 // Uno Digital Pin 7
#define DIRECTION_MASK ((1<<X_DIRECTION_BIT)|(1<<Y_DIRECTION_BIT)|(1<<Z_DIRECTION_BIT)) // All direction bits


Raspberry Pi.

This controller uses the TX and Rx on pins 14 and 15 of the Raspbery Pi header. These are typicall in use for a login shell. You will need to go in the raspi-confi program and stop the ligin shell and enable it for use by other programs.

Note: Arduinos use a trick with the USB to Serial adapter built into each one to reboot the CPU every time you connect. The Raspberry Pi cannot do that, because it has no access to the reboot pin . Grbl will not reboot each time you connect. This may confuse some senders. Also if you try to use the Arduino IDE to program the Nano via Raspberry Pi, it will not be able to trigger the bootloader. You will have to click the reset button on the Nano as the IDE is trying to upload the program. It is best to remove the Nano and program via USB.

Using a Servo.

Stock Grbl does not support servos, so the servo is wired to the Raspberry Pi header. The servo is using the 5V power from the Arduino or the Raspberry Pi, so you should only use micro servos to avoid drawing too much power and damaging something. You should use an external 5V power supply if you want to use a larger servo.

The servo is hooked up to PWM0 (Pin 12)

Using the Controller

You can use it via Raspberry Pi or standalone. If you use the Raspberry Pi, you should not connect the USB to the Arduino. That create a communications conflict and could damage something.

Documentation: (Current version 1.0):

The license is Creative Commons 4.0 Share Alike – Attribution.


Please ask via the comments section. I’ll answer there and update this post as required.







Using Grbl’s Spindle PWM to Control a Servo

While I am waiting on some parts to arrive for a pen ‘bot, I started investigating ideas to control it. It will be using a hobby servo for pen up/down. Servos work great for things like this because they are easy to integrate and don’t need to be homed. They always know where they are in rotation.

I am probably going to use Grbl  and it outputs step and direction signals for motion.  A servo requires a PWM signal.  Since the spindle already uses PWM to set speed, this seems like a good place to start hacking. A PWM signal has a frequency and a duty cycle.  The frequency is how often the signal repeats and the duty cycle is how long the output signal is logic high (the rest of the time it is low). Servos want the signal to repeat every 20ms (50Hz). They want the duty cycle to be 1m long at one end of the rotation and 2ms at the other end.

  • 0 degree duty cycle = 1ms
  • 180 degree duty cycle 2ms
  • Frequency 50Hz (20ms)

PWM is a peripheral found on most micro controllers including Arduinos.  They use the timers built into CPU. You setup a few registers and the PWM runs independent of of the code. The spindle is using timer2.  All other timers are being used by other Grbl functions (on Unos), so they are not available. Timer2 is an 8 bit timer so it can only count up to 255.  To set the duty cycle you set a “compare” number that is 0-255. At the beginning of the cycle, the output will go high and the timer will begin counting.  When it reaches the compare value the output goes low. When it reaches 255, the cycle starts over again.


  • Resolution: Since the servo’s duty cycle range ( 1ms to 2ms ) is only a fraction of the frequency (1ms/20ms) , we only have 1/20 of the 256 counts at best. That is going to limit our resolution, but we only care about a rough pen up and pen down in this application.
  • Frequency: You don’t get to pick any frequency on Arduinos. You are limited to certain fractions of the CPU clock.  The allowable fractions are 1/1, 1/8, 1/64, 1/256 & 1/1024. We need to pick one that is close to getting us to 50Hz.

Setting the frequency.

The formula for the setting the frequency is..

Freq = F_CPU / (Prescaler * TimerResolution)    Eq #1

  • Freq: Our desired frequency of 50Hz
  • F_CPU: This is the frequency of the CPU. For most Arduino that is 16Mz
  • Prescaler: This is that fraction mentioned about.
  • TimerResolution: In our case this will be 256

This can be rewritten as this to find Prescaler…

Prescaler = F_CPU / (TimerResolution * Freq)  Eq #2

Prescaler = 16,000,000 / (256 * 50)

This yields 1250 as the desired prescaler. This is not an option so we pick the closest one of 1024.  If we plug that into Eq #1, we get 61Hz. That is close enough.

Determine the duty cycles.

We need to determine the compare values for each end of the servo rotation.  A unit of compare value is often called a “tick”. Each “tick” of the timer is…

Tick = 1 / (F_CPU / Prescaler) Eq3

Tick = 1 / (16,000,000 / 1024)

This yields a tick length of 0.000064 seconds. We then determine how many ticks are needed for each end of travel.

  • 0 degree = 0.001 / 0.000064. This yields 15.6 Ticks which needs to be rounded to 16
  • 180 degrees = 0.002 / 0.000064. This yields 31.25 Ticks which needs to be rounded to 31.

Setting The Resisters.

You need to deeply dive into the datasheets for these, but I’ll briefly explain them here.

TCCR2A = (1<<COM2A1) | ((1<<WGM20) | (1<<WGM21));
TCCR2B = (1<<CS22) | (1 <<CS21) | (1<<CS20);
OCR2A = 31;

  • First line: TCCR2A (Timer/Counter Control Register A for Timer 2).   WGM20 & WGM21 (Waveform Generation Modes) are setting the mode to Fast PWM.  The COM2A1 bit tells the CPU to clear the compare value when reached.
  • Second line: TCCR2B (Timer/Counter Control Register B for Timer 2) This sets the Clock Select bits to the value needed for a 1024 prescaler .
  • Third Line: Sets OCR2A (Output Compare Register A for Timer 2) to 31, which is the 180 degree value determined above.

Note: Grbl uses some aliases for the register names to make the code a little easier to read and more universal between Uno/Mega, so keep that in mind when reading the actual code.


I loaded the firmware and hooked the output to my Saleae Logic 4 logic analyzer.

Here is the output at at the 0 degree rotation 1.087ms @ 61.07Hz

Here is the output at 180 degree rotation. 2.047 @ 61.07Hz

The Firmware.

I put everything into the a spindle_control.c file. Just replace it with the one Grbl comes with. Note: This is designed for Grbl 1.1f


  spindle_control.c - spindle control methods
  Part of Grbl

  PEN_SERVO update by Bart Dring 8/2017
  Copyright (c) 2012-2017 Sungeun K. Jeon for Gnea Research LLC
  Copyright (c) 2009-2011 Simen Svale Skogsrud

  Grbl is free software: you can redistribute it and/or modify
  it under the terms of the GNU General Public License as published by
  the Free Software Foundation, either version 3 of the License, or
  (at your option) any later version.

  Grbl is distributed in the hope that it will be useful,
  but WITHOUT ANY WARRANTY; without even the implied warranty of
  GNU General Public License for more details.

  You should have received a copy of the GNU General Public License
  along with Grbl.  If not, see <http://www.gnu.org/licenses/>.

#include "grbl.h"

Pen Servo: 

For a pen bot I want to use the spindle PWM to control a servo
When the spindle is on, the servo moves the pen down
When it is off the pen moves up

The spindle output is using a PWM, but we need to adjust that 

We only need a rough 

Use 1024 prescaler to get. ... 16,000,000 Mhz  / 1024 = 15625 Hz
It is an 8 bit timer so 15625 / 256 = 61 Hz. This is pretty close the the 50Hz recommended for servos
Each tick = 0.000064sec 
One end of servo is 0.001 sec (0.001 / 0.000064 = 15.6 ticks)
The other end is 0.002 sec (0.002 / 0.000064 = 31 ticks)


#define PEN_SERVO
// these are full travel values. If you want to move less than full travel adjust these values
// If your servo is going the wrong way, swap them.
#define PEN_SERVO_DOWN     16      
#define PEN_SERVO_UP       31        

  static float pwm_gradient; // Precalulated value to speed up rpm to PWM conversions.

void spindle_init()

    SPINDLE_PWM_DDR |= (1<<SPINDLE_PWM_BIT); // Configure as PWM output pin.
	#ifndef PEN_SERVO 
		// Configure variable spindle PWM and enable pin, if requried. On the Uno, PWM and enable are
		// combined unless configured otherwise.
		SPINDLE_TCCRA_REGISTER = SPINDLE_TCCRA_INIT_MASK; // Configure PWM output compare timer
		#ifdef CPU_MAP_ATMEGA2560
		// not supported yet
        SPINDLE_TCCRA_REGISTER = (1<<COM2A1) | ((1<<WGM20) | (1<<WGM21));
		TCCR2B = (1<<CS22) | (1 <<CS21) | (1<<CS20);
      SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
      SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.

    pwm_gradient = SPINDLE_PWM_RANGE/(settings.rpm_max-settings.rpm_min);


    // Configure no variable spindle and only enable pin.
    SPINDLE_ENABLE_DDR |= (1<<SPINDLE_ENABLE_BIT); // Configure as output pin.
    SPINDLE_DIRECTION_DDR |= (1<<SPINDLE_DIRECTION_BIT); // Configure as output pin.



uint8_t spindle_get_state()
		  // No spindle direction output pin. 
			  if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
	 			if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { return(SPINDLE_STATE_CW); }
      if (SPINDLE_TCCRA_REGISTER & (1<<SPINDLE_COMB_BIT)) { // Check if PWM is enabled.
        else { return(SPINDLE_STATE_CW); }
		  if (bit_isfalse(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) { 
		  if (bit_istrue(SPINDLE_ENABLE_PORT,(1<<SPINDLE_ENABLE_BIT))) {
      else { return(SPINDLE_STATE_CW); }

// Disables the spindle and sets PWM output to zero when PWM variable spindle speed is enabled.
// Called by various main program and ISR routines. Keep routine small, fast, and efficient.
// Called by spindle_init(), spindle_set_speed(), spindle_set_state(), and mc_reset().
void spindle_stop()
  #ifndef PEN_SERVO	
		SPINDLE_TCCRA_REGISTER &= ~(1<<SPINDLE_COMB_BIT); // Disable PWM. Output voltage is zero.
			SPINDLE_ENABLE_PORT |= (1<<SPINDLE_ENABLE_BIT);  // Set pin to high
			SPINDLE_ENABLE_PORT &= ~(1<<SPINDLE_ENABLE_BIT); // Set pin to low
		  SPINDLE_ENABLE_PORT |= (1<<SPINDLE_ENABLE_BIT);  // Set pin to high
		  SPINDLE_ENABLE_PORT &= ~(1<<SPINDLE_ENABLE_BIT); // Set pin to low

  // Sets spindle speed PWM output and enable pin, if configured. Called by spindle_set_state()
  // and stepper ISR. Keep routine small and efficient.
  void spindle_set_speed(uint8_t pwm_value)
    #ifdef PEN_SERVO
		if (pwm_value == SPINDLE_PWM_OFF_VALUE) 
		else // not off
		SPINDLE_OCR_REGISTER = pwm_value; // Set PWM output level.
		  if (pwm_value == SPINDLE_PWM_OFF_VALUE) {
		  } else {
			SPINDLE_TCCRA_REGISTER |= (1<<SPINDLE_COMB_BIT); // Ensure PWM output is enabled.
		  if (pwm_value == SPINDLE_PWM_OFF_VALUE) {
			SPINDLE_TCCRA_REGISTER &= ~(1<<SPINDLE_COMB_BIT); // Disable PWM. Output voltage is zero.
		  } else {
			SPINDLE_TCCRA_REGISTER |= (1<<SPINDLE_COMB_BIT); // Ensure PWM output is enabled. } #endif #endif } #ifdef ENABLE_PIECEWISE_LINEAR_SPINDLE // Called by spindle_set_state() and step segment generator. Keep routine small and efficient. uint8_t spindle_compute_pwm_value(float rpm) // 328p PWM register is 8-bit. { uint8_t pwm_value; rpm *= (0.010*sys.spindle_speed_ovr); // Scale by spindle speed override value. // Calculate PWM register value based on rpm max/min settings and programmed rpm. if ((settings.rpm_min >= settings.rpm_max) || (rpm >= RPM_MAX)) {
        rpm = RPM_MAX;
        pwm_value = SPINDLE_PWM_MAX_VALUE;
      } else if (rpm <= RPM_MIN) { if (rpm == 0.0) { // S0 disables spindle pwm_value = SPINDLE_PWM_OFF_VALUE; } else { rpm = RPM_MIN; pwm_value = SPINDLE_PWM_MIN_VALUE; } } else { // Compute intermediate PWM value with linear spindle speed model via piecewise linear fit model. #if (N_PIECES > 3)
          if (rpm > RPM_POINT34) {
            pwm_value = floor(RPM_LINE_A4*rpm - RPM_LINE_B4);
          } else 
        #if (N_PIECES > 2)
          if (rpm > RPM_POINT23) {
            pwm_value = floor(RPM_LINE_A3*rpm - RPM_LINE_B3);
          } else 
        #if (N_PIECES > 1)
          if (rpm > RPM_POINT12) {
            pwm_value = floor(RPM_LINE_A2*rpm - RPM_LINE_B2);
          } else 
          pwm_value = floor(RPM_LINE_A1*rpm - RPM_LINE_B1);
      sys.spindle_speed = rpm;
    // Called by spindle_set_state() and step segment generator. Keep routine small and efficient.
    uint8_t spindle_compute_pwm_value(float rpm) // 328p PWM register is 8-bit.
      uint8_t pwm_value;
      rpm *= (0.010*sys.spindle_speed_ovr); // Scale by spindle speed override value.
      // Calculate PWM register value based on rpm max/min settings and programmed rpm.
      if ((settings.rpm_min >= settings.rpm_max) || (rpm >= settings.rpm_max)) {
        // No PWM range possible. Set simple on/off spindle control pin state.
        sys.spindle_speed = settings.rpm_max;
        pwm_value = SPINDLE_PWM_MAX_VALUE;
      } else if (rpm <= settings.rpm_min) {
        if (rpm == 0.0) { // S0 disables spindle
          sys.spindle_speed = 0.0;
          pwm_value = SPINDLE_PWM_OFF_VALUE;
        } else { // Set minimum PWM output
          sys.spindle_speed = settings.rpm_min;
          pwm_value = SPINDLE_PWM_MIN_VALUE;
      } else { 
        // Compute intermediate PWM value with linear spindle speed model.
        // NOTE: A nonlinear model could be installed here, if required, but keep it VERY light-weight.
        sys.spindle_speed = rpm;
        pwm_value = floor((rpm-settings.rpm_min)*pwm_gradient) + SPINDLE_PWM_MIN_VALUE;

// Immediately sets spindle running state with direction and spindle rpm via PWM, if enabled.
// Called by g-code parser spindle_sync(), parking retract and restore, g-code program end,
// sleep, and spindle stop override.
  void spindle_set_state(uint8_t state, float rpm)
  void _spindle_set_state(uint8_t state)
  if (sys.abort) { return; } // Block during abort.
  if (state == SPINDLE_DISABLE) { // Halt or set spindle direction and rpm.
      sys.spindle_speed = 0.0;
  } else {
      if (state == SPINDLE_ENABLE_CW) {
      } else {
      // NOTE: Assumes all calls to this function is when Grbl is not moving or must remain off.
      if (settings.flags & BITFLAG_LASER_MODE) { 
        if (state == SPINDLE_ENABLE_CCW) { rpm = 0.0; } // TODO: May need to be rpm_min*(100/MAX_SPINDLE_SPEED_OVERRIDE);
    #if (defined(USE_SPINDLE_DIR_AS_ENABLE_PIN) && 
      // NOTE: Without variable spindle, the enable bit should just turn on or off, regardless
      // if the spindle speed value is zero, as its ignored anyhow.
  sys.report_ovr_counter = 0; // Set to report change immediately

// G-code parser entry-point for setting spindle state. Forces a planner buffer sync and bails 
// if an abort or check-mode is active.
  void spindle_sync(uint8_t state, float rpm)
    if (sys.state == STATE_CHECK_MODE) { return; }
    protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed.
  void _spindle_sync(uint8_t state)
    if (sys.state == STATE_CHECK_MODE) { return; }
    protocol_buffer_synchronize(); // Empty planner buffer to ensure spindle is set when programmed.

A Grbl Raspberry Pi Hat

I have been making small scale CNC machines lately. I wanted a very small Grbl based CNC controller. I used the Eleksmaker Mana SE for the Coasty Laser. The big drawback was no access to the pins used for limit and control switches. I did like the modular approach.  The Stepstick style drivers are easy to find at less the $2 each and Arduino Nano clones can be found for less than $4.  There is no way I could even get the components for that price at the scale I am working at.

Edit: Now a few are available on Tindie.

(my hand tacked limit switch wires)

Raspberry Pi Real time Issues.

Raspberry Pi is great, but it cannot handle the real time requirements of CNC. Beagle Bone uses coprocessors (PRU) to get around this and there are some dual core devices like the UDOO NEO that have a second core that can be used for CNC. That got me thinking, why not just add the second processor myself. If I added an Arduino 328 processor connected by the hardware UART on the Pi, I would have an easy fix without any firmware development.

It’s a Raspberry Pi HAT…or not.

After taking Chris Gammell’s KiCAD lesson I wanted to make a Raspberry Pi HAT, but I typically don’t use a Raspberry Pi. I realized that the Nano could talk to either the USB or the Pi. The female header going to the Pi is out of the way and well protected from shorts if it is not used. You can therefore use it on the Pi or stand alone.

5V Power.

The 5V logic power can come from the USB connection or the Pi. There is a diode OR isolating the 2 sources. There is no on board step down supply, so this cannot be used if it is not connected to USB or a Pi.


The processor uses a standard Arduino Nano. This is a mini version of the Uno, but it actually exposes more of the I/O pins (A6 and A7).


3 Axis Drivers (+1 slaved)

The firmware is standard Grbl, so it is limited to 3 axes. I had room for 4 drivers, so there are 2 for Y. If you needed 2 on a different axis, you could simply edit the config file for Grbl. These use standard Stepstick / Pololu footprints. There are jumpers to select the microstepping value.


I added a big header for all of the I/O. All of the typically used signals have their own grounds to make wiring easier. A6, A7 and +5V are also on the header.


I added this at the last minute, just for experimenting. It is hooked to the Raspberry Pi PWM0 pin. If you wanted Grbl to use a servo for pen up type applications, you should hook the servo up to one of the Nano GPIO pins.

Using the Raspberry Pi serial port.

The standard GPIO header has UART Tx and Rx on pins 8 and 10.

This serial port is /dev/ttys0.  It is typically used for a serial console. You will need to disable this to use the serial port.  To disable type…

sudo raspi-config

To get the configuration screen. Select Advanced Options.

Select Serial.

Disable the serial login shell.

There are several ways to use the serial port with a basic terminal session. The most basic is ….

screen devttys0 115200

If you want a more interactive GUI, use …

cutecom.  You will probably need to install it

sudo apt-get install cutecom



Next Steps

  • I want to experiment with running full featured sender programs like BCNC on the Pi.
  • I will release the source and might sell some on Tindie if there is some demand. Unfortunately I did the layout in Diptrace, but I can release the Gerbers too.

Documentation (more coming soon after complete testing)