This allows you to create interesting variable-stroke-thickness artistic effects with a flexible brush pen:
Notice how the line thickness varies as we raise and lower the pen during strokes:
PLEASE HELP by clicking "watch" on our EggBot Firmware Enhancement Request (more info below) to make this AxiDraw feature even more powerful for everyone.
Any other cool ideas or have you done a hack with this technology? Let us know at axidraw@lurkertech.com.
The servo in the plotter only lifts up the pen (it does not push the pen down) so the weight of the pen must be sufficient to do whatever drawing/scribing you want but not too heavy to overload the servo.
We used a flexible brush pen with a built-in (replaceable) ink cartridge, available cheaply at art supply stores, similar to this one:
While making the drawings seen in the video above, I was worried that (given the hacks in the software required, as explained below) the pen would not move fast enough. But it turns out I actually had to program in massive delays in order to give the pen time for its brush to get replenished with ink flowing down into the bristles!
But from the (unusually good) dox it is still not clear how to make the device move in XY and Z simultaneously. That is documented in the comments of our github feature request here:
EggBot Firmware Enhancement Request
As you can see, there is sort of a way to do it now, within limitations, but it is not enough to do really expressive curved moves in 3-D.
We're asking the very nice firmware hackers behind the EBB board (the board that drives AxiDraw and other products) for a much simpler, cleaner, nicer way to accurately control all 3 dimensions with perfect sync. They seem into it!
PLEASE HELP by clicking "watch" on our enhancement request page if this feature interests you.
That will help the very nice EmbeddedMan and oskay prioritize their feature requests and let them know how people are using their awesome control board.
Version note: the method on this page worked for us on our AxiDraw with firmware revision 2.5.1 (you can get the current firmware rev from the "V" EBB command and it's probably shown somewhere in high-level software like Inkscape that connects to AxiDraw too). We do not know if the same sequence of EBB commands works on other revs or not. We did notice that after 2.5.1, the EBB folks fixed a bug related to whether or not a certain command waits for another command to finish, so it is conceivable that the change might affect our 3-D hack, but we haven't tried any other firmware revs yet. We are very much looking forward to the official 3-D command proposed in our enhancement request, which will make everything clean and easy to support.
This is a primitive hack: there is no path planning, bandwidth restriction, smoothing, or anything fancy like that. Use at your own risk!
This code assumes that there is a computer somewhere connected to the AxiDraw and running our simple AxiDraw Server, but you can simply plug in your own code to send commands directly to AxiDraw assuming it is hooked up to your local machine. To send commands to AxiDraw, if you are a Python fan, check out fogleman's cool "Unofficial Python library" at https://github.com/fogleman/axi.
This code draws the starburst-shaped pattern above.
Code is also available for download here.
# 3daxi.pl - Plot in X, Y, and Z with AxiDraw Plotter # - Chris Pirazzi and Paul Haeberli # # For details, see https://lurkertech.com/3daxi # # Accesses AxiDraw using server described at https://lurkertech.com/axiserver # use utf8; use strict; use English qw( -no_match_vars ); use Carp qw(cluck confess); use Data::Dumper; use Math::Trig qw(pi); use IO::Socket::INET; # auto-flush on socket $| = 1; # create a connecting socket my $socket = new IO::Socket::INET ( PeerHost => 'mycomputer.local', # <-- hostname of server PeerPort => '12345', # <-- port of server Proto => 'tcp', ); die "cannot connect to the server $!\n" unless $socket; print "connected to the server\n"; sub cmd { my $s = shift; # data to send to a server my $size = $socket->send($s . "\n"); print "sent [$s]\n"; # receive a response of up to 4096 characters from server my $response = ""; $socket->recv($response, 4096); chomp $response; print "received response: [$response]\n"; print "\n"; #exit if ('OK' ne $response); } # servo levels ("min"/"max") # - SC,5,Z (up) or SC,4,Z (dn) # - Z in [1,65535] (for Axidraw [7500,28000]) # - controls a pulse width in ns for a servo controller # - units of 83ns of duty cycle (units of 1/12000th of a second) # - e.g. 16000 * 83ns = 1.33ms # - wider pulse makes the pen go higher in z # - pulses are sent out each 24ms # # servo rate SC,10,R # - if R=0 then SC,5 takes effect immediately # - new pulse width starts coming out immediately after cmd executes # - I guess this means hardware goes as fast as it can # - if R != 0 then when you issue SC,5 # - first the hardware outputs the old rate # - then every 24ms # - the system adds/subtracts R to to get towards the new rate # - until enough 24ms periods happened to get to new rate # - so R = height unit change per 24ms # - so if we have desired speed S = height unit change per ms # R = S*24 # my $pen_x; my $pen_y; my $pen_z; sub pen_z_to { my $dst_z = shift; my $ms = shift; my $dz = abs($dst_z - $pen_z); my $S = $dz / (0.0 + $ms); # choose servo rate $R that will make a $dz change happen in $ms ms # my $R = $S * 24.0; print "dz=$dz ms=$ms S=$S R=$R\n"; $R = int($R); cmd("SC,10,$R"); # servo rate cmd("SC,4,$dst_z"); # pen down pos, default 12000, more higher # XXX third arg should be $ms according to dox: CONFUSED cmd("SP,1,0"); # pen down $pen_z = $dst_z; } sub pen_up { cmd("SC,10,0"); # servo rate ("quick as posible") cmd("SP,0,200"); # pen up (200ms enough for "quick as possible") } #cmd("R"); # reset # set pen up pos nice and high cmd("SC,5,20000"); # pen up pos, default 16000, more higher # quickly put pen in known down pos cmd("SC,10,0"); # servo rate ("quick as possible") $pen_z = 20000; cmd("SC,4,$pen_z"); # pen down pos, default 12000, more higher cmd("SP,1,200"); # pen down (200ms enough for "quick as possible") # assume xy pos $pen_x = 0; $pen_y = 0; sub move_to { my $x = int(shift); my $y = int(shift); my $z = int(shift); my $ms = int(shift); print "===== move to x=$x y=$y z=$z ms=$ms\n"; print "cur pos pen_x=$pen_x pen_y=$pen_y pen_z=$pen_z\n"; my $dx = $x - $pen_x; my $dy = $y - $pen_y; print "dx=$dx dy=$dy\n"; # returns immediately, does not delay next command, move takes $ms pen_z_to($z, $ms); # returns immediately, does not delay next command, move takes $ms cmd("XM,$ms,$dx,$dy"); # move xy # ... somehow magically next command delayed by $ms?! HOW??? $pen_x = $x; $pen_y = $y; } # centerburst # starting at 0,0,20000 # my $orad = 6000; my $slices = 18; for(my $out_to_in = 0; $out_to_in < 1; $out_to_in++) { for(my $i=0; $i < $slices; $i++) { my $phase = ($out_to_in ? 0 : 0.5); my $ang = 2*pi * (($i + $phase) / $slices); pen_up(); if ($out_to_in) # thick out to thin in { move_to($orad + $orad * sin($ang), $orad + $orad * cos($ang), 20000, 10000); # let ink flow down move_to($orad + $orad * sin($ang), $orad + $orad * cos($ang), 9000, 200); move_to($orad, $orad, 16000, 1200); } else # thick in to thin out { move_to($orad, $orad, 20000, 5000); # let ink flow down move_to($orad, $orad, 9000, 200); move_to($orad + $orad * sin($ang), $orad + $orad * cos($ang), 16000, 1200); } } } pen_up(); move_to(0, 0, 20000, 2000); $socket->close();
https://twitter.com/graficaobscura
Thanks to EBB board firmware authors EmbeddedMan and oskay for their awesome support.
Submit This Site | Like what you see? Help spread the word on social media: | |||
| ||||
Support This Site | I work on this site in my off hours. Please help me to push aside my day job and work on it more by supporting the site in one of these ways: | |||
![]() | Use your credit card or PayPal to donate in support of the site. | |||
![]() | Use this link to Amazon—you pay the same, I get 4%. | |||
![]() | Learn Thai with my Talking Thai-English-Thai Dictionary app: iOS, Android, Windows. | |||
![]() | Experience Thailand richly with my Talking Thai-English-Thai Phrasebook app. | |||
![]() | Visit China easily with my Talking Chinese-English-Chinese Phrasebook app. | |||
![]() | I co-authored this bilingual cultural guide to Thai-Western romantic relationships. | |||
Copyright | All text and images copyright 1999-2023 Chris Pirazzi unless otherwise indicated. | |||