Wednesday, 20 May 2026

Wiring the control box up again - Mesa boards and P330 Tiny PC. Magic smoke!!


Before I start, here's what we have today. There's an ASrock J1900 Mini-ITX mobo in that black box, along with a Mesa 5i25 Superport board. The breakout boards 7i76 and 7i85 are mounted on the lid. I will leave the PC in the box where it is, in case I want to flash it up later to access any files. Besides, there's no benefit in removing it and I'm not about to remount all the wiring and boards.

The 7i76 has some messy wiring on it that needs to be tidied up later. These are the limit and home switches for the X and Z axes and I clearly never got around to terminating them in a workmanlike manner.

TB6 is the "field inputs" section, where these limit switch inputs terminate.


With the lid off, we can see the 5i25, which is mounted on the case and connected by a couple of ribbon cables to a PCI-to-PCIe adaptor - the 5i25 needs an old fashioned PCI slot but the mobo only has a PCIe slot. I need to recover the 5i25, then reassemble it, leaving it operational, just in case.




Removed.




Here's the old adaptor, alongside the new one, which uses a USB-type cable to communicate with the PCIe plug. That's handy, as there's no room inside the Tiny PC for the 5i25. Both use the Asmedia ASM1083 bridge IC.


Back together again.


A quick note of the 256GB SSD and 8GB RAM:



Only one slot is occupied, so could increase memory if I have some spare.


New adaptor board in place, cover ready to go back on. Looks good to me. It could almost have been planned:



The 5i25 plugs into to the adaptor board. But when I do this, the PC won't boot and the 12V supply shuts down. Clearly something not right here. Note the brown smudge on the PCI edge connector - that PTC has let some smoke out!


The root cause of the problem is actually visible in ths pic:


This is how I assembled it, with all external connections at the same end:


But in fact, this is how it's supposed to be fitted:


From Wikipedia, it seems that this PCI board is "Universal (3.3V & 5V) 32-bit PCI Card", which can be fitted the wrong way round. If you have the mounting bracket and are fitting the board into a mobo, perhaps there's less of a risk of getting it wrong.


So because of this, the 5i25 has 2 slots, allowing it to be fitted either way round. Have I popped something? That burnt PTC ("self resetting fuse") is protecting the 5V supply to one of the BOBs. Luckily I'm not relying on that route, as they have their own dedicated 5V PSU.


No. Luckily, the PC, adaptor board, 5i25 and breakout boards have all survived. TFFT!

And yes, the PC still works and the BOBs appear to be functional. Onwards and upwards!

Sunday, 17 May 2026

VFD speed noisy?

The spindle control on the Bantam / LinuxCNC system seems to be suffering from noise. Although I can set a constant speed demand within LinuxCNC, the VFD itself seems to be having a difficult time maintaining a nice, smooth speed. 

The VFD itself is a rather unusual device, being of New Zealand origin and dating back to the mid 1990s. I acquired a few of these after the demise of Wavedriver Ltd (a maker of electric vehicle drives and components) at the hands of Powergen (national utility company, run by a bunch of grubby thrusters). It works well and is unusual in having a single phase 240V input and a power rating of 5.5kW - most single phase VFDs max out at ~4kW these days, as you are expected to use 3-phase above that sort of power.

Luckily I grabbed a copy of the manual some years back, so I can look up the functions and connections.

Without diving into the detailed info about setting up the analogue inputs (I've already done that of course), this high level diagram tells me what I need to know:


And this is what it actually looks like in the cabinet. The cover is off the VFD and there's a scope and probe draped over the wiring, otherwise it's actually reasonably tidy in there.


And here's the signal connections on the VFD end:

The 3 wires at the VFD that I am interested in are:
  • T13: +10V reference voltage
  • T14: Analogue input 1
  • T15: Analogue 0V

And yes, the screen is already connected to the analogue 0V / ground.

At the other end of the cable, the "digital potentiometer" within the Mesa 7i76 sits on an electrically isolated island, with the signal passed across the isolation barrier by means of a high speed digital opto, followed by a low pass filter and opamp, presumably powered from the +10V analogue reference voltage (although I can't be arsed to check that).

A point worth registering is that the analogue island isn't grounded at either end. There are a few different options here:

  • Ground one or both ends of the cable, noting that the analogue ground and screen are the same (possibly not helpful?), as I seem to recall I ran out of wires in the screened cable. So perhaps grounding the VFD end of the screen would make sense.
  • Slap a cap between the analogue control voltage and the analogue ground / screen - to dampen any differential mode noise. A lossy electrolytic might work here.
  • Put some ferrite clamps on the cable - to attenuate any common mode noise.
Here's what it sounds like - and looks like on the scope. Lots of very energetic bursts of ringing going on there.


  • Result of fitting a ground wire to the screen - zich.
  • Result of slapping a cap on the analogue voltage - zilch.
  • ...and I couldn't find my stash of ferrite clamps, so this will have to wait until a load of Chinese clamps of unknown spec arrive tomorrow.
So although annoying, this isn't critical. However, it's been persisting for a long time and the current hiatus (replacing the PC) would seem like a good opportunity to fix it.

Update: slapped 5 of the ferrite clamps on the signals wires / cables. I'm assuming these are actually some kind of lossy ferrite, of course. Made sod all difference. That's with ground wire, lossy electrolytic and ferrite clamps.

I may be forced to fit a proper modern VFD here but for now I have my hands full, changing the PC from the ASrock J1900 to a Thinkstation P330. 

Saturday, 16 May 2026

Crash prevention for PBL conversational lathe cycles?

When trying out / developing / testing the conversational cycles in Probe Basic Lathe, it's been pretty clear that it would be quite easy to accidentally type in an inappropriate diameter (X coordinate) or axial position (Z coordinate). Humans are good at doing this sort of thing. But worst of all, there's currently nothing by way of a sanity check in the macros to prevent a bad crash. They are pretty robust and straightforward but they expect a degree of responsibility on the part of the user to get the coordinate inputs right.

By experimenting with different starting positions when trying out the macros with air cuts, the result of wrongly specifying X and/or Z coordinates is easy to see on the backplot. In simple terms, the positioning (clearance and positioning) moves are simply based on the starting position and the dimensions of the stock and the feature to be machined, as specified in the setup table. The macro doesn't check the tool position against the outline of the stock you have defined, yet it executes rapid positioning and clearance moves based on that info. What could possibly go wrong?

As you can see, positioning the tool as shown below results in the tool attempting retract and positioning moves within the stock - not ideal: 

Here's a tool start position at 7mm (diameter), with "10mm diameter at corner" ie stock diameter.


Looks almost sensible:


Same operation but with tool, start position at 7mm (diameter), with "10mm diameter at corner" ie stock diameter.


Oooof. Lots of retract and positioninbg moves within the stock:


We can surely do better than this, based on the information at hand.

Quite simply, the plan is for the tool to approach the toolpath from outside the stock in both X and Z. However, if the starting X and Z coords are within the stock outline, an error should be notified and the operation aborted.

Doesn't sound very tricky to implement, so I asked Claude to propose a simple sanity check. 

Good progress. Here's my
suggestion for the sanity checks:
After starting_X and starting_Z are captured (before any motion), add a block that checks:
checks:
Z-side check (wrong side of the face):
  • Front outside / Front inside: starting_Z must be > radius_z (approach from the open/tailstock side)
  • Rear outside: starting_Z must be < radius_z (approach from the chuck side)
X-clearance check (inside the stock):
  • Front outside / Rear outside: starting_X must be > radius_x (outside the OD)
  • Front inside: starting_X must be < radius_x (inside the bore)
In NGC it would look like
this immediately after the starting_X/starting_Z assignments:

o120 if [#<radius_exterior_front> GT 0]
     o121 if [#<starting_Z> LE #<radius_z>]
          (MSG,ERROR: Front outside radius - start tool to the +Z side of the face)
          o121 return [-2]
     o121 endif
     o122 if [#<starting_X> LE #<radius_x>]
          (MSG,ERROR: Front outside radius - start tool outside the diameter)
          o122 return [-2]
     o122 endif
o120 elseif [#<radius_interior> GT 0]
     o123 if [#<starting_Z> LE #<radius_z>]
          (MSG,ERROR: Front inside radius - start tool to the +Z side of the face)
          o123 return [-2]
     o123 endif
o120 elseif [#<radius_exterior_rear> GT 0]
     o124 if [#<starting_Z> GE #<radius_z>]
          (MSG,ERROR: Rear outside radius - start tool to the -Z side of the face)
          o124 return [-2]
     o124 endif
     o125 if [#<starting_X> LE #<radius_x>]
          (MSG,ERROR: Rear outside radius - start tool outside the diameter)
          o125 return [-2]
     o125 endif
o120 endif

One subtlety: the radius_x comparison for front inside is less clear-cut (the boring bar could be anywhere inside the bore), so I'd leave that one out unless you want to add it. The Z-side check catches the most dangerous crash scenario.

Want me to add this to the file?

Let's test this out and see if there are any situations where this might be a problem limiting the desired operation - and if it is actually a useful safety feature in the first place. If it looks helpful, we can then implement similar sanity checks on the other operations.

Here's the equivalent operation in the Radius macro, with this error checking implemented:


There's no machine movement and the error box pops up.

Once the tool position on the X axis exceeds the specified "Diameter at Corner" value, operation is allowed. Sounds like a good result.

Checking with the tool position on the Z axiswithin the stock bounds also works:


That is a win. 

A couple of observations / issues to fix next:

  • The macros will run with T0 ("no tool") loaded, at which point, there's no tool shape shown in the backplot. Is that a problem?
  • It would be handy to have some gridlines shown in the backplot to give an idea of scale. Perhaps autoscaled to suit the operation in hand.
So, let's get the other sanity checks implemented, then get these 2 points resolved.

Sunday, 10 May 2026

Testing the lathe cycles

After some distinct buggerage with the lathe cycle graphics, let's do some actual testing of the cycles on a live machine. Of course, I can start by checking what commands the macros are sending to the machine controller but ultimately I need to see what happens when I run the machine.

The more conventional "turning" and "facing" operations are prett straightforward and although I can't pretend I've done any seriously thorough testing at this stage, they seem to work largely as expected. I'm sure I can finesse the instructions a bit but initially I need to know if the toolpaths are almost sensible looking.

The "chamfer" toolpaths don't seem to be working quite as expected. There are 3 "corner types" on offer, depending on which of the3 possible chamfers you want to machine.

External chamfer (Front Outside"):

Here's the dummy setup I'm planning to run. It's air cutting at this stage but the tool starting position and chamfer parameters are hopefully good starting points.


And here's the displayed toolpath trace ie where the tool actually went, as reported in the backplot panel within the main screen:


Ooof. What's happening here?
  • The backplot trace is all over the shop. This is due to the graphics freezing up, then waking up again and jumping to the current position. So parts of the toolpath are missing, with rogue traces where the jumps happened. The machine itself was working as expecting, so this seems to be a graphics problem.
  • The starting coordinates are inappropriate. The macros start by acquiring and storing the current machine coordinates under the active WCS. This position is then used as the retract position (G30 perhaps?), so ideally you'd get them right. In my case, I seem to have positioned the tool miles away from the stock. It's a learning process, I guess.
  • But more worryingly, the toolpath seems to be making rapid moves within the stock. For an external "Front Outside" chamfer, the tool should be clearing the work to the right and bottom of the screen for a front toolholder. The cause is actually quite visible - for this type of chamfer, the "chamfer distance" argument (5mm here) should immediately follow the feed argument (0.15mm) - check out the orange "call" script at the bottom of the setup panel). So, by sending the distance parameter as the 8th argument rather than the 7th argument, the GUI is accidentally specifying a "rear outside" chamfer. This turned out to be fairly simple to fix.
Here's the chamfer.ngc file:

chamfer
o<chamfer> sub

  o<backup_status> call

#<chamfer_x>              = #1
#<chamfer_ss>             = #2
#<chamfer_doc>            = #3  ;depth of cut
#<chamfer_z>              = #4
#<chamfer_tool>           = #5
#<chamfer_feed>           = #6
#<chamfer_exterior_front> = #7   ;will be cut if > 0
#<chamfer_interior>       = #8   ;will be cut if > 0
#<chamfer_exterior_rear>  = #9   ;will be cut if > 0
#<chamfer_coolant>        = #10
#<chamfer_maxrpm>         = #11
#<chamfer_units>          = #12  (=21) (20=inch, 21=mm)

        o100 if [#<chamfer_tool> NE #<_current_tool>]
             (MSG,ERROR : Set tool before use macro)
             o100 return [-2]
        o100 endif

        o105 if [#<chamfer_doc> LE 0]
             (MSG,ERROR: Depth of cut must be greater than zero)
             o105 return [-2]
        o105 endif

G8  ; Lathe radius Mode
G18 ; XZ Plane
G90 ; Absolute Distance
G21 ; Metric

#<chamfer_x> = [#<chamfer_x> / 2] ; because of radius mode
#<starting_X> = #<_x> (starting X)
#<starting_Z> = #<_z> (starting Z)

G96 D#<chamfer_maxrpm> S#<chamfer_ss> ; Constant Surface Speed Mode
M3            ; Start Spindle
G95 F#<chamfer_feed>      ; Feed-Per-Rev Mode
G4P1          ; Wait to reach speed

        o110 if [#<chamfer_coolant>]
                M8
        o110 endif

#<temp> = 0
        o200 if [#<chamfer_exterior_front> GT 0] ; front outside
             o201 while [[#<temp> + #<chamfer_doc> ] lt #<chamfer_exterior_front> ]
                  #<temp> = [#<temp> + #<chamfer_doc> ]
                  G0 x[#<chamfer_x> - #<temp>] z#<starting_Z>
                  G1 z#<chamfer_z>
                  G1 x#<chamfer_x> z[#<chamfer_z> - #<temp>]
                  G1 x#<starting_X>
                  G0 z#<starting_Z>
             o201 endwhile

             G0 x#<starting_X> z#<starting_Z>
             G0 x[#<chamfer_x> - #<chamfer_exterior_front> ]
             G1 z#<chamfer_z>
             G1 x#<chamfer_x> z[#<chamfer_z> - #<chamfer_exterior_front> ]
             G1 x#<starting_X>
             G0 z#<starting_Z>
        o200 elseif [#<chamfer_interior> GT 0] ; front inside
             o202 while [[#<temp> + #<chamfer_doc> ] lt #<chamfer_interior>  ]
                  #<temp> = [#<temp> + #<chamfer_doc> ]
                  G0 x[#<chamfer_x> + #<temp>] z#<starting_Z>
                  G1 z#<chamfer_z>
                  G1 x#<chamfer_x> z[#<chamfer_z> - #<temp>]
                  G1 x#<starting_X>
                  G0 z#<starting_Z>
             o202 endwhile

             G0 x#<starting_X> z#<starting_Z>
             G0 x[#<chamfer_x> + #<chamfer_interior>  ]
             G1 z#<chamfer_z>
             G1 x#<chamfer_x> z[#<chamfer_z> - #<chamfer_interior> ]
             G1 x#<starting_X>
             G0 z#<starting_Z>
        o200 elseif [#<chamfer_exterior_rear> GT 0] ; back outside
             o203 while [[#<temp> + #<chamfer_doc> ] lt #<chamfer_exterior_rear>]
                  #<temp> = [#<temp> + #<chamfer_doc> ]
                  G0 x[#<chamfer_x> - #<temp>] z#<starting_Z>
                  G1 z#<chamfer_z>
                  G1 x#<chamfer_x> z[#<chamfer_z> + #<temp>]
                  G1 x#<starting_X>
                  G0 z#<starting_Z>
             o203 endwhile

             G0 x#<starting_X> z#<starting_Z>
             G0 x[#<chamfer_x> - #<chamfer_exterior_rear>]
             G1 z#<chamfer_z>
             G1 x#<chamfer_x> z[#<chamfer_z> + #<chamfer_exterior_rear>]
             G1 x#<starting_X>
             G0 z#<starting_Z>
        o200 endif
M5
M9

  o<backup_restore> call     ; restore g20/21, g90/g91, feedrate cuter-comp and other using now global _backup_var

o<chamfer> endsub

M2
%

By placing the chamfer distance in argument #7 instead of #8, the cycle will select the correct section of code to execute("if [#<chamfer_exterior_front> GT 0] ; front outside" etc).

External chamfer ("Rear Outside"):


This looks almost credible, with the caveat that again, I seem to have positioned the virtual tool miles from the actual stock. And again, the graphics is sorely messed up due to the freezing / jumping behaviour:

Internal Chamfer ("Front Inside"):


Ditto, the freezing graphics issue and starting position have made a mess of things but otherwise it's actually looking OK:


There then followed a session where Claude buggered about with the Python code that generates these calls. This fixed the front / rear chamfer mixup.

Graphics problems:

As for the freezing graphics, "we" ended up changing "wake states" in the BIOS (no, me neither), which then highlighted an apparent "bug" (hate that word) in the rendering of the backplot. This resulted in the backplot completely vanishing for most of the rest of the day. I was able to monitor the PC between real life tasks elsewhere using the GL-iNet KVM (remote KVM over the network) as Claude beasted away trying (mostly in vain) to identify and fix the problem - and finally we got our backplot back by the end of play yesterday.

The __doCommonSetViewWork() in setViewXZ is at line 1732. I need to add a self.renderer.ResetCamera() call after it, but the file is owned by root. Please run:

sudo sed -i '1732 a\        self.renderer.ResetCamera()' /usr/lib/python3/dist-packages/qtpyvcp/widgets/display_widgets/vtk_backplot/vtk_backplot.py

This adds ResetCamera() right after __doCommonSetViewWork() in setViewXZ, which will auto-fit the camera scale to show the full machine. Then restart LinuxCNC.

Woohoo that fixed it. What was the root cause in the end?

The root cause was a bug in the QtPyVCP VTK backplot code, unmasked by the i915 boot.

The bug: setViewXZ() (the lathe's default view) positions the camera but never sets the parallel projection scale. VTK defaults to scale = 1.0, which means only ±1mm of the scene is visible. The tool cursor exists in the scene, but the camera is so zoomed in you can't see anything.

Why it worked before: Almost certainly the camera was being auto-scaled by a ResetCamera() call that was subsequently commented out in the code (line 600 has # self.renderer.ResetCamera()). At some point during PBL development someone commented it out — probably because it was causing an unwanted camera jump — but left the lathe XZ view broken as a side effect.

Why the i915 boot exposed it: Before May 11, PBL had probably been running continuously or being restarted without a full cold-start. Something in the Qt/VTK window lifecycle (resize event, first paint, etc.) was accidentally triggering a camera reset that masked the bug. The i915.enable_rc6=0 boot forced a different initialisation path — VTK's GL context was set up differently — which stopped that accidental rescaling from happening. After reverting i915, the "lucky" rescaling never came back, leaving the bug fully exposed.

The fix: Explicitly calling renderer.ResetCamera() after setViewXZ() sets the scale correctly from machine actor bounds every time.

which file has been corrected?

/usr/lib/python3/dist-packages/qtpyvcp/widgets/display_widgets/vtk_backplot/vtk_backplot.py

Note that this is a system package file — it will be overwritten if python3-qtpyvcp is ever upgraded. If that happens, you'd need to reapply the sed command. Worth keeping a note of it.


And here's what we get when we choose a sensible starting point for the tool position:

There's still the graphic problem causing the freezing / stuttering / jumping issue. I guess that's the next thing to focus on.

Saturday, 9 May 2026

Grooving grief!

I've made some progress getting Andy Pugh's conversational macros implemented in the Probe Basic Lathe (PBL) GUI for LinuxCNC. PBL is one of several GUIs that have been developed for the LinuxCNC control system and in my view it actually looks like a reasonably user friendly and almsot attractive user interface. Previously, I was using the gmoccapy GUI but although functional, it looked pretty clunky.

PBL looks similar to the Pathpilot GUI used by Tormach for their machines - this is actually based on LinuxCNC but has been developed and tested by their own professional software engineers. While it's possible to fiddle with Pathpilot and create a customised version for non-Tormach applications, it's not a well-trodden path and comes with challenges of its own. In contrast, PBL is actively supported, although on the downside it has very limited resources dedicated to its development.

As mentioned previously, I'm planning to use PBL with the conversational macros ("lathe cycles"), which I saw as one of its attractions. However, I discovered that this would require me to do the work to get it up and running, as the cycles haven't actually been implemented yet, beyond being imported as a placeholder. 

One aspect of this is the graphics that are shown in the "Lathe Cycles" panels. Ideally they would be simply imported into PBL - but nothing is that simple, as gmoccapy was created using the Glade environment, while PBL was developed and implemented in Qt. I know almost nothing about either. Claude Code to the rescue? As previously described, it's managed to get my PBL system up and running, so hopefully he/it can also assist with getting these macros running.

He/it made a good start but we hit a good old roadblock when it came to the "groove" operation. The (relatively few) parameters required to set it up comprise the groove diameter (at the root of the groove), the position of the groove on the Z axis and the feed rate (mm per revolution).

The source graphics are vector-based, rather than bitmap, so you might think this would make manipulation relatively straightforward - but you'd be wrong there. Here's the hilarious series of (failed) attempts at placing the dimensions (leader lines and dimension arrowheads). Sounds like a reasonably simple task?

In Linux, there's a graphics editor called Pinta that in some ways is similar to Microsoft Paint. This allows fairly simple edits to be made. So here, I'm trying to show Claude where the leaders (red) and arrowheads (blue) need to go.


Er, no. 


Er, no.


Getting there?


FFS, now it's 90 degrees off. That hardly constitutes progress.


God.

Slightly better?



Claude suggested I choose one of these 3 lines


Woohoo. Getting there - but the arrowheads need to be clear of the body for clarity.


Dear god. Now the leaders are too short.


That's ALMOST there. But the LH leader is off to the side by several pixels.


Now if only those leaders ended at the surface of the body...


Losing the will to live here - but it's almost acceptable now.


And here's what it looks like when you flash up PBL and select the groove operation.


F*ck me, that took hours off my life. I can safely conclude that graphics manipulation isn't Claude's strong point. Or even Claude's weak point.

Hopefully now I can do some actual reviewing, testing and finessing.

Wiring the control box up again - Mesa boards and P330 Tiny PC. Magic smoke!!

Before I start, here's what we have today. There's an ASrock J1900 Mini-ITX mobo in that black box, along with a Mesa 5i25 Superpor...