The most recent moteus firmware release, 2021-12-03, added not one, but two new control modes for less common applications. Previously, mentioned was the “voltage_control_mode” for using gimbal style high resistance motors without changing the sense resistors. In this post, I’ll describe a similarly named, but very different mode “fixed voltage mode” for operating brushless motors as if they were a stepper motor.
For some applications, you don’t care about torque control, or about power consumption at all. Traditionally you would use a stepper motor in those applications, with a correspondingly less expensive stepper motor driver. However, in some cases you may still want to have high rate trajectory control, CAN based telemetry, or have already standardized on moteus controllers for other moving parts of your solution. There are two new options that can be used in such situations:
servo.fixed_voltage_mode: When this is non-zero, the primary encoder is not used for control at all. Instead, positioning is performed entirely in the electrical phase space, with a fixed voltage applied always to the phase windings.
servo.fixed_voltage_control_V: The fixed voltage to apply to the phase windings.
When this new mode is active, the controller will continually burn power in the windings of the motor and uses no feedback from the motor at all. As mentioned above, this makes it operate like a micro-stepping stepper motor, or an inexpensive gimbal motor controller. If the externally applied torque is greater than that produced by the fixed voltage, the motor will “skip” and lose track of its position.
There’s an updated release out for the mjbots pi3hat which features a useful bug fix and a minor feature.
First, the configuration of automatic retransmission was broken in several ways. The symptoms for previous versions would be that any attempt to change the CAN configuration for a bus would result in all channels attached to that controller having auto-retransmit turned off. Since it was by default on, that would typically result in a decrease in transmission reliability, and in some particular cases with arbitration conflicts, could result in frequent packet loss. Fixing this requires updating both the firmware on the device and the C++ and python libraries. Fortunately, this would only come up if you were communicating with non-moteus devices using the pi3hat, which likely isn’t that common.
Upgrading the firmware of existing pi3hats is not trivial, since it requires use of the external stm32 programmer and an openocd version that is not yet packaged in any major Linux distribution.
Second, the python packages have been updated to support the newly released Raspberry Pi OS “bullseye” 11.0 out of the box.
The moteus brushless controller can drive many motors out of the box, but until now it has been challenging to use with gimbal style brushless motors. They are wound with thin wire so that they have a very high winding resistance, and thus can be driven by inexpensive low current controllers. Using something like moteus with a gimbal motor isn’t absolutely necessary, but does give benefits in terms of high performance trajectory tracking and torque control.
The primary challenge when using moteus with high winding resistance motors is the mechanism moteus uses to sense current through the motor phases. It has a set of 3 current sense shunts, basically resistors, that have a small voltage induced across them proportional to the amount of current flowing. When commanding a specific current, moteus continually adjusts the voltage on each of the phase windings until the desired current is achieved. These resistors are sized so that moteus has reasonable resolution up to its 100A maximum current rating. When used with a motor that has a maximum current of 1A though, almost all of this resolution is wasted.
In the past I have replaced the sense resistors on moteus boards in order to drive gimbal motors. That is the optimal solution, as it allows moteus to continue to sense the current through the windings and provide accurate torque control. But not everyone is set up to perform surface mount soldering, and accurate torque control at all speeds and temperatures is not required in many applications.
Voltage mode control
As of release 2021-12-03, moteus now has a new configurable option, called “voltage_mode_control”. In this mode, torque commands no longer use the current sense resistors for feedback. Instead, they use the calibrated phase resistance of the motor to derive what voltage would be necessary to achieve a given torque.
The downsides of this approach are that there are many factors that will make the mechanical output torque not match what was intended. For instance, the back EMF if the motor is moving at non-zero velocity, changes in the winding resistance due to temperature, or inductive coupling between the quadrature frames at non-zero velocity. All of these factors will reduce the accuracy of the torque command, so that the mechanical torque output will not match what was commanded. However, for many applications, the motor is not spinning quickly and precise torque control is not required.
Since this control mode takes effect only at the end of the normal moteus control loop, it means that all of the “position” mode control works as before. Thus the constant velocity mode, stop position, and the “within” mode can all be used without regard to whether the controlled motor is running in the normal “current mode control” mode, or in the new “voltage mode control”.
With the new moteus_tool calibration mechanism, this means that gimbal motors can be used in a basic fashion out of the box with moteus by tweaking only a single configurable value: servo.voltage_control_mode. Here’s a video showing how that works with a real motor.
The initial implementation of auxiliary encoders for moteus supported exactly one encoder, the AS5048B. The hardware can support any I2C based encoder, so supporting additional encoders has always been on the TODO list.
I’m excited to announce, that as of firmware release 2021-12-03, AS5600 encoders are now supported as well. They are a lot cheaper than the AS5048 as they have a much lower update rate and resolution, but that isn’t necessarily a problem if it is only used to disambiguate a modest gear reduction.
To use the moteus brushless controller with a motor, you first have to calibrate it with moteus_tool (for history, see “Encoder autocalibration” and “Auto-tuning current control loops“). This calibration process is primarily used to measure the mapping between electrical phases and the encoder, but as a secondary parameters also measures the winding resistance and Kv of the motor and determines the parameters necessary to set the current control bandwidth.
To date, this process can be used with any motor, but making it work can involve fiddling with a number of inscrutably named command line parameters to moteus_tool. --cal-power, --cal-voltage, and --cal-speed are all there, however they don’t really do what you think based on their name, but it is necessary to adjust them to make many motors work.
I went to address this and make the calibration process more robust across a range of motor types, from small high speed motors, to large low Kv ones, high winding resistance, and low winding resistance. All of these can now be handled with mostly no additional options required.
The new process
In the new world, with no additional options, moteus_tool gradually eases up the voltage applied when measuring resistance and when measuring speed, so that it can be safely used with many motors with no additional tweaks. The power expended in the windings is limited to roughly 5W, which is about the only remaining necessary configurable parameter. You’d only need to change that for a very small motor for which 5W would unnecessarily heat it up.
The existing parameters all get new names which more precisely describe what they do. You rarely need to specify any of them anymore, but you can if for some reason you don’t want to trust the auto-detection mechanism.
What it does?
The voltage used when spinning the motor open loop for encoder calibration.
Speed in electrical revolutions per second when spinning the motor open loop for encoder calibration.
The voltage used when measuring the winding resistance.
The voltage used when measuring the Kv parameter.
This new parameter controls how much power is dissipated in the windings when performing the encoder and inductance calibration with a default of 5W.
This new parameter controls how fast the motor is spun when measuring Kv with a default of 6Hz.
The old parameter names will continue to work for now and just emit a deprecation warning. Even so, the new parameters should now only very rarely be needed, as every motor I have tested works fine without specifying anything at all.
How to get it?
Just update your moteus python package to at least 0.3.30 and you’ll get all the new features in moteus_tool!
It is just a Teensy 4.0 I had lying around, together with an audio board, a basic lav mic, and a spare 74XX245 from my grab bag held together with hot glue and proto wire. It drives a cheapo 300 LED RGB strip that is VHB’d to the bell. I think the LEDs will only last a few more transport sessions, but with any luck I’ll make a slightly more polished revision with better longevity in the not too distant future.
This is a series, check out the previous posts at part 1, part 2, or part 3. This time, I’m going to make this probe hopefully do something.
I started out just verifying that the Pocket NC would treat the vers.by probe the same as the built in tool setter probe. So I ran a tool measure cycle, and then just tweaked the probe by hand. Woohoo! It stopped the cycle just like normal. Actually measuring a tool worked too if the probe wasn’t activated, or if it wasn’t plugged in. Success.
Next, I got a crash course in G-Code. Mostly I used the Linux CNC reference, since that is what the Pocket NC used and all I needed to be interoperable with. Having done no real manual G-Code programming before aside from my limited python auto-generation, I was I guess surprised that there was any real support for in-program scripting. The fun limitations:
Variables can either be “numbered” or “named”. 30 of the “numbered” variables are function local, (and are also necessary for argument passing), and all the remainder are global variables. “named” variables can be global or function local.
All control flow requires human assigned unique integers for each instance of that control flow construct. i.e., an “if-else-endif” chain requires a human assigned integer that is unique script wide to be applied to the if, and its matching elses and end-if statements.
Largely, subroutines need to be in a file by themselves, and all in the same directory.
Annoyingly, expression grouping is with square braces “”, not parentheses, “()”.
“comments” are overloaded to also be used for all “non-machine” operations. If you want a comment to actually be a comment, the best and seemingly standard way is to ensure all comments are prefixed with a space.
Some things can be indirected natively, but not for instance, “which axis to move”. That must be specified using a literal character in each command.
The first probing function I needed was to reference the outer diameter of a cylindrical feature. I started by writing a subroutine which would perform a single linear probe in a parameterizable axis. It first probes quickly, then backs off a bit to probe again slowly. To work around the lack of axis indirection, it just uses if-else chains to handle the X, Y, and Z axes.
Next, I used that in an cylindrical feature probing script, where you manually position the probe along one of the major axes at the proper Z probing depth, assuming that the feature is “roughly” at the center of the current coordinate system. It would then probe all 4 axes, finally setting the coordinate system 0, 0 to be the center of the feature. For this, I “simulated” some arrays using the 30 numbered function local variables so that the probing logic could be implemented in a loop.
This did the trick, and now I could reference cylindrical (and square) features using G54.
I ran this around 30 times over the course of a few hours, including remounting the probe a few times and changing the temperature and airflow to get an idea of the repeatability of the probing process.
Peak to Peak
So, roughly around 1 thousandth or 0.02mm of absolute repeatability. I might be able to improve that by tweaking the probing speed or otherwise adjusting parameters, but the Pocket NC itself isn’t a whole lot better so it should be “good enough” for now.
This project is at a functional point for myself, but isn’t quite ready for others to use. The biggest issue is the necessary modifications to the shaft of the vers.by probe, as they aren’t easy to do and require additional equipment. The other pieces also still have some rough edges that should be filed off, including keeping chips out of the RJ45 connectors and getting a PCB in that doesn’t require bodge wires to work.
I also intend to do a little work to demonstrate that the probing can be used to register features across operations properly.
My eventual goal is to eventually get the design to a state where it is nearly “off the shelf” and list it on tindie. To do that will depend upon if I can figure out a better solution for the probe shaft.
In part 1 and part 2, I covered my motivation and the mechanical hardware behind a touch probe add-on for my Pocket NC V2-50. In this post, I’ll cover my prototype electrical hardware.
My intention with the probe was to connect it logically “in parallel” with the existing tool setter probe that the Pocket NC has. I figured that would be likely easiest to integrate with the Linux CNC scripts when I got to the software point. The existing tool setter probe is located in the rotating B axis. That is connected to the Y axis via a single CAT5-ish cable, so my hope was that I could devise something which would pass through the necessary signals on that cable while also paralleling in the new touch probe.
Using a multimeter to probe around, it was pretty obvious the first 4 pins went directly to the B axis stepper motor. Of the remaining, 5 was pretty obviously ground. Slightly confusingly, the one that had 3.3V on it appeared to be a pullup for the open-drain normally open tool setter, while the pin with 2.8V on it was the power for tool setter and the B axis hall effect homing sensor. The one remaining pin was the output of the B axis homing sensor.
There were a few electrical challenges here. The first was that the vers.by probe needs 5V, not 2.8V. To begin with, I just wired in 4 AA batteries, and for a longer term solution I picked up a 5V charge doubler from digikey, the TPS60241.
The second required a fair amount of thought: how to make the normally closed vers.by probe act “in parallel” to the built in tool setter, while still being able to disconnect the probe and maintain tool setter functionality. Just inverting the normally closed signal would result in something that made the tool setter appear to be always activated whenever the touch probe was disconnected.
Here, I relied on a design artifact of the vers.by probe. The “USB cable” connector had both D- and D+ connected together, but in the probe itself. So if the probe or cable were disconnected, those two nets would have no connection. Thus I pulled one high, and pulled one low. Then the three states I cared about looked like:
Probe Connected and Inactivated
Probe Connected and Activated
I used a 74HC series NAND gate to only activate a parallel N-FET in that final case, where the probe is connected and activated.
I breadboarded this with the 4 AA batteries, then did a proto-board implementation that used the 5V charge pump too. I was going to use the same SMT components on the proto-board implementation, but the NAND gates, despite being labeled as the same 8VSSOP package as the charge pump, and both from TI, turned out to be a package that was too small for me to “dead bug” solder. So, instead I just flipped over the DIP package NAND I had and wired that up.
Then using some cardboard, hot glue, and a zip tie, I fastened it to the back of the A axis stepper motor on the Pocket NC:
Before I was able to really test this well, a PCB from OSHPark came in, so I used that with a 3D printed enclosure:
Last time in part 1, I talked about why I wanted to add a touch probe to my Pocket NC. This time, I’ll cover the basic hardware necessary to make it happen.
I decided to start with an inexpensive probe so that as I was figuring things out, I wouldn’t be too sad if I smashed it a few times. I’ve seen a number of other hobby machinists use the “vers.by” probes, so I decided to give them a try too.
This probe requires 5V-24V power, has a 6mm shank, and provides a NPN-NC output with a USB connector as the physical connector. Note, it isn’t USB, but just uses that connector for power and the signal.
To start with, I needed to get the probe such that I could mount it in the spindle of the Pocket NC. The V2-50 I have can handle a 4mm shank at most, and that is what I primarily use. Obviously, 6mm is bigger than 4mm, so something needed to be done.
So, I wouldn’t be a quality engineer if I didn’t have the brand new toy disassembled within hours of receiving it:
What I ended up doing was turning down the 6mm shaft to 4mm on one of the Artisan Asylum’s manual lathes.
This was pretty challenging. First because the shaft was already permanently mounted into that relatively thin base section, so getting the part trued up in the chuck took some time. Second, because it sticks out so far, I could only take excruciatingly light cuts. In hindsight, I should have worked harder to get the opposite side supported. The entire operation took something like 3 hours. However, when done, I had a probe with a 4mm shaft!
And hey, it fits!
After a bit of tuning with my 2 micron dial indicator, and the provided adjustment screws, it seems to pretty dialed in.