Wednesday, January 03, 2018

Homegrown XY plotter with Arduino

[ This is work in progress and only for myself. If you are looking for ready-made kit, then have e.g. a look at the MaXYposi from German Make Magazine ]

Back in school we had a HP plotter well hidden in some closet in the science department. I was able to play with it for a while and always had the desire to have one on my own (but why, where dot-matrix printers are so much versatile and useful).

Bildschirmfoto 2018 01 03 um 12 11 22
Photo from Plotter in action. Video here.

Fast forward many many years. Stepper motors are easily available, I am back into doing stuff with electronics and micro controllers and recently saw someone creating some displays with engraved acrylic. This triggered me to finally get started with the plotter (and later engraver etc).

To get going I got some parts and as I am an old-school 5V guy, I totally like the original Arduino UNO. In the list, I put in links for reference. I am not affiliated with those companies

  • FabScan shield - physically hosts the Stepper motor drivers
  • SilentStepSticks - motor drivers, as the Arduino itself can't handle the voltage and current that a stepper motor needs. I am using the ones with a Trinamic TMC2130 chip, but in standalone mode for now. Those are replacements for the Pololu 4988, but allow for much quieter operation.
  • StepStick protectors - diodes that prevent the turning motor to fry your motor drivers (you want them, believe me)
  • Stepper motors - I took NEMA 17 ones with 12V (Watterott, Sparkfun)
  • Linear guard rails
  • Wooden base plate
  • Wood, screws, ..
  • GT2 belt, GT2 timing pulley

As you can see in the next picture I started out much too big - I can't really have the plotter sit on my desk comfortably, but anyway :) I did it for learning purposes (and as I have to re-do some things, I'll also use smaller beams).

Hardware side

IMG 20180101 185406
View of the plotter base plate with X-axis and Y-axis rails

The belt is mounted on both sides of the rail and then slung around the motor with some helper wheels:

Detail of the belt routing on the motor

On the Arduino side there is a stack of things. On the bottom, the Arduino, then the FabScan shield, then on motor slots 1+2 a StepStick protector and then on top of them the SilentStepSticks. Note that the SCK and SDI pins are not connected

IMG 20180103 110111
Setup on Arduino (see here for a larger image)

Btw be careful with the wires to the motor to correctly attach them. When in doubt have a look at the data sheet or a ohm-meter to figure out which wires belong together.

Software side

I know that there is software like Grbl, that can interpret so called G-codes for tool movement and other things and I could have just flashed that to the Arduino, but I am too curious for that and wanted to better understand things myself.


To drive a stepper motor with the StepStick driver (or compatibles) one basically needs to send a high and then a low signal to the respective pin. Or in Arduino-terms

digitalWrite(stepPin, HIGH);
digitalWrite(stepPin, LOW);

Where stepPin is the pin number for the stepper - 3 for motor 1 and 6 for motor 2.

Before the stepper does any work, it needs to be enabled.

digitalWrite(enPin, LOW);

Actually the StepStick knows three states for the pin here

  • LOW: motor is enabled
  • HIGH: motor is disabled
  • pin not connected: motor is enabled but goes into some energy saving after a while

When a motor is enabled, its coils are powered and it keeps its position. It is almost impossible to manually turn its axis. This is good for precision purposes, but also means that both motors and driver chips are "flooded" with power and will thus warm up.

And not last but not least, we need a way to determine the direction

digitalWrite(dirPin, direction);

The following table lists the functions and the pins


Before we can use the pins, we need to set them to OUTPUT mode, best in the setup() section of the code

pinMode(enPin1, OUTPUT);
pinMode(stepPin1, OUTPUT);
pinMode(dirPin1, OUTPUT);
digitalWrite(enPin1, LOW);

With that knowledge we can easily get the stepper to move around:

    totalRounds = ...
    for (int rounds =0 ; rounds < 2*totalRounds; rounds++) {
       if (dir==0){ // set direction
         digitalWrite(dirPin2, LOW);
       } else {
         digitalWrite(dirPin2, HIGH);
       delay(1); // give motors some breathing time
       dir = 1-dir; // reverse direction
       for (int i=0; i < 6400; i++) {
         int t = abs(3200-i) / 200;
         digitalWrite(stepPin2, HIGH);
         delayMicroseconds(70 + t);
         digitalWrite(stepPin2, LOW);
         delayMicroseconds(70 + t);

This will make the slider move left and right. When you execute that code, you can also see that this only deals with one stepper, but for a XY-plotter we have two axis to cater for.

Command interpreter

I started to implement a simple command interpreter that allows to use path specifications like

"X30|Y30|X-30 Y-30|X-20|Y-20|X20|Y20|X-40|Y-25|X40 Y25
to describe relative movements in millimetres (internally 1mm equals 80 steps).

The plotter software implements a continuous mode which allows to feed large paths (in chunks) from a connected PC to the plotter. This how the Hilbert-Curve in this tweet has been plotted.

Better pen holder

In the first image above the pen was only tied to the y-Axis with some metal string. This was not precise and did also not allow to have the software raise and lower the hand (this explains the big black dots).

I have meanwhile created a better, more precise pen holder that is using a servo to raise and lower the pen. The original form of this new holder can be seen in the Hilbert-Curve video.

Servo to raise/lower the pen
Close view of the servo arm in the upper position raising the pen.

The Pen gets a little clamp attached (the one shown is a size 8 one to attach cables to walls). The servo arm can then raise the pen. When the arm goes down, gravity will also lower the pen.

Driving the servo

Driving the servo is relatively straightforward. One has to only provide the position and the servo does all the work.

#include <Servo.h>

// Servo pin
#define servoData PIN_A1

// Positions
#define PEN_UP 10
#define PEN_DOWN 50

Servo penServo;

void setup() {
  // Attach to servo and raise pen

I am using the servo headers on the Motor 4 place of the FabScan shield, so the pin to use is Analog pin number one.

Lowering the pen is then as easy as



One of the next steps is to add some end-detectors (but I may skip them and use the StallGuard mode of the TMC2130). Those detectors can then also be used to implement a home command

And then perhaps in the future I add a real z-Axis than can hold an engraver to do wood milling or PCB drilling or engraving of acrylic or .... :-) (A laser comes to mind as well).

More ...

That's it for now. The software is available at and comes without any warranty.

My original announcement tweet

Friday, September 29, 2017

Find the hidden exception with the IntelliJ debugger

I was hacking some code and running tests and got:

  testA(org.acme.ATest)  Time elapsed: 0.114 sec  <<< ERROR!
   java.lang.RuntimeException: Could not inject members
   Caused by: java.lang.NullPointerException

No stack trace, no line number, nothing :-(

Attaching a debugger and making it stop on NPE also did not help, as this was slowing execution down to no avail.

Luckily IntelliJ IDEA has a nice feature to just log the exception when it happens. Just go to the breakpoint view in the Debugger and tick the respective checkbox

Bildschirmfoto 2017 09 29 um 16 16 46

You should also unmark the suspend checkbox as you don't want your porgram being interrupted all the time in places you don't want to know about (I had some hundreds of lines of NPEs within the JRE itself).

When you then attach the debugger to your process, you will see all NPEs along with the place they were thrown. And if the place is within your code, you can navigate to it via the log entry with one click.

I am sure other IDEs have a similar functionality.

Wednesday, June 14, 2017

Was tun ohne Wald?

Mein Beitrag zum Comic-Collab von Schlogger zum Thema Wald.

Comic collab wald


Thema für den 15. Juli: „Schmerzen“

Mit dabei im Juni 2017: (wird noch aktualisiert)

– Schlogger
Rainer Unsinn
Strichweise Diesig
Dramatized Depiction

Monday, December 05, 2016

Hawkular at GrafanaCon

Grafanacon logo finalI had the pleasure to be invited to present the Hawkular eco-system at GrafanaCon 2016.

The venue for this 2-day conference was certainly not your everyday conference venue in a hotel ballroom or cinema, but a lot more heavy-metal:

And thus the sessions of the first day all happened in the on-board theatre which used to be one of the elevators that moved the aircrafts from the hangar to the flight deck.

IMG 20161130 092133
Former aircraft elevator

The sessions were kicked off by Torkel Odegaard, the creator of Grafana by giving some numbers about the growth and versions of Grafana and the community of users and contributors.

In the next session Kevin from Fermilab talked about lasers and how they are connected to Grafana (hint: monitoring of the huge infrastructure that monitors the collider experiments).

And then next was something that probably most have been waiting for: the official launch of Grafana 4 by Torkel. This included a demonstration of some new features like Alerting, where you can define alerts directly on a graph including a visual value-picker and a simulation mode. The announcements continued later by announcing the renaming of Raintank to GrafanaLabs and the completion of the Stack with Intel Snap, which was announcing its version 1.0 followed by Graphite doing the same

I am not going through all the sessions here, but still want to mention the presentation of Kyle Brandt, creator of Bosun alert engine. His talk was less of a product presentation, but rather a philosophical one on getting the communication right. If one engineer sets up an alert trigger and another one has to work on the fired alert, it is important that the later gets enough context to be able to quickly react to the alert.

The afterparty in the evening happened in a nearby bowling place. Those balls are a lot larger and heavier than those we use in Germany for Kegeln.

Intrepid by night

The second day had a format with 2 parallel sessions, which was a lot more "how-to" like, which included a good presentation by Brian Brazil of Promtheus fame and a nice (hi)story of monitoring at Sony PlayStation. My talk took place on the afternoon at 3pm. It went well and I got some good questions and feedback.

As this was the first day with better weather I also toured the flight deck and the bridge of the Intrepid

IMG 20161201 121049
Bridge of the Intrepid

IMG 20161201 121905
Lockheed A1

IMG 20161201 123151
Space Shuttle Enterprise

IMG 20161201 125541
View from the bridge

All talks were recorded and will be pushed online once the video team has edited in the slides. My Slides are available in the meantime from I will update this post once the recordings are online.

Tuesday, October 18, 2016

A DSL for Alert Trigger Definitions in Hawkular

Hawkular had for a while a UI with the possibility to set up Alert Triggers. As the name suggests are those triggers used to define conditions when an Alert is to be fired.

Since a while there is now the ManageIQ UI that allows to set up such triggers. And also Hawkular APM is now able to forward data into Alerting.

The other day I was doing some testing and a colleague asked me if I had already defined some triggers. I thought that I neither want to log into ManageIQ right now nor pass JSON structures via curl commands.

As I did some DSL work for metrics recently, I thought, why not set up a DSL for trigger definitions. This is work in progress right now and here are two examples

Set up a threshold trigger to fire when the value of _myvalue_ is > 3:

define trigger "MyTrigger"
 ( threshold "myvalue" > 3 )

Set up a trigger on availability when it is reported as DOWN. The trigger is not enabled.

define trigger "MyTrigger"
  ( availability "mymetric" is DOWN )

As with my metric DSL I am implementing this in Ruby with the help of Treetop. And likewise I am integrating this in HawkFX.

Inserting a definition

At the moment it is a very crude integration via entry points in the main menu. And the DSL itself is also far from ready. I consider this an experimentation space. If it turns our successful, it may be possible to take the grammar and directly integrate it into Hawkular-Alerts, so that one can directly POST a document with a DSL fragment, which then gets turned into the internal representation.

If you are looking for code, this is available in the alert_insert branch of HawkFX.

Tuesday, September 27, 2016

Computed metrics for HawkFX (updated)

Computed metrics are something I wanted to do for a very long time, already in RHQ, but never really got around it and sort of forgot about it again.

Lately I found a post that contained a DSL to do exactly this (actually you should read that post not because of the DSL, but because of the idea behind it).

After seeing this, I got the idea on what to do and to include this in HawkFX, my pet project, which is an explorer for Hawkular.

HawkFX screen shot
HawkFx with the input window for formulae, that shows a formula and also a parser error.
The orange chart shows Non-Heap used, the redish one the heap usage of a JVM.


Formulas are in a DSL that looks a bit like UPN, e.g. as in the following (I've shortened the metric ID for readability, more on them below):

(+ metric( "MI~...Heap Used" , "max")
   metric( "MI~...NonHeap Used", "max"))

to sum up two metrics (see also screenshot below). The 'metric' element gets two parameters, the metric id and also which of the aggregates that the server sends should be taken (in this case the max value) - this comes from the fact that we request the values to be put into 120 buckets by the server.

Or if you have the total amount of memory you could also subtract the used memory to get a graph of the remaining:

(- 1000000 metric( "MI~...NonHeap Used", "max"))

You could also get the total wait time for responses at a point in time when you multiply the average wait time with the number of visitors:

(* metric("MI~..ResponseTime","avg")

Computed total memory usage

Summing up the metrics for 'Heap Used' and 'NonHeap Used' as shown above would then give you a nice graph of the total memory consumption of a JVM:

Chart with computed metric
The green chart now shows to combined memory usage of Heap and Non-Heap, which is computed from the other two series. Orange and red are as above.

On metric IDs

Metric IDs are the IDs under which a metric is stored inside of Hawkular. The example here comes from an installation of Hawkular-services in Docker. If you just feed your metrics into Hawkular metrics, the IDs will looks like the ones you are using.

ID and path field
ID (upper) and path fields (lower) for a selected item in the tree

I have just pushed an update to HawkFX that provides the ID and path in their own fields at the bottom of the main window, so you can copy&paste them.


I will talk more about the parser in an upcoming article. For now it is a personal playground to also better understand what is doable here. If this turns out to be successful I can imagine that the DSL could directly be incorporated into Hawkular-metrics so that the rules are available to all metrics clients.

It would of course be cool to have an editor for the formulas that allows to interactively pick metric IDs etc, but I doubt that I will get to this any time soon.