• TalkBass has been independent since 1998. Add your voice.
    Create a free account to reply to discussions, view embedded media, and browse with fewer display ads.
    Join freeLog in
    Want zero display ads or expanded classifieds tools? Compare plans.

CNC fretboard G-code generator

After writing a macro to build a fretboard model in CAD earlier this year I then tried to find a tool chain to actually carve it on a CNC. Free 3D tool chains for Linux are hard to come by and I never did find a satisfactory solution. So instead I changed gears (no pun intended) and wrote a script to generate the required G-code directly.

This time I took a different approach and asked for the nut and bridge string spacing as well as the desired nut and fretboard-end width. This allows the script to always build ruled surface fretboards, meaning the fretboard will always be a straight line along all the string paths.

It can handle both single and compound radius boards, though adding compound did add significant math complexity that made my brain hurt. For single radius boards it will effectively flatten the radius in the middle of the board when making straight string paths. It will also calculate and tell you the fretboard-end radius for a given nut radius and string spacing that will result in an equal fretboard edge thickness all the way down the board.

Screenshot of the tool path and some of the G-code for anyone curious. The highlighted G-code are the blue lines on the toolpath:
fretboard.png


That one is the code for my pickup mule neck, basically a J-bass with 7.25" nut radius and 20" radius at the end of the board.

This is just plain python but I may build a plugin for bCNC given that is my preferred G-code streamer and all around cool tool.

So now I need to finish my CNC modifications so I can try it out. All the required parts should arrive by the end of they year -- and then I just have to actually build it. Hah!

UPDATE: The script has now been improved to also do twisted fretboards, plus perimeter engraving. See post #79 for the latest version of the script.
 
Last edited:
fwiw, per EIA convention, G01 and G00 are modal. meaning you only need to invoke it once until it is cancelled out by the other. you can save some code by adjusting your post to omit the redundant commands. for ex:

(header commands here)
G00 X1., Y1., Z.1
G01 Z-.25 F100.
Y-1. F800.
X-1.
Y1.
X1.
G00 Z.1
(etc, etc, etc)

if you really wanted to compact things you could do some parametric programming where you factor in 17.817 into each subsequent location if your control is macro enabled. you could even consider doing a local or a remote sub routine as well.
 
Last edited:
  • Like
Reactions: Jeff Siddall
fwiw, per EIA convention, G01 and G00 are modal. meaning you only need to invoke it once until it is cancelled out by the other. you can save some code by adjusting your post to omit the redundant commands. for ex:

(header commands here)
G00 X1., Y1., Z.1
G01 Z-.25 F100.
Y-1. F800.
X-1.
Y1.
X1.
G00 Z.1
(etc, etc, etc)

if you really wanted to compact things you could do some parametric programming where you factor in 17.817 into each subsequent location if your control is macro enabled. you could even consider doing a local or a remote sub routine as well.

Thanks! Yes, you are right, the code I wrote was focused on getting it working more than getting it working optimally. It turns out the way the loops happen I can take out all the G0 commands and not have it mess up any context, so I will do that.

Further optimizations that you mention have the potential to be controller specific and thus less portable (not to mention more work). Given there are only 143 lines for a whole fretboard -- even with passes spaced at 1 mm -- I think other optimizations would be largely irrelevant.
 
Thanks! Yes, you are right, the code I wrote was focused on getting it working more than getting it working optimally. It turns out the way the loops happen I can take out all the G0 commands and not have it mess up any context, so I will do that.

Further optimizations that you mention have the potential to be controller specific and thus less portable (not to mention more work). Given there are only 143 lines for a whole fretboard -- even with passes spaced at 1 mm -- I think other optimizations would be largely irrelevant.

yeah, macros can be controller dependent. i'm pretty sure almost any machine can do a local or remote sub though. still the difference is like 20 lines vs 143, so probably not worth the effort.
 
  • Like
Reactions: Jeff Siddall
Nice work! Someone has to invest the time to work these things out. CNC machines can't make accurate fingerboards by themselves. They need human brain help to figure out the design and write the code.

One comment: Remember that the final contour of the frets (radius and level-ness) is determined by the fingerboard surface, not the slots. The frets are pressed in until the head seats against the surface. The slots need to be a little bit deeper than the depth of the fret tangs. The fret tangs should never bottom out in the slots. Your G-code needs to describe cutting the surface shape of the fingerboard (probably with a ball-end router bit) first, then locating the slots by position and cutting them to a fixed depth below the surface.
 
  • Like
Reactions: Jeff Siddall
Nice work! Someone has to invest the time to work these things out. CNC machines can't make accurate fingerboards by themselves. They need human brain help to figure out the design and write the code.

One comment: Remember that the final contour of the frets (radius and level-ness) is determined by the fingerboard surface, not the slots. The frets are pressed in until the head seats against the surface. The slots need to be a little bit deeper than the depth of the fret tangs. The fret tangs should never bottom out in the slots. Your G-code needs to describe cutting the surface shape of the fingerboard (probably with a ball-end router bit) first, then locating the slots by position and cutting them to a fixed depth below the surface.

Yes, the ruled surface board means they contour of the frets will be perfectly level along the string if they are fully seated. And yes, the next job is to add fret slots.

Unfortunately the math for that could get crazy since the shape of the bottom of the slots is not a constant radius on a ruled surface board. However, I can locate the center and two ends of the slot so I think I will write a "triangular bottom" slot. Significantly shallower slot in the middle of the board compared to a flat bottom but feasible to implement. Even then, my brain is going to hurt!

I will make the slot depth configurable, but it seems like most people recommend 1.5x the tang height.
 
Last edited:
in free cad can you generate an intersection edge curve at the fret position with a perpendicular surface and then translate it into the model? this will give you your radii and depth at each position. or you could just keep it on the surface and loop the depth cuts in going incremental (G91) and using (L)
 
in free cad can you generate an intersection edge curve at the fret position with a perpendicular surface and then translate it into the model? this will give you your radii and depth at each position. or you could just keep it on the surface and loop the depth cuts in going incremental (G91) and using (L)

Yes, I probably could, but that sounds hard, and less good since it builds a dependency on FreeCAD also.

However, having thought about this some more, I can probably interpolate fretboard tool path path calculations (basically what the CNC controller does) to locate the fret slot position. That could also let me make a quasi-curved fret slot bottom based on line segments. Still making my brain hurt.
 
is the overall goal to make a standalone "module" so that anyone can make a complete fingerboard by inputting some specs.?

fwiw, a lot of people are happy with straight fret slots although radiused is better IMO.

were it mine i would consider having the code defined by the constant 17.817 for fret spacing and invoke a loop or sub based upon number of frets (user input) and combined with number of depth cuts for the slots (user input) and execute. so you would zero G54 X, Y at the nut edge of the fb and Z zero at the bottom of the fb. set T1 and H1 here as well. start pgm, move to F1 position in G90, loop in the depth cuts in G91, retract, in G90 invoke the sub with the 17.817 constant to go to F2 position, drop down to R, switch to G91 and invoke the slot depth sub again and repeat for the required number of frets. Basically just a local subroutine with simple user defined inputs via the GUI.
 
Last edited:
  • Like
Reactions: Jeff Siddall
is the overall goal to make a standalone "module" so that anyone can make a complete fingerboard by inputting some specs.?

Well... the goal for now is just to get my own CNC to make fretboards for some ongoing builds. But ultimately, yes, the idea is to just input the specs and moments later get the G-code.

If I get it working I would be happy to share with anyone else interested.
 
Last edited:
I am effectively building a custom CNC with an all metal Z-axis with 52 mm motor, 1200 mm SBR20 linear rails for the X axis and MGN15H linear rails on the Y-axis. The result will be a 30x70x8 cm cut volume (big enough for a 27.5" long fretboard or 14" wide body) and hopefully rigid enough to cut hardwood at speed without issues. All of this controlled with GRBL 1.1f.
 
fwiw, a lot of people are happy with straight fret slots although radiused is better IMO.

were it mine i would consider having the code defined by the constant 17.817 for fret spacing and invoke a loop or sub based upon number of frets (user input) and combined with number of depth cuts for the slots (user input) and execute. so you would zero G54 X, Y at the nut edge of the fb and Z zero at the bottom of the fb. set T1 and H1 here as well. start pgm, move to F1 position in G90, loop in the depth cuts in G91, retract, in G90 invoke the sub with the 17.817 constant to go to F2 position, drop down to R, switch to G91 and invoke the slot depth sub again and repeat for the required number of frets. Basically just a local subroutine with simple user defined inputs via the GUI.

I will definitely do something better than flat slots, but how close to matching the fretboard curve I can get is still unclear.

Regarding subroutines/macros, they only work easily for simple (single scale, flat bottom) work, and because one of the projects I need this for is a compound radius multiscale I won't be using them. That, plus the fact that my controller (GRBL) doesn't support macros or subroutines. Even if I approximate each fret slot as 10 line segments it's still just a few hundred lines of G-code per pass and not worth the effort to further optimize. Multiple passes will add G-code for sure but depending on the depth per pass it still probably works out to less than 1000 lines.
 
Some general thoughts:

If I were going to build a custom CNC machine for myself, I'd build two machines. One for bodies, with the length and width and frame stiffness, and a 3 1/2 hp router head. Straight linear XYZ axes. Good dust collection.

The second machine would be optimized for necks. Long narrow frame and a smaller more precision router head. And, add a fourth roll (Alpha?) axis. Either the head can tilt to either side through some angle, or the whole bed tilts. Having that extra axis would help a lot in shaping the backs of necks, radiusing fingerboard surfaces, and cutting fret slots.

Also, have a second motor head that can interchange onto the neck machine which has a right angle drive and a small slotting saw blade. Much more efficient for cutting the slots, than using a tiny router bit.
 
  • Like
Reactions: Jeff Siddall
Some general thoughts:

If I were going to build a custom CNC machine for myself, I'd build two machines. One for bodies, with the length and width and frame stiffness, and a 3 1/2 hp router head. Straight linear XYZ axes. Good dust collection.

The second machine would be optimized for necks. Long narrow frame and a smaller more precision router head. And, add a fourth roll (Alpha?) axis. Either the head can tilt to either side through some angle, or the whole bed tilts. Having that extra axis would help a lot in shaping the backs of necks, radiusing fingerboard surfaces, and cutting fret slots.

Also, have a second motor head that can interchange onto the neck machine which has a right angle drive and a small slotting saw blade. Much more efficient for cutting the slots, than using a tiny router bit.

All good thoughts and, for someone with serious manufacturing in mind, those all make sense.

In my case, I am not trying to carve complete necks or bodies. Rather, I am trying to do more finesse or tricky work -- things like ruled surface fretboards, blind fret slots, ferrule holes, pickup covers, control knobs, control recesses, etc., and for those I can get away with a small CNC and long runtimes. The spindle motor I chose is only 1/3 HP and I probably won't stress it with what I have planned.
 
I will definitely do something better than flat slots, but how close to matching the fretboard curve I can get is still unclear.

Regarding subroutines/macros, they only work easily for simple (single scale, flat bottom) work, and because one of the projects I need this for is a compound radius multiscale I won't be using them. That, plus the fact that my controller (GRBL) doesn't support macros or subroutines. Even if I approximate each fret slot as 10 line segments it's still just a few hundred lines of G-code per pass and not worth the effort to further optimize. Multiple passes will add G-code for sure but depending on the depth per pass it still probably works out to less than 1000 lines.

"gerbil" has it limits :). in reality, subs are very simple to implement because you only need to define the movement, contour, surface, etc.. once. how many times that movement is executed is up to L. what a lot of people get stuck on is how critical it is to make sure you transition from absolute to incremental and back to avoid a crash.
 
Last edited:
  • Like
Reactions: Jeff Siddall
In that case, think about placing the side rails closer together, to make the gantry frame narrower and more rigid. Make the frame so the side rails go over top of the body. You only work one area of the body at a time. Optimize it for precision work in smaller areas.

Yes, I could do that if I had a 3-axis gantry, but the gantry I have is fixed (only Y and Z axis) and the bed moves for the X-axis. Once I get it assembled I will see if I need more rigidity. The original Y-axis was like a wet noodle so anything will be an improvement!
 
Some general thoughts:

If I were going to build a custom CNC machine for myself, I'd build two machines. One for bodies, with the length and width and frame stiffness, and a 3 1/2 hp router head. Straight linear XYZ axes. Good dust collection.

The second machine would be optimized for necks. Long narrow frame and a smaller more precision router head. And, add a fourth roll (Alpha?) axis. Either the head can tilt to either side through some angle, or the whole bed tilts. Having that extra axis would help a lot in shaping the backs of necks, radiusing fingerboard surfaces, and cutting fret slots.

Also, have a second motor head that can interchange onto the neck machine which has a right angle drive and a small slotting saw blade. Much more efficient for cutting the slots, than using a tiny router bit.

so says the machinery "collector" with tons of space!:)

excellent points though actually.
 

Latest posts