Archives: Development

Low cost off axis encoders for moteus - a beginning

The moteus line of brushless controllers all have an integrated “on-axis” magnetic encoder. These encoders are designed to allow moteus to sense the position of a motor’s shaft directly, assuming that an appropriate diametrically magnetized sense magnet is attached to the rotating shaft and the moteus is mounted so that its sensor is positioned over the magnet.

This works great for many applications, but what about hollow shaft motors? moteus supports a few encoder types that will work for off axis encoders, most notably is the AksIM-2. This is a high performance off-axis encoder that gives great performance and is manufactured in configurations for a variety of hollow shaft diameters. However, it does have downsides. First, it comes with a commensurate price tag. In single quantities, the AksIM-2 and magnetic code disc are more expensive than an entire moteus brushless motor controller. Second, only the moteus-n1 has the necessary RS422 transceiver integrated into it. All other moteus boards need an external RS422 transceiver.

callgrind profiling of embedded targets

When performing optimization or micro-optimization on desktop applications, callgrind combined with kcachegrind are one of my favorite combinations. While slow to run, it gives you precise information about where instructions are spent and has at least a decent way of moving up and down the call frame or digging into disassembly. The downside, is that it largely only works if you can run the application on your host processor, which isn’t that relevant when working with embedded targets like STM32 (or other) microcontrollers. Recently, I got fed up trying to find more cycles to shave off the moteus firmware, and decided to take a stab at making at least a minimal solution.

Optimizing moteus command rate

Probably one of the most frequently asked questions in the mjbots Discord is “how fast can I send new commands to moteus”, or “how fast can I read the status from moteus”. That may be because you want to perform torque based control in your application and require high bandwidth, or just because you have a high torque to inertia ratio system that reacts on very short time-scales. No matter the reason, the principles that control the maximum rate you can send updates are the same.

Default bandwidths for moteus

moteus has long had both automatically tuned current control bandwidth and a built-in low-pass filter for encoder readings. During calibration, these are usually set with moteus_tool’s --cal-bw-hz option, which specifies the current loop (interchangeably called the torque loop) bandwidth. TLDR is that these heuristics have changed as of pypi 0.3.64, hopefully with only improved behavior. Read on if you want to understand more or if you need to resolve problems with something that changed for the worse.

Forbidding stop_position with acceleration limits

When the moteus acceleration and velocity limits were first announced more than a year ago, it was noted that the semantics of using the legacy “stop_position” along with the new acceleration and velocity limits was “not particularly useful”. In the meantime, I’ve seen many cases where people get tripped up by this, even more so since developer kits now come with velocity and acceleration limits configured.

To mitigate that, as of firmware release 2023-09-26, moteus will now fault with code 44 if you attempt to use a stop_position while acceleration or velocity limits are configured. Here’s a quick reminder on how to upgrade:

STM32G4 ADC performance part 2

Back last year, I walked through bisecting and debugging an annoying problem that caused the STM32G4 ADC on the moteus controller to exhibit higher than expected noise in result largely to either the exact placement in flash of the initialization code, or to the exact timing of the initialization. While the immediate glaring sharp edge was removed, the resulting performance still was confusing to me, and looked like it was not yet optimal. Further, a moderate percentage (2% or so), of production boards failed end-of-line tests related to the current sense noise in ways that were hard to fix by swapping components. Because of this, I wanted to dive in and investigate further. This is that process.

5 Side PCB Test Fixture

If you look around online, there are lots of examples of PCB test fixtures used to perform end of line testing. In the low to medium volume scale, nearly all of these are either clamshell or 2 side affairs, where probe pogo pins or interfaces are connected to the bottom and top of the board.

When developing the moteus-n1, one of the challenges was the number of right angle board edge connectors it has. Those right angle connectors are what allow it to maintain a very low overall stack height when installed in applications, but are also much harder to perform testing on, since by definition the access points are not vertical. On the base n1, there are 6 total right angle connectors, 2 on each of 3 sides, and future variants may have additional bottom side CAN and power connectors populated to make 8 total right angle connectors.

moteus external connector pin selection

moteus r4.11 has two external connectors, the ABS connector (AUX2) and the ENC/AUX1 connector. The ABS connector was designed initially just to have 2 I2C pins. The ENC connector just has the random pins that were used for the onboard encoder SPI plus one more. Thus the range of external accessories that can be connected is somewhat haphazard and not necessarily all that useful.

When working on a more ground up revision of the controller, I wanted to improve that situation to expose more connectivity options on still a relatively limited connector set. The idea was to use 2 connectors, one which has 5 I/O pins and the other with 4 I/O pins. The onboard encoder SPI would still be accessible on the larger connector to use for at least one external SPI encoder, but how much other functionality could be crammed into the remaining pins? To start, lets see what possible options there are in the current firmware and supported by the STM32G4 microcontroller that moteus uses:

Resistive heater dummy load

While testing moteus controllers, it is often necessary to experiment with high power conditions. For short durations, any decent sized brushless motor can work, as the windings have a non-zero thermal mass and take a little bit to warm up. However, when testing at high power for extended duration, it can be hard to find a way to get rid of all output energy. Even blowing a fan directly onto a motor only gets you so far when you are trying to get rid of 1kW.

Debugging bare-metal STM32 from the seventh level of hell

Here’s a not-so-brief story about troubleshooting a problem that was at times vexing, impossible, incredibly challenging, frustrating, and all around just a terrible time with the bare-metal STM32G4 firmware for the moteus brushless motor controller.

Background

First, some things for context:

moteus has a variety of testing done on every firmware release. There are unit tests that run with pieces of the firmware compiled to run in a host environment. There is a hardware-in-the-loop dynamometer test fixture that is used to run a separate battery of tests. There is also an end-of-line test fixture that is used to run tests on every board and some other firmware level performance tests.