Z-Axis servo driver

by NilsR Jan 12, 2014
Download All Files

Please Login to Comment


your project inspired me to do the same kind of Z-axis for my own DVD drive "micro CNC" plotter. I improved some things in your code (like possible variable inconsistencies between interrupt and main loop). The derived project is available at github: https://github.com/jan-r/servo-stepper . It's available under the same CC license; I hope that is ok for you.



My software is just a quick hack and can certainly use some improvements, like use of interrupts, integrated PWM, etc.

Best regards,

No worries, your software runs just fine. I mainly adapted it to my machine:



Hi, I am wondering that how is the connection of HOME Z pin?


this is an output pin, signalling to the main controller that the virtual axis has returned home. It emulates the home switch that would normally be placed at the home position of the emulated axis.


I'm using an arduino cnc shield v3, the one in this link: http://blog.protoneer.co.nz/arduino-cnc-shield/
I'm still figuring out where to place the Z-home pin. I've managed to place the rest of the pins on the A4988 socket (https://www.pololu.com/picture/view/0J3360), but in what socket do I have to connect the Z-home pin?

You'll have to connect it to the Z endstop input. Which one depends on your board and the software/configuration behind it. For example, the site you linked lists the "+" as the "top" limit switch, and the "-" as the "bottom" limit switch. I can't remember exactly if I went down or up with this virtual axis, I might have to dig in my files. The project has been dismantled since.


This is a.cool hack, nice work. To control multiple servos would you use one Ardiuno or multiple TTiny's? Was the reason you chose a TTiny 25 cost?



it was meant to be a quick solution to drive a servo with existing hardware. I didn't have a third stepper driver or a third axis that would work in the design. The Attiny25 was chosen because it was the smallest controller I had lying around; a full-blown Arduino would have been overkill.

The program as-is can run only one servo.

Almost got it...
Inverted Z by changing #define REVERSE_Z_BEHAVIOUR to //#define REVERSE_Z_BEHAVIOUR
and now "homes" properly.(including z axis servo sweep) YUS!!!
but any z movement (G01 Z1 F260 even G01 Z-1 F260) triggers limit switch. and i have to reset....
any ideas why?
wrong G-Code? bad increments 1,-1,0.1??
i see you hinted at going negative z in a comment to apone4 below.
z=0 = home
z=-12 = pen down on paper

on Grbl 0.9g, what do you recommend for
$102=250.00 (z,step / mm)?
$112=100.00 (z max rate, mm/min)?
$122=10.00 (z accel, mm/sec^2)?
$132=200.000 (z max travel, mm)?
i know this is going to be mostly servo/machine specific but any hints would be nice.

i might bypass home and use physical switch? but not as cool...

Thanks NilsRoe for this awesome project!!

set $102=1.000; helped a lot!

using z-5 and z5 seams to now lift and lower pen.
But any z0? or commands after? will set limit alarm..
so close.....

I have found the main control board of the plotter, but unfortunately the µC has been removed and was likely used in something else. That means the settings can't be retrieved anymore. If I find enough time, I'll try setting it up again.

Thanks for the quick reply !
voltage appears to be ok.

i might have to change signal bits for direction.
maybe this is why i thought i needed to invert the code //#define REVERSE_Z_BEHAVIOUR

i am also lowering step rate.
i also was thinking i was hitting the limit when inverting the Z position.

i think i need to spend more time on calibrating servo/grbl/attiny

i am pretty sure that most of my problems are from my lack of knowledge in G Code.
i am using grbl controler 3.6.1 as an interface btw.
i can send z5 and the axis moves. i should probably be using something like G01 Z5 F200 instead.
again a feed rate of 200 may be way out. idk yet?

no need for you to rebuild an old project just to get settings. i understand how projects get recycled.
well now to go tinker...

as i understand z range should be from 0 to - (minus) whatever (as far as physical servo limitation)
z0 and above z0.1 , z1, z5 will trigger home pin

my servo appears to be somewhat centered at Z0 i can move up and down with + and - Z values..
shouldn't z0 be as high as possible (home) and then lower in the z plane hence - (negative values, z-5)?

errors (example 1)
ALARM: Hard/soft limit

errors (example 2)
G01 Z-1 F260
ALARM: Hard/soft limit

errors (example 2)
ALARM: Hard/soft limit

seams so random to me....

Please post all your config parameters, maybe I'll find something in there. Also what I remember is playing around with the pulse length parameter, but I'm not sure if it had any effect.

Also with the Z commands:

Imagine the axis hitting a hard limit on z-5, the motor keeps driving the axis but there is no feedback that a limit is hit. When going backwards, the same happens, but in reverse. This time there is feedback that a limit is hit before the axis gets to its destination, and thus the limit alarm is triggered. Try lowering the steps per mm and the stepping rate. Use Z0 to return the axis and then gradually increase the axis' position in 1mm steps until you have found the right positions for up/down. The program in the Attiny also has configurable limits that determine the travel of the servo.

The acceleration can be cranked up (to the limits of your stepper motors). Did you check if the servo causes any dips in the voltage, as well as the grbl config bits for signal directions? I've got to go to work now, so I can't check my machine's configuration until this evening. I have since disassembled the machine because it was just for learning/for the fun of it, but the control board should be still intact.

Lowering the max. step rate should help, the way it's programmed it will start missing steps as step rate goes too high.

Sorry but couldn't get this to work. So I used a small stepper motor instead of a servo motor. I had to buy another stepper driver though. But made it easier for me to adjust the gcode. Here is a demo...

Did you set the fuse bytes accordingly?

There are now two weeks that the woodpecker's head into the wall,
but I can not make it work, you have attached the .hex
does not move the servo, so I recompiled with Arduino IDE,
my TTiny25 runs at 8MHz, but now the servant only works
in one direction, and xy ranging in shots, as if grbl does not receive OK
Z, if I run XY, without gcode of Z, 2-axis work well,
I studied all the code, but I do not understand a lot, so I think
that the problem is signal direzzione and frequency,
most do not know where to turn, now I have finished the walls: - (((((.
help !!!!

Is the config bit in GRBL for detecting Z-home correctly set? The AtTiny is supposed to run at 8 MHz (see Makefile).

Connect the STEP pin (PB2) to the STEP output of the GRBL board
Connect the DIRECTION pin (PB1 at default) to the DIR output of the GRBL board
Connect the HOME pin (PB3 at default) to the z-zero switch input of the GRBL board. GRBL can be set to accept either a positive or negative edge as a "home switch triggered" signal.

When the simulated Z-axis is at zero (at minimum), the HOME pin goes low. Everything else makes it go high.

The Z-axis behaviour can be set in the code to either of these:
-Positive direction makes the servo turn right, negative direction makes the servo turn left.
-Negative direction makes the servo turn right, positive direction makes the servo turn left.
Experiment what suits your application. My DVD carriage plotter was set up this way:

Z-axis is home, when pen is in parking position, Z=0.00
Z-axis set to Z=-10.0 to make pen hover close to paper (during travel)
Z-axis set to Z=-12.5 to put pen onto the paper (to draw line)

If you have any questions send me a message.

Good luck!

Thank you for your help:-))),
Yes, I put in ATtiny bootloader 8MHZ and I also added to
source #define F_CPU 8000000, I am attaching a picture of the connections,
also the video of the behavior,
I have seen this in the source:
ISR (TIMER0_COMPA_vect), but is not supported TIMER0_COMPA_vect
for ATtiny 25, TIM0_COMPA_vect instead seems to you, this might give
a problem?
I have tried to compile with TIM0_COMPA_vect, but nothing has changed: - ((((,
do you have any idea?

the best regrds!


just setting the F_CPU to 8000000 isn't enough, and it is already set in the makefile. The fuse bytes have to be set as well with the programmer. It is a common oversight; by default the CPU is set to divide the internal 8 MHz clock by 8 to give a more precise 1 MHz clock.

The datasheet has TIMER0_COMPA in it.

What compiler are you using? I'm using avr-gcc in Programmer's Notepad as AVR Studio has some problems.

I need to know what pin does what; is there a "real" schematic available?

Which pin?

The best regards :-)

Comments deleted.

This is really awesome.. A schematic would greatly help.. Thanks a lot for the code.. :D

I tried uploading a schematic multiple times but Thingiverse won't let me. :-(

It is very a pity! You can will share through dropbox ;)?

Thank you very much! Only I not absolutely understand, where Z Home on connection of arduino?

This is code for an attiny25, there is no Arduino involved.

Z zome is an output that tells the attached controller wheb the simulated axis is in home position (connect instead of a real limit switch)

If I was to use this solution with a bigger 36V Servo motor, I probably need a driver in between my ATtiny and the motor, right?