3D touch probe connected to can bus

Hello all,

I’ve recently been experimenting with creating a 3D touch probe that I would like to use for things like engraving on non flat surfaces (that need to be scanned first). To find the center in holes when setting work origin etc. So I designed a DIY version of such a touch probe which I posted earlier on the forum in one of the DIY module threads:

The video just shows a continuity test and that the principle works. Still needs some small improvements but already quite satisfied with this so far.
The design files (OpenSCAD) can be found here:

It still lacks some documentation and pictures or video on the assembly. I’ll keep updating as I further work on the design.

A visualization of the design:

Of course, a next step is to have it talk with the Snapmaker so it can be used as an alternative probe (like the inductive sensor in the printhead). For this some hardware and software is needed. Since I’ve had some ESP32 devices laying around and this already has a CAN controller on board, I just needed a CAN transceiver to get it connected to the SnapMaker.
The current state of the code is to be found in this repository:

It’s a platformIO project so should be very easy to get started with if someone wants to experiment with it.

Again, still very rough and needs a significant amount of extra work (and some documentation like the wiring scheme, although simple). For now I can use my DIY probe perfectly when the printhead is connected to the controller as I can send messages with the right CAN Packet ID to indicate if it touches the bed yes or no when doing a Z-probe (G30) command or running the bed calibration. Haven’t checked yet if G38 works.

When the CNC head is connected it doesn’t work unfortunately as the G30 command doesn’t really do anything. To be investigated how that could be made to work. Might need a change in the code of the module and/or controller.

Some weirdness I’ve seen so far: between reboots the ID linked to the bed sensor (3D printhead) has been 0x605 and 0x604 :unamused: . Still need to figure out how and where the ID is decided and how to know which one it should be.

To be continued. Any ideas and suggestions are definitely welcome :slight_smile:


You’ll need to announce the z probe feature during initialization, otherwise the controller knows there’s no probe.

I think. Been awhile since I’ve looked into it.

1 Like

This is my first ever hands-on interaction with a CAN bus, so I’m just trying stuff so far. This definitely helps me look in the right direction :slight_smile:

Peruse the print_head.cpp in the modules repo. It’s pretty simple.

This is where the module responds to a function request at startup: https://github.com/Snapmaker/Snapmaker2-Modules/blob/1a2135a09551f4ea1c1038fa9c7e23d0ba00cccd/Marlin/src/module/print_head.cpp#L54

And here’s where it reports status on a trigger: https://github.com/Snapmaker/Snapmaker2-Modules/blob/1a2135a09551f4ea1c1038fa9c7e23d0ba00cccd/Marlin/src/module/print_head.cpp#L105

The controller uses do_blocking_move_to for the probing movement, knowing that the endstop will directly stop motion in the bresenham stepping algorithm.

endstops.enable_z_probe(true); must be called at some point to enable the z probe so that when it triggers motion will be interrupted.

In probe_pt for G30 calls that’s handled via the macro here: https://github.com/Snapmaker/Snapmaker2-Controller/blob/2234db4ca4505564eac675eb1911843f5935e614/Marlin/src/module/probe.cpp#L749

For G38 it’s directly called here in a different way: https://github.com/Snapmaker/Snapmaker2-Controller/blob/2234db4ca4505564eac675eb1911843f5935e614/Marlin/src/gcode/probe/G38.cpp#L35

The z probe is an endstop just like the switches on the axes so enabling “all” endstops in G38 also enabled the z_probe endstop.

In Stepper.cpp the function endstops.update() is called to check all endstops, including the probe, which shows up here: https://github.com/Snapmaker/Snapmaker2-Controller/blob/2234db4ca4505564eac675eb1911843f5935e614/Marlin/src/module/endstops.cpp#L1039, amongst other places like L917.

The probe endstop status is stored in printer1->probe_state(), which is part of toolhead_3dp.h

^ The fact the printer holds the probe state is probably the biggest problem to overcome in the controller firmware as it may not be updated automatically. It appears it should, as long as the callback is registered properly which it isn’t: https://github.com/Snapmaker/Snapmaker2-Controller/blob/2234db4ca4505564eac675eb1911843f5935e614/snapmaker/src/module/toolhead_3dp.cpp#L39

The callback is reigstered in the toolhead_3dp.cpp Init() function.

It could be trivial to add a probe callback to the cnc head similarly, or just manually register the callback from the printer function from the cnc toolhead. I believe all toolheads are created in memory at startup so static references are fine.

1 Like

G38 definitely does some weird stuff to the printer. After running it, (G38.2 X100 F50) to see if I could touch of to the side of the bed) the printer suddenly also somehow decides that from now on the current Z-value will be 0. With the actual X-module 20 cm above the plate…

This will be fun. And you would kind of expect that homing would fix that. Unfortunately not. It’s even saved after a reboot of the printer. Isn’t that just great.
Swapping toolheads fortunately does fix it again.

Edit: ok, not able to reproduce that one. I did do a G38.2 that didn’t reach it target which caused an error. Maybe that was the source of the issue. Either way, the fun continues.

I have not had issues with G38. Perhaps the leveling mesh didn’t turn on automatically after

Had some silly failures while experimenting with it. I think it was triggered by an G38.2 X-10 that didn’t trigger the probe. This brings the machine into an error state. Don’t know why it would have caused issues after restarting. Anyway, too much of an edge case to spend time on if there’s more fun stuff to do… :innocent:

1 Like

Ok, a short update on this little side project. No real progress on the touch probe itself, but I was struggling with understanding what was going on on the CAN bus, so I decided to try and understand that a bit better first.
(And I needed an excuse to finally get to understand websockets)

So I created a very basic web-interface that runs on the ESP which is connected to the can bus to log all messages and collect which ones are sent and with what data payloads.

it’s simple and crude, but actually works ok and it’s definitely easier than staring at a console.

Next steps is to actually understand all id’s and what they are doing (and if they are useful for anything).

As mentioned, I’m using an ESP32, but don’t see why it wouldn’t work on other similar boards (Arduino, Teensy etc)

1 Like

I’ll need some time to process all that information and to understand the snapmaker source code better. but I’ve been wondering:
Would it be a good idea to consider the touchprobe as just another module? and implement it as such?

Not sure if that would be a “better” approach (for whatever definition of better). Having it act as just another extra endstop in the system. Which should mean it can be used in any combination with any other modules without code changes to those?

Been taking the approach of trying to create it as just another addon/module. But not really liking the snapmaker code so far.
So happy it’s really consistent and well documented… :roll_eyes:

1 Like

Have you had Any further development on this?

Yes and no.
The current code can be found in the respective github repositories:
For the controller; I think it has all important changes, but haven’t tested it at all. The firmware builds, but didn’t even install it yet.

For the modules; just added the boiler plate code. actual logic (which is more or less available in the github repo from the initial post. but that version only works with the 3d print head as it "uses"the already available logic of the printhead probe)

Haven’t made real changes in the last three weeks because of work, life and spring (requiring more urgent work in the garden.)
Still on my todo list and not forgotten. but not necessarily my highest priority right now.

Although I’m bit stuck (i.e. didn’t spend time on it yet) on how to get the firmware module on the esp32. The CAN messaging and addressing logic is still a bit of black box to me right now and will need some more focus.

But if you’re volunteering to help, I don’t mind :wink:

1 Like

Very interested in this project. Looking into getting some interface hardware to snoop the can buses.

Found this guy:

Or this guy (but expensive)

Both seem to have libraries working for them.

This has ended up on my low prio list for now. Still want to finish it, but life interrupted my plans a bit :slight_smile:
I’m using just an ESP32 board with an MCP2551 board and that works just fine. (see link in the opening post). With that you can already listen in on the can bus

That evtv thing seems rather expensive for basically similar hardware.

The main thing I’m missing is a better understanding of the communication protocol and how the can addresses are defined. Other than that, I think I’m pretty close to a working prototype. (that works with other toolheads than just the 3D printing toolhead)

yeah, life does get in the way hehe. I have some of my time back (suposedly) and I’d like to help this along as much as I can but, for now, I’m still trying to understand how the whole flow is for the can-bus message for the probe loop.

If you have any chance to look at this or any advances, please do post here!

A few questions that pop into my head:

  • Is there a need to modify any module definitions or lists in the controller firmware to get the gcode command to probe with alternative toolheads other than the 3dprint one, or is the probing capability something that the module tells the controller via CAN bus?
  • Which repo has the module definitions that are actually running on my machine? I can see module definitions in the official controller repo as well as in the suposed official module repo
  • Would it be possible to flash code of the module repo into an arduino/teensy and “clone” a module, like @Ronin did with his 4th axis or does it need a lot of rework? I’m trying to hook up a more powerful laser to the toolhead and I think I could do it like that.