Tag Archives: stm32

Spread spectrum integration

I’ve been developing a new bi-directional spread spectrum radio to command and control the mjbots quad robot.  Here I’ll describe my first integration of the protocol into the robot.

To complete that integration, I took the library I had designed for the nrfusb, and ported it to run on the auxiliary controller of the pi3 hat.  This controller also controls the IMU and an auxiliary CAN-FD bus.  It is connected to one of the SPI buses on the raspberry pi.  Here, it was just a matter of exposing an appropriate SPI protocol that would allow the raspberry pi to receive and transmit packets.

Slightly unfortunately, this version of the pi3hat does not have interrupt lines for any of the stm32s.  Thus, I created a multiplexed status register that the rpi can use to check which of the CAN, IMU, or RF has data pending.  Then I slapped together a few registers which allowed configuring the ID and reading and writing slots and their priorities.

Then I refactored things around on the raspberry pi side so that one core would keep busy polling for one of those things to become available.  So far, for the things which access SPI, I’ve been putting them locked to an isolcpu cpu to get improved SPI timing.  Eventually, once I have interrupt lines, I might consolidate all of these down to a single core.  That, plus defining an initial mapping between the controls and slots resulted in:

Finally, I created a very simple GL gui application which connects to an nrfusb and a joystick.  It uses Dear ImGui to render a few widgets and glfw to window and read the joystick.

2020-04-03-145917_1280x720_scrot

While I was at it, I finally updated my joystick UI to make gait selection a bit faster, and got the robot to do a better job of switching out of the walk gait.  Thus the following video showing all of that hooked together.

Spread spectrum implementation

With a protocol design in hand, the next step was to go and implement it.  My goal was to produce a library which would work on the nrfusb, and also on the auxiliary stm32g4 on the mjbots pi3 hat.  In this first implementation pass however, I only worked with the nrfusb as both transmitter and receiver.

While developing this, I had more than my share of “huh” moments working from the datasheet and with the components.  To begin with, the initial nrf24l01+ modules I got were all Chinese clone ones.  While I was having problems getting auto acknowledgement to work, I discovered that the clones at a minimum were not compatible with genuine Nordic devices.  Thus I reworked genuine parts into the modules I had:

dsc_0376

dsc_0375
A Nordic clone about to be removed

That didn’t solve any of my immediate problems, but the subsequent modules I got all had genuine chips so it was useful that they all were compatible.

The other more annoying problems are somewhat obvious in hindsight.  For a transmitter to be able to successfully receive an automatic acknowledgment from a receiver, not only does the ID need to be configured in the appropriate RX_ADDR register, but EN_RXADDR also needs to have the correct bit set.  I had assumed that was only required for slave devices as there was no mention of it in any of the Enhanced Shockburst flow charts or setup procedures for transmitters or auto acknowledgment.

The second annoyance, was that when in receiver mode, switching channels seems to kinda work a little bit for some channels even with CE held high, but to be reliable you have to pull CE low and put the unit in standby mode while changing channels.

With those problems (and some others) resolved, I have a reliable bidirectional link that is ultimately tweakable.  Next I’ll integrate this into the quad A1 to actually control the robot and monitor its telemetry.

 

Power distribution board r3

While I was able to make the r2 power distribution board work, it did require quite a bit more than my usual number of blue wires and careful trace cutting.

dsc_0394

Thus I spun a new revision r3, basically just to fix all the blue wires so that I could have some spares without having to worry about the robustness of my hot glue.  While I was at it, I updated the logo:

dsc_0393

As seems to be the way of things, a few days after I sent this board off to be manufactured, I realized that the CAN port needed to actually be isolated, since when the switches are off, the ground is disconnected from the rest of the system.  Sigh.  Guess that will wait for r4.

Here is r3 all wired up into the chassis:

dsc_0395

 

Bringing up CAN on the quad pi3 hat

After getting the power to work, the next step in bringing up the new quad’s raspberry pi interface board is getting the FDCAN ports to work.  As described in my last roadmap, this board has multiple independent FDCAN buses.  There are 2 STM32G4’s each with 2 FDCAN buses so that every leg gets a separate bus.  There is a 5th auxiliary bus for any other peripherals driven from a third STM32G4.  All 3 of the STM32G4’s communicate with the raspberry pi as SPI slaves.

Making this work was straightforward, if tedious.  I designed a simple SPI based protocol that would allow transmission and receipt of FD-CAN frames at a high rate in a relatively efficient manner, then implemented that on the STM32s.  On the raspberry pi side I initially used the linux kernel driver, but found that it didn’t give sufficient control over hold times during the transmission.  Since the SPI slave is implemented in software, I needed to leave sufficient time after asserting the chip select and after transmitting the address bytes.  The kernel driver gives no control over this at all, so I resorted to directly manipulating the BCM2837s peripheral registers and busy loop waiting in a real time thread.

dsc_0347
A lot of scope probes!

After a decent supply of bugs were squashed, I got to a point where the host could send off 12 queries to all the servos with the four buses all being used simultaneously, then collating the responses back.  I haven’t spent much time optimizing the cycle time, but the initial go around is at around 1.0ms for a query of all 12 devices which is about 1/3 of the 3.5ms I had in the previous single-bus RS485 version.

20200226-leg-transaction

Here’s a scope trace of a full query cycle with 2 of the 4 CAN buses on the top, and the two chip selects on the bottom.  Woohoo!

Bringing up the IMU on the pi3 hat

The next peripheral to get working on the quad’s raspberry pi interface board is the IMU. When operating, the IMU will primarily be used to determine attitude and angular pitch and roll rates.  Secondarily, it will determine yaw rate, although there is no provision within the IMU to determine absolute yaw.

To accomplish this, the board has a BMI088 6 axis accelerometer and gyroscope attached via SPI to the auxiliary STM32G4 along with discrete connections for interrupts.  This chip has 16 bit resolution for both sensors, decent claimed noise characteristics, and supposedly the ability to better reject high frequency vibrations as seen in robotic applications.  I am currently running the gyroscope at 1kHz, and the accelerometer at 800Hz.  The IMU is driven off the gyroscope, with the accelerometer sampled whenever the gyroscope has new data available.

My first step was just to read out the 6 axis values at full rate to measure the static performance characteristics.  After doing that overnight, I got the following Allan Variance plot.

20200304-bmi088-allan-variance

That gives the angular random walk at around 0.016 dps / sqrt(Hz) with a bias stability of around 6.5 deg/hr.  The angular random walk is about what is specified in the datasheet, and the bias is not specified at all, but this seems really good for a MEMS sensor.  In fact, it is good enough I could probably just barely gyrocompass, measuring the earth’s rotation, with a little patience.  The accelerometer values are shown there too, and seem fine, but aren’t all that critical.

Next up is turning this data into an attitude and rate estimate.

fdcanusb up at mjbots.com

I’ve received my first production run of the fdcanusb CAN-FD USB adapters and they are up for sale at mjbots.com!

fdcanusb_angle

While this is necessary for interacting with the moteus controller, it is also a fine general purpose CAN-FD adapter.  At the moment, the USB interface is a platform independent line based serial one (Windows, Linux, MacOS).  It doesn’t yet interoperate with SocketCAN on linux, but hopefully that will be resolved in the not too distant future.

New quad power distribution board

Finally returning back to other pieces of my quad roadmap, I finished getting an updated power distribution board ready for the quad A0.  This board is one I had made many months ago and mostly brought up, but then didn’t quite finish.  The r1 was when I first discovered my unfortunate stm32g4 pinout problems that doomed 3 of my in flight boards.  The pictures here are of r2, which suffered from yet more pinout problems, resulting in more than my usual number of blue wires.  Fortunately, identifying those problems here let me fix them ahead of time for the fdcanusb and moteus r4 boards.

dsc_0193

This version has a probably overkill XT90 input connector, 6x XT30 output connectors, a connector for a lighted toggle switch and an FD-CAN port.  The CAN port will eventually allow me to implement a soft power off, although I haven’t done that yet.

When hooked up to a moteus dev kit, it does do the proper pre-charging thing:

dsc_019420200131-precharge

CAN bootloader for moteus r4.x

One final piece of porting that needed to happen for the moteus controller r4.x series was the bootloader.  The r3.x series has a bootloader, which allowed re-flashing the device over the normal data link, but that was largely specific to the RS485 and mjlib/multiplex framing format.  Thus, while not particularly challenging, I needed to update it for the FD-CAN interface used on the r4.x board.

The update itself was straightforward: https://github.com/mjbots/moteus/compare/406f01…1123a9

For now, on the assumption I will in the not too distant future deprecate the r3.x series, just duplicated the entire bootloader, replacing all the communication bits with FDCAN and stm32g4 appropriate pieces.  As before, this bootloader is designed to only operate after the normal firmware has initialized the device, and also is required to be completely standalone.  To make code size easier to manage, it makes no calls to any ST HAL library and manipulates everything it needs purely through the register definitions.

Thankfully, the ST HAL sources are BSD licensed, otherwise I’m not sure I could have gotten the FD-CAN and flash peripherals to work just given the reference manual.  With it, copying out the necessary constants made for an easy solution.

 

Bringing up the fdcanusb

I introduced the fdcanusb previously, now I’ll describe some of the process and challenges in getting it to work.

Hardware

My initial challenges were around the PCB design and manufacturing.  To begin with, my very first revision was sent out for manufacturing with the same incorrect pinout as the moteus controller r4.0 and thus was only really usable as a paperweight.  Second, the supply of STM32G474 chips seems to be spotty now, so for r2 I had to scavenge chips from the boards that had broken pinouts.

The r2 boards did have a DB9 pinout that was not industry standard, this time due to Eagle’s DB9 footprint being broken, but that will be easy enough to fix in r2.1.

Software

The software had three things that needed to work, FDCAN, USB, and the finally all the glue logic.  Getting FDCAN to work was remarkably easy:  I just used the STM HAL APIs and was basically done.

USB was harder.  The last time I made a virtual serial port for the STM32, the mjmech gimbal board, I used the STM provided CDC libraries.  However, those are released only under a rather restrictive license, confusingly named the “Ultimate Liberty Software License Agreement”.  Despite the claims in the title, you actually have very little liberty, in that the software can only be used on STM controllers and has notice provisions as well.  As with the rest of the moteus universe, I wanted to be able to release this firmware under a permissive license so needed to look elsewhere.

Github and google found a number of candidates, and the one that I ended up starting from was dmitrystu/libusb_stm32.  It was already licensed under the Apache 2.0, and supported controllers which looked like they would be very similar to the STM32G4.  Sure enough, the STM32L433 has an identical USB peripheral and was already supported.

I ended up forking that repository into the fdcanusb one and modifying it slightly to be usable with C++ and mbed.  Also, interestingly, the CDC demo used the same endpoint for RX and TX, which the linux drivers didn’t seem to like so I just gave them separate endpoints like I’ve done before.  I then implemented a wrapper for the CDC class which presents the same asynchronous serial interface as everything else in mjbots/mjlib and was set to go.

The final piece of the software was all the glue and application logic.  I just used PersistentConfig and CommandManager from mjlib, which gave a human readable ASCII interface out of the box.  Then I wrote up the application logic in CanManager, which didn’t have to do much at this point.

Next steps

In its current state, the fdcanusb firmware is capable of communicating with the moteus r4.X series controllers just fine.  Next I’ll get a few more made to distribute with moteus development kits and see if there is any more demand for them.

 

fdcanusb

One of the necessary pieces for bringing up the moteus brushless controller and for ongoing development with it is being able to communicate with the device on the desk.  There aren’t many options for desktop FDCAN communication currently, and certainly none that are in the affordable range occupied by the CANUSB family of devices which I’ve used before and was very happy with.  Thus I created “fdcanusb”, a USB to FDCAN converter that allows one to communicate with FDCAN devices via a USB interface using a documented protocol, no drivers necessary.

The notable features:

  • USB 2.0 full speed host interface
  • ISO 11898-1: 2015 FDCAN interface on industry standard DB9 connector
  • Standards compliant bitrates up to 1/5Mbps supported
  • Software controllable termination
  • Frame sizes up to 64 bytes
  • Non-standards compliant bitrates allowed
  • Documented CDC ACM based host protocol (virtual COM port)
  • Apache 2.0 licensed firmware based on the STM32G474 controller

All for an expected sales prices of around $100.

This does come with some caveats: For one there is no galvanic or optoisolation, you get a common mode range of around +- 12V.  Another is that using just a USB 2.0 full speed interface means it may not be able to keep a FDCAN bus fully saturated at high bitrates.  Finally, the firmware will start out with just the bare bones capabilities, but can be extended to support features such as error injection, triggers, buffering, and more compact protocols in the future.

I’ve got the first functioning prototypes of these boards in hand now:

fdcanusb_r2
PCB render
dsc_2026
Set up for test

Next up I’ll describe bringing up this board.