Connecting to an old portable CMM (MicroScribe 3DX). This is a robot arm type CMM using
serial link kinematics to track the tip position. I wanted to check the functionality of this device
but the original software wasn't readily available, so I wrote my own.
The code:
https://github.com/jarofmolasses/microscribe
If our PC had an RS-232 port like before, we could directly connect the MicroScribe and have our python program handle everything.
Unfortunately not the case for us now, so instead we use an Arduino as RS-232 adapter.
The Arduino isn't strictly necessary to do this, a direct USB-RS232 adapter could work as well and would be cleaner hardware-wise.
I didn't have one when I started the project and it was convenient enough to write a bit of Arduino code to handle it, using the original SDK as a starting point.
The old SDK and an example Arduino port are archived here: https://github.com/martennettelbladt/microscribe/tree/main
The PC software is written in python and unwisely uses matplotlib as a 3D graphics engine. Matplotlib is not intended to do this,
but it actually works pretty decently - lack of graphics acceleration notwithstanding. Using the joint angles reported by the Microscribe,
a live updating 3D model of the arm is displayed in the GUI.
The app is mostly intended to be a simple demonstration but it has some CMM functionality:
Source code for demo: DHjointsDemo.py
We can determine the position and orientation of the stylus by computing the forward kinematics of the arm.
There are many ways to describe the kinematics of the system, so how we approach this will depend on how the constants have been stored in
the machine EEPROM.
The Arduino code provides a function print_hci_strings()
to pull the system information from the unit, we get:
PRODUCT NAME: MicroScribe3D
PRODUCT ID: MSCR
MODEL NAME: DX
COMMENT: Standard+Beta
PARAM FORMAT: Format DH0.5
VERSION: HCI 2.0
I'm actually not sure what "DH0.5" refers to, but I assumed that it means modified Denavit-Hartenberg (as opposed to standard DH) parameters, and this seems to check out.
A reference frame is placed at each joint, plus the tip of the stylus, for a total of n = 6.
The static "zeroth" reference frame is at the base of the unit.
Each reference frame is described by 4 parameters - 3 constant and 1 variable:
print_param_block()
, with which we can get the constant parts of the transformation matrices:
OFFSETS D:
210.820007
-22.250398
-0.025400
234.848403
8.128000
-134.010391
OFFSETS A:
0.000000
24.307800
260.400787
13.893800
-10.160000
10.160000
SKEW ALPHA:
0.000000
1.567824
0.002684
1.567920
-1.572618
-1.569550
Point clouds up to 2000 points can be generated, and exported as CSV files.
Three points can be collected (starting with origin, then defining two basis vector endpoints) which define a reference plane.
Then, the normal distance between the tip and reference plane can be measured.
A second measurement will bring up the point-to-point distance between the two latest measurement points.
May 2025