Making a CNC Plasma Cutter Play Music (December 2014)

We do a lot of metal fabrication at work and earlier this year my boss bought a CNC plasma cutter. Basically it's a computer controlled lightsaber that reads a G-code file and cuts out shapes from sheets of metal. A table supports the sheet of metal and a gantry rolls up and down the table in the Y axis. The X axis moves along the length of the gantry and the Z axis moves perpendicular to the sheet of metal. The gantry and Z axis mechanism are controlled by stepper motors and early on I noticed different feed rates made the stepper motors play different notes. With that realization I thought it would be really cool to write a G-code file by hand that made the machine play music.

The first order of business was to figure out what feed rate makes the motor play what note. This was slightly complicated by the fact that the Z axis motor is smaller than the X and Y axis motors. So a feed rate that works for the Z axis won't play the same note on the X and Y axis. I have a guitar tuner app on my phone that I used to sound a note and I adjusted the feed rate until it matched. Below is a table showing what feed rate equals what note.

Z Axis IPMNote X&Y Axis IPMNote
41.2G# 193C#
39G 183.8C
36.5F# 174B
34.75F 165.7A#
32.8E 153A
31.2D# 146.8G#
29.2D 139.4G
27.6C# 130.2F#
26C 122.9F
24.75B 116.8E
23.2A# 110.9D#
22A 104.9D
20.7G# 96C#
19.6G 92.7C
18.4F# 86.83B

The next problem is working out the values for each note. For example, on the Z axis, a high G# has a feed rate of 41.2 inches per minute and a low G# is 20.7 inches per minute. That means if I want one second of sound from each note, the high G# will travel 41.2 ipm / 60 seconds = 0.686 inches. Since the low G# is moving roughly half as fast, it will need to move roughly half as far. 20.7 ipm / 60 seconds = 0.345 inches for one second of sound.

I arbitrarily decided to make the high E on the Z axis equal a quarter note when it has traveled .25 inches. Since the feed rate of the high E is 32.8 IPM and the distance it travels in one quarter note is .25 inches, .25 / 32.8 will give me a conversion factor of 0.00762195121951 that I can multiply to all the other feed rates. That will give me how far they need to move for one quarter note. Dividing the quarter note distance in half will give me eighth notes and so on. For the song I plan to make, I only need quarter and eighth notes. Here's the updated table showing the distances required for each note to be in time.

Z Axis IPMNoteQuarter NoteEighth Note X&Y Axis IPMNoteQuarter NoteEighth Note
41.2G#0.3140.157 193C#1.4710.736
39G0.2970.149 183.8C1.4010.700
36.5F#0.2780.139 174B1.3260.663
34.75F0.2650.132 165.7A#1.2630.631
32.8E0.2500.125 153A1.1660.583
31.2D#0.2380.119 146.8G#1.1190.559
29.2D0.2230.111 139.4G1.0620.531
27.6C#0.2100.105 130.2F#0.9920.496
26C0.1980.099 122.9F0.9370.468
24.75B0.1890.094 116.8E0.8900.445
23.2A#0.1770.088 110.9D#0.8450.423
22A0.1680.084 104.9D0.8000.400
20.7G#0.1580.079 96C#0.7320.366
19.6G0.1490.075 92.7C0.7070.353
18.4F#0.1400.070 86.83B0.6620.331

Once the musical side of things was done, it was time to write the G-code to drive the plasma cutter which would play the music. G-code is pretty easy to understand and there's a lot of websites around with big charts showing what each of the G words mean. Basically, each line gives the plasma cutter a set of coordinates to move to and at what speed to move at.

Here's the first bar of the song I want to make in musical and G-code notation. For those that can read music, I had to transpose the song because of the limited range on the plasma cutter. So the notes on the sheet music won't match the notes I play in the G-code, but the difference between the notes will always be the same.

First bar from Carol of the Bells       N0010 G01 Z0.250 F32.8 (E Quarter)
N0020 G01 Z0.369 F31.2 (D# Eighth)
N0030 G01 Z0.244 F32.8 (E Eighth)
N0040 G01 Z0.034 F27.6 (C# Quarter)

The first part of a line is the "N" word. This is just the line number. You don't have to use line numbers, but it's often a good idea so you can quickly find where problems are in a program. Often they're incremented by 5 or 10 so you can come back and add lines later if you need to.

The next part is called a "G" word. G01 means to move the tool in your CNC machine at a specified feed rate, as opposed to a rapid rate which just means move as fast as possible to get to a new area of the workpiece.

The next section tells the machine to move from where the tool currently is .25 inches in the positive direction along the Z axis. Since the first note in the song is a quarter note, I first find the note I want to play in the chart above, then select the distance required for a quarter note. In this case I'm playing an E, so I put in .25. The next two notes are eighth notes, so I add or subtract their eighth note distance to where the tool is currently. My Z axis only has 4" of travel, so I have to keep the tool within that range or I will damage the machine.

The next part is an "F" word which stands for feed rate. In this case I want the tool to move at 32.8 inches per minute for the first note.

And finally that last section is just a comment so I can keep track of what's going on. I have both what note is being played, and its duration.

Taken all together, the first line of the G-code means: This is line 10, we're going to be moving at a specified feed rate of 32.8 IPM and I want you to move the tool up a quarter inch along the Z axis.

As long as we're playing one note at the time, it's pretty simple to write the G-code. The problem is when you want to play two notes at once. Here's another bar from the song and I'll explain how it's written.

Bass added to Carol of the Bells       N0010 G01 Z0.250 X1.471 F195.767 (E32.8 C#193)
N0020 G01 Z0.369 X2.207 F195.506 (D#31.2 C#193)
N0030 G01 Z0.244 X2.943 F195.767 (E32.8 C#193)
N0040 G01 Z0.034 X4.414 F194.963 (C#27.6 C#193)

This G-code looks largely the same. The Z axis is doing the exact same thing as in the previous bar. We've added the X axis and the feed rate is way faster. This is because you can't tell the machine to move the Z axis at one rate and the X axis at another. You have to calculate the composite feed rate. Put another way, you have to find the hypotenuse of the X and Z axis.

Looking at the comments in the first line of code above, the Z axis note is an E (32.8 IPM) and the X axis is a C# (193 IPM). To find the composite feed rate, we need to use the Pythagorean theorem. Sqrt(32.8^2 + 193^2) = 195.767 IPM. So as the tool is moving along the diagonal hypotenuse, the X axis will be moving at 193 IPM and the Z will be moving at 32.8 IPM.


After hours and hours of work eventually you'll have made it through the whole song and end up with this:

And below is the G-code. If you use it on your machine, the Z will travel from -0.037 to 1.975 and the X will travel from -0.776 to 4.414. If you don't have enough room, the machine might damage itself.

N0120 G01 Z0.250 F32.8 (E Quarter)
N0130 G01 Z0.369 F31.2 (D# Eighth)
N0140 G01 Z0.244 F32.8 (E Eighth)
N0150 G01 Z0.034 F27.6 (C# Quarter)
N0160 G01 Z0.284 F32.8 (E Quarter)
N0170 G01 Z0.403 F31.2 (D# Eighth)
N0180 G01 Z0.278 F32.8 (E Eighth)
N0190 G01 Z0.068 F27.6 (C# Quarter)
N0200 G01 Z0.318 F32.8 (E Quarter)
N0210 G01 Z0.437 F31.2 (D# Eighth)
N0220 G01 Z0.312 F32.8 (E Eighth)
N0230 G01 Z0.102 F27.6 (C# Quarter)
N0240 G01 Z0.352 F32.8 (E Quarter)
N0250 G01 Z0.471 F31.2 (D# Eighth)
N0260 G01 Z0.346 F32.8 (E Eighth)
N0270 G01 Z0.136 F27.6 (C# Quarter)
N0280 G01 Z0.386 X1.471 F195.767 (E Quarter C# 3 beats)
N0290 G01 Z0.505 X2.207 F195.506 (D# Eighth)
N0300 G01 Z0.380 X2.943 F195.767 (E Eighth)
N0310 G01 Z0.170 X4.414 F194.963 (C# Quarter)
N0320 G01 Z0.420 X3.088 F177.065 (E Quarter B 3 beats)
N0330 G01 Z0.539 X2.425 F176.775 (D# Eighth)
N0340 G01 Z0.414 X1.762 F177.065 (E Eighth)
N0350 G01 Z0.204 X0.436 F176.175 (C# Quarter)
N0360 G01 Z0.454 X1.602 F156.476 (E Quarter A 3 beats)
N0370 G01 Z0.573 X2.185 F156.149 (D# Eighth)
N0380 G01 Z0.448 X2.768 F156.476 (E Eighth)
N0390 G01 Z0.238 X3.934 F155.469 (C# Quarter)
N0400 G01 Z0.488 X2.815 F150.420 (E Quarter G# 3 beats)
N0410 G01 Z0.607 X2.256 F150.079 (D# Eighth)
N0420 G01 Z0.482 X1.697 F150.420 (E Eighth)
N0430 G01 Z0.272 X0.578 F149.372 (C# Quarter)
N0440 G01 Z0.522 X1.744 F156.476 (E Quarter A 3 beats)
N0450 G01 Z0.641 X2.327 F156.149 (D# Eighth)
N0460 G01 Z0.516 X2.910 F156.476 (E Eighth)
N0470 G01 Z0.306 X4.076 F155.469 (C# Quarter)
N0480 G01 Z0.556 X2.957 F150.420 (E Quarter G# 3 beats)
N0490 G01 Z0.675 X2.398 F150.079 (D# Eighth)
N0500 G01 Z0.550 X1.839 F150.420 (E Eighth)
N0510 G01 Z0.340 X0.720 F149.372 (C# Quarter)
N0520 G01 Z0.590 X1.712 F134.268 (E Quarter F# 3 beats)
N0530 G01 Z0.709 X2.208 F133.886 (D# Eighth)
N0540 G01 Z0.584 X2.704 F134.268 (E Eighth)
N0550 G01 Z0.374 X3.696 F133.093 (C# Quarter)
N0560 G01 Z0.624 X2.964 F101.449 (E Quarter Low C# 3 beats)
N0570 G01 Z0.743 X2.598 F100.943 (D# Eighth)
N0580 G01 Z0.618 X2.232 F101.449 (E Eighth)
N0590 G01 Z0.408 X1.500 F99.889 (C# Quarter)
N0600 G01 Z0.658 X0.508 F134.268 (E Quarter F# 3 beats)
N0610 G01 Z0.777 X1.004 F133.886 (D# Eighth)
N0620 G01 Z0.652 X0.508 F134.268 (E Eighth)
N0630 G01 Z0.442 X1.500 F133.093 (C# Quarter)
N0640 G01 Z0.692 X0.381 F150.420 (E Quarter G# 3 beats)
N0650 G01 Z0.811 X0.940 F150.079 (D# Eighth)
N0660 G01 Z0.686 X0.381 F150.420 (E Eighth)
N0670 G01 Z0.476 X1.500 F149.372 (C# Quarter)
N0680 G01 Z0.726 X0.334 F156.476 (E Quarter A 3 beats)
N0690 G01 Z0.845 X0.917 F156.149 (D# Eighth)
N0700 G01 Z0.720 X0.334 F156.476 (E Eighth)
N0710 G01 Z0.510 X1.500 F155.469 (C# Quarter)
N0720 G01 Z0.760 X0.381 F150.420 (E Quarter G# 3 beats)
N0730 G01 Z0.879 X0.940 F150.079 (D# Eighth)
N0740 G01 Z0.754 X0.381 F150.420 (E Eighth)
N0750 G01 Z0.544 X1.500 F149.372 (C# Quarter)
N0760 G01 Z0.849 X0.381 F152.152 (G# Quarter G# 3 beats)
N0780 G01 Z0.988 X0.940 F151.270 (F# Eighth)
N0790 G01 Z0.836 X0.381 F152.152 (G# Eighth)
N0800 G01 Z0.586 X1.500 F150.420 (E Quarter)
N0810 G01 Z0.891 X0.237 F170.460 (G# Quarter A# 3 beats)
N0820 G01 Z1.030 X0.868 F169.672 (F# Eighth)
N0830 G01 Z0.878 X0.237 F170.460 (G# Eighth)
N0840 G01 Z0.628 X1.500 F168.915 (E Quarter)
N0850 G01 Z0.933 X0.174 F178.539 (G# Quarter B 1 beat)
N0860 G01 Z1.072 X0.757 F157.294 (F# Eighth A 1 beat)
N0870 G01 Z0.920 X1.340 F158.142 (G# Eighth)
N0880 G01 Z0.670 X0.221 F150.420 (E Quarter G# 1 beat)
N0890 G01 Z0.822 X0.957 F197.101 (G# Eighth C# Eighth)
N0900 G01 Z0.974 X0.294 F178.539 (G# Eighth B Eighth)
N0910 G01 Z1.113 X0.877 F157.294 (F# Eighth A Eighth)
N0920 G01 Z0.961 X1.460 F158.142 (G# Eighth A Eighth)
N0930 G01 Z0.711 X0.341 F150.420 (E Quarter G# Quarter)
N0940 G01 Z0.921 X1.460 F149.372 (C# Quarter, G# 3 beats)
N0950 G01 Z0.816 X0.901 F149.372 (C# Eighth)
N0960 G01 Z0.921 X0.342 F149.372 (C# Eighth)
N0970 G01 Z0.827 X-0.217 F148.872 (B Eighth)
N0980 G01 Z0.911 X-0.776 F148.439 (A Eighth)
N0990 G01 Z0.753 X0.343 F148.252 (G# Quarter, G# 3 beats)
N1000 G01 Z0.832 X0.902 F148.252 (G# Eighth)
N1020 G01 Z0.753 X1.461 F148.252 (G# Eighth)
N1030 G01 Z0.823 X2.020 F147.949 (F# Eighth)
N1040 G01 Z0.761 X2.579 F147.713 (E Eighth)
N1050 G01 Z0.901 X1.413 F154.102 (F# Quarter, A 2 beats)
N1060 G01 Z0.831 X0.830 F154.102 F# Eighth)
N1070 G01 Z0.901 X0.247 F154.102 (F# Eighth)
N1080 G01 Z0.822 X0.910 F175.227 (G# Eighth, B Eighth)
N1090 G01 Z0.892 X0.327 F154.102 (F# Eighth, A Eighth)
N1100 G01 Z0.767 X1.446 F147.713 (E Quarter G# 3 beats)
N1110 G01 Z0.708 X2.005 F147.616 (D# Eighth)
N1120 G01 Z0.646 X2.564 F147.713 (E Eighth)
N1130 G01 Z0.541 X3.683 F147.447 (C# Quarter)
N1140 G01 Z0.620 X3.124 F148.252 (G# Eighth, G# 3 beats)
N1150 G01 Z0.708 X2.565 F148.622 (A# Eighth)
N1160 G01 Z0.807 X2.006 F149.085 (C Eighth)
N1170 G01 Z0.912 X1.447 F149.372 (C# Eighth)
N1180 G01 Z1.031 X0.888 F150.079 (D# Eighth)
N1190 G01 Z1.156 X0.329 F150.420 (E Eighth)
N1200 G01 Z1.295 X0.888 F151.270 (F# Eighth G# 3 beats)
N1210 G01 Z1.447 X1.447 F152.472 (G# Eighth)
N1220 G01 Z1.725 X2.566 F151.270 (F# Quarter)
N1230 G01 Z1.975 X3.685 F150.420 (E Quarter)
N1140 G01 Z1.896 X3.126 F148.252 (G# Eighth, G# 3 beats)
N1150 G01 Z1.808 X2.567 F148.622 (A# Eighth)
N1160 G01 Z1.709 X2.008 F149.085 (C Eighth)
N1170 G01 Z1.604 X1.449 F149.372 (C# Eighth)
N1180 G01 Z1.485 X0.890 F150.079 (D# Eighth)
N1190 G01 Z1.360 X0.331 F150.420 (E Eighth)
N1200 G01 Z1.221 X0.890 F151.270 (F# Eighth G# 3 beats)
N1210 G01 Z1.064 X1.449 F152.472 (G# Eighth)
N1220 G01 Z0.786 X2.568 F151.270 (F# Quarter)
N1230 G01 Z0.536 X3.687 F150.420 (E Quarter)
N1240 G01 Z0.286 X2.216 F195.767 (E Quarter C# 3 beats)
N1250 G01 Z0.167 X1.480 F195.506 (D# Eighth)
N1260 G01 Z0.292 X0.744 F195.767 (E Eighth)
N1270 G01 Z0.502 X-0.727 F194.963 (C# Quarter)
N1280 G01 Z0.252 X0.599 F177.065 (E Quarter B 3 beats)
N1290 G01 Z0.133 X1.262 F176.775 (D# Eighth)
N1300 G01 Z0.258 X1.925 F177.065 (E Eighth)
N1310 G01 Z0.468 X3.251 F176.175 (C# Quarter)
N1320 G01 Z0.218 X2.085 F156.476 (E Quarter A 3 beats)
N1340 G01 Z0.099 X1.502 F156.149 (D# Eighth)
N1350 G01 Z0.224 X0.919 F156.476 (E Eighth)
N0390 G01 Z0.434 X-0.247 F155.469 (C# Quarter)
N1360 G01 Z0.184 X0.872 F150.420 (E Quarter G# 3 beats)
N1370 G01 Z0.065 X1.431 F150.079 (D# Eighth)
N1380 G01 Z0.190 X1.990 F150.420 (E Eighth)
N1390 G01 Z0.400 X3.109 F149.372 (C# Quarter)
N1400 G01 Z0.150 X2.377 F101.449 (E Quarter Low C# 3 beats)
N1410 G01 Z0.031 X2.011 F100.943 (D# Eighth)
N1420 G01 Z0.156 X1.645 F101.449 (E Eighth)
N1430 G01 Z0.366 X0.913 F99.889 (C# Quarter)
N1440 G01 Z0.116 X1.645 F101.449 (E Quarter Low C# 3 beats)
N1450 G01 Z-.003 X2.011 F100.943 (D# Eighth)
N1460 G01 Z0.122 X2.377 F101.449 (E Eighth)
N1470 G01 Z0.332 X3.109 F99.889 (C# Quarter)
N1480 G01 Z0.082 X2.377 F101.449 (E Quarter Low C# 3 beats)
N1490 G01 Z-0.037 X2.011 F100.943 (D# Eighth)
N1500 G01 Z0.088 X1.645 F101.449 (E Eighth)
N1510 G01 Z0.298 X0.913 F99.889 (C# Quarter)