Use Pythagoras' Theorem to Draw Pictures

By John Proudlock. Posted

A few years ago, I ended up with a spare Raspberry Pi, and I set about looking for a project to put it to good use. I wanted something that needed a bit of simple coding – I’d not coded for years, and I wanted to make something that would have some vaguely artistic output. And that’s why plotters caught my eye. I’ve never been very good at drawing. I always wondered if I could build a machine to help me… It turns out I could.

The basic principles are fairly straightforward, and this article explains them.

You’ll probably have seen commercial plotters. Typically, the paper is set horizontally, and an armature moves a pen over the surface to draw. There’s a much simpler version, known as a vertical plotter (depending on the creator, they might also be called v-plotter, polar plotter, or polargraph). Search for images online, and you’ll quickly see how these devices work – but I’ve marked up the photo of the one I built below, and its main parts:

A. Paper attached vertically to a wall (on the plotter easel)

B. At the top-left and right corners, there are two motors; the drive shafts point out into the room

C. Pen holder, suspended on a toothed belt running between the two motors

D. When the motors move, the pen is dragged across the surface of the paper, creating an image

E. Toothed belt moving over the motor sprockets

F. Weights (steel chain) to counter the weight of the pen holder

G. Control electronics with small output display

The Plotter Today

The control electronics:
A. The power supply unit (from an old desktop PC)

B. PSU breakout board

C. Raspberry Pi B+ and GPIO breakout

D. 7-inch HDMI screen (the back of)

E. Breadboard

  • Stepper motor drivers to left and right motors
  • Drive for the pen lift servo

F. Cooling fan for motor driver circuits (normally mounted over the breadboard)

The Control Electronics

V-Plotter Mathematics

I start new projects by working on what I think will be the hardest part of the project for me to complete. That way, if the project is beyond me, I find that out early on and abandon it! For the plotter project, I wanted to make sure I could understand the underlying mathematics. I sketched out a simple model of a plotter.

I wanted to work in Cartesian coordinates, so if I want the pen at point p(x,y) how long would the belts from the left motor (Ll) and the right motor (Lr) need to be? To know that, I also need to know the height of the paper (h) and the width between the two motor spindles (w).

Understanding the Maths

The v-plotter makes two right-angled triangles, and the values can all be calculated using Pythagoras’ theorem:

Ll = √(x2 + (h-y)2)
Lr = √((w-x)2 + (h-y)2)

So, if the plotter is 500 mm square, h=500, w=500. And, if I want the pen to be at p(150,200), then x=150 and y=200 so the belt lengths can be calculated as:

Ll = √(1502 + 3002) = 335.4
Lr = √(3502 + 3002) = 461.0

I then started to think about moving the pen across the paper to draw a line. I bought a pair of NEMA stepper motors which are driven by electrical pulses (that would come from the Pi’s GPIO). For each pulse, the motor would turn 1.8 degrees, so 360/1.8 = 200 steps per full rotation of the motor shaft.

Using a GT5 sprocket to precisely control the plotter

I then dipped into the world of 3D printers to get a GT2 toothed pulley for the motor shaft, and decided I’d use a GT2 toothed belt to run over each pulley and suspend the pen. This had the advantage that the pulley wouldn’t slip or stretch (unlike string).

The sprockets I found had a circumference of 40 mm. This means one rotation of the motor would take 200 pulses, and would move the pen 40 mm closer/further from the motor. You can see the left-hand motor setup in the image above.

In the example before, if the pen is at point A(150,200) we know Ll = 335.4 mm and Lr = 461.0 mm.

If I want to move the pen to Point B (350,450) then we need to make Ll = 353.6 mm and Lr = 158.1 mm.

Just considering the right-hand motor and Lr, the change in Lr is 461 – 158.1 = 302.9 mm. This requires 302.9/40 = 7.57 rotations of the motor spindle.

As a single rotation requires 200 pulses, we can calculate that the right-hand motor must receive 200 × 7.57 = 1514 pulses.

You can use the same working to calculate the pulses needed to set the new length of the left-hand belt, Ll (the answer is 91 pulses).

Hardware – Setting Up The Motors

Confident that the underlying mathematics was all manageable, I moved onto the hardware and getting the two motors powered up. The Pi GPIO would provide the signal (the pulses mentioned earlier) as a square wave, but the Pi can’t provide the current needed to drive the motors, so you need some additional circuitry to boost the amps.

Firstly, I connected the GPIO from the Pi to a breadboard so that the signals from individual pins were accessible. It was also easier to get pre-built stepper motor driver circuits to save time, and I found the (excellent) ‘EasyDriver – Stepper Motor Driver’ circuits. I soldered on the headers so the two driver circuits would plug into the breadboard.

I connected the four power lines to each stepper motor and powered up the driver circuits. The motor spindle went from being loose to fixed firm (stepper motors draw current and lock without an input signal).

I always intended to transfer the breadboard circuit onto stripboard, but never got around to it. By using short wires, close to the board, the breadboard solution has been robust enough to work reliably.

There were two inputs required to make the motor move: the ‘drive’ signal, which would be a square wave where each pulse would move the motor spindle 1.8 degrees, and a ‘direction’ signal as the motors would need to rotate back and forth depending on the direction of pen line required. Armed with this knowledge, it was time to write the first code for the project.

Software – Drawing A Line

I used Python and worked in the IDLE environment to simply set a GPIO pin high, then low, 50 times a second. I did this for four seconds, and I got a motor spindle to turn one rotation clockwise. I then set the ‘direction’ pin to high, and repeated the four-second cycle. The spindle turned one rotation anti-clockwise.

From there, I duplicated the code for the other motor and clamped each motor to a shelf: one on the left, one on the right. Under the shelf, I propped up a whiteboard. I took the toothed GT2 belt and draped it across the two motors. I gaffer-taped an old takeaway carton in the middle of the belt and glued a dry marker to it. With the left motor turning anti-clockwise, and the right motor turning clockwise, the pen was dragged up the board and made a neat vertical line.

I wasn’t going to meet any artistic needs with a single vertical line, though, so I wrote a function that would be passed an (x,y) location and would move the pen from its current location to the one I requested.

The main steps to this are:
• Knowing your current pen position

• Knowing the position you want to move to

• Calculating the change in the left belt, and the right belt

• Calculating how many steps are required for each motor to make the change in belt lengths

• Moving the motors

I had the maths for this from earlier in the project, so coded it up. The first stumble was that if you move one motor, then the other, you don’t get a straight line to the destination, you get a sort of L shape. So you have to use two processor threads, one for each motor. Both motors have to start moving at the same instant.

I found that I needed a more sophisticated development environment than IDLE and moved the project into PyCharm. The PyCharm debugging and refactoring tools were essential as the code got more sophisticated.

Unfortunately, that still left me with a kinked line because (unless it’s a vertical line in the centre of the paper) the L belt change and the R belt change are different lengths, so one motor finishes first and you end up, again, with a curved L shape instead of a straight line.

To fix this, the motors have to run for the same period of time, starting together and

finishing together. To do this, you need to have set your fastest motor speed. I found 50 pulses per second worked, and used that as the ‘maximum motor speed’:

• Identify which belt length change is the biggest. In the example from earlier, this is the change to Lr, which requires 1514.32 pulses. At 50 pulses per second, this will take 30.29 seconds

• The left motor must change the Ll length by just 91 pulses. These must be delivered through the 32.29 seconds that the right-hand motor is running, which requires a pulse rate of 91/32.29 = 3 pulses per second

I coded this so that both motors ran for equal periods and… it worked, mostly. Short lines of about 5 mm appeared straight. Long horizontal lines would curve slightly, like they were sagging. You can see this in Figure 1 from early in the plotter’s development. The plotter is drawing squares of increasing size. As the horizontal lines get longer, you can see them dip in the middle. There was distortion on the vertical lines too, but it was not as noticeable.

The cause is that in my implementation, the pulse rate sent to the motors is constant, and each motor rotates at a fixed rpm as the pen moves. Instead, the motor rpm should vary constantly during pen motion. I haven’t attempted to understand the mathematics required to fix this (I’m not sure I could), so instead, I found a workaround. Any long line is broken into segments, each no longer than 5 mm. In this way, a long line is drawn in several short segments. Although each segment bows slightly, it’s not visible and the line appears straight.

Portraits, looking basic

In this prototype version of the plotter, you can see that I’m plotting on a whiteboard and that the marker pen is held in an old takeaway container. The container holds my trusty Buddha paperweight to stabilise the pen.

I really wanted to draw something a little more inspiring than squares and started to experiment with drawing bitmap images, all with a single line. I started by considering a photograph I had and simplifying it into a small bitmap of 23×23 pixels.

I then mapped these pixel values to a ‘darkness level’ by equating black to a darkness level of 100 and white to level 0. In the plotter control code, I stored these values in a two-dimensional array. The plotter was then configured to represent each pixel in a 20 mm square and started with the pen in the top-left corner of the image. The latter is a white pixel (level 0), so the pen moves to a random point in the next adjacent pixel. If the next pixel is black (represented by 100), the pen must keep moving to random points in the pixel’s square until 100  mm of line has been drawn. After that, it moves to the next adjacent square.

Portraits, starting with the basics

This simple algorithm would ‘colour in’ a 20 mm square with an amount of line represented by a pixel’s darkness level. In this way, graduating tones would be represented too. A mid-grey (value 50) would cause 50 mm of line to be drawn in a pixel’s square.

Once coded up, I set the plotter running and waited to see how close the plot was to the image I had passed in.

With some squinting, I could just about make out the original image but could see that to make an engaging image, I would need a much higher resolution. This would need a bigger drawing space and a smaller pen tip. In any case, the shambolic ‘tape a couple of motors onto a shelf’ approach was not proving particularly reliable. This triggered the building of a simple easel that I could hang on the wall. In turn, I also upgraded the drawing algorithm to work in 5 mm squares per pixel, and this allowed the re-creation of 100-pixel images, and much better image creation.

 Portraits, a 100x100 pixel bitmap, drawn with a single, unbroken line

What Next…?

This is a ‘weekend project’ that’s now been running for about four years, and some extensions I’ve found fun to add to the project are:

  • Plotting bitmap images with a single line

  • ‘Generative Art’, which basically means plotting the results of equations. It may sound dull, but the results can be stunning:

    • Plotting spirographs (the equations are scary-looking, but not that hard to replicate in code – even if you don’t understand them)
    • Plotting fractals
    • Plotting modulo arithmetic
  • Adding a mechanism to lift the pen off the paper

  • Plotting G-code, an industry standard file format for CNC machines

  • Drawing bitmap files with multiple colours

  • Writing an emulator so you can predict how the plot will look on screen before you waste another set of pens and a sheet of paper

Each of these hacky endeavours would be an article in itself, but you can see the results from this plotter project at instagram.com/inkylinesplots and inkylines.blogspot.com.

More features from HackSpace magazine magazine

Subscribe