SnekBoard and Lego

I was hoping to use some existing boards for snek+Lego, but I haven't found anything that can control 9V motors. So, I designed SnekBoard.

(click on the picture to watch the demo in motion!)

Here's the code:

def setservo(v):
    if v < 0: setleft(); v = -v
    else: setright()

def track(sensor,motor):
    while True:
        setservo(read(sensor) * 2 - 1)

track(ANALOG1, MOTOR2)

SnekBoard Hardware

SnekBoard is made from:

  1. SAMD21G18A processor. This is the same chip found in many Arduino boards, including some from Adafruit. It's a ARM Cortex M0 with 256kB of flash and 32kB of RAM.

  2. Lithium Polymer battery. This uses the same connector found on batteries made by SparkFun and Adafruit. There's a battery charger on the board powered from USB so it will always be charging when connected to the computer.

  3. 9V boost power supply. Lego motors for the last many years have run on 9V. Instead of using 9V worth of batteries, using a boost regulator means the board can run off a single cell LiPo.

  4. Four motor controllers for Lego motors and servos. The current boards use a TI DRV9938, which provides up to 1.5A.

  5. Two NeoPixels

  6. Eight GPIOs with 3.3V and GND available for each one.

  7. One blue LED.

Getting SnekBoard Built

The SnekBoard PCBs arrived from OshPark a few days ago and I got them assembled and running. OshPark now has an associated stencil service, and I took advantage of that to get a stainless stencil along with the boards. The DRV8838 chips have small enough pads enough that my home-cut stencils don't work reliably, so having a 'real' stencil really helps. I ordered a 4mil stencil, which was probably too thick. They offer 3mil, and I think that would have reduced some of the bridging I got from having too much paste on the board.

Flashing a Bootloader on SnekBoard

I forked the Adafruit UF2 boot loader and added definitions for this board. The version of GCC provided in Debian appears to generate larger code than the newest upstream version, so I wasn't able to add the NeoPixel support, but the boot loader is happy enough to use the blue LED to indicate status.

STLink V2 vs SAMD21

I've got an STLink V2 SWD dongle which I use on all of my Arm boards for debugging. It appears that this device has a limitation in how it can access memory on the target; it can either use 8-bit or 32-bit accesses, but not 16-bit. That's usually just fine, but there's one register in the flash memory controller on the SAMD21 which requires atomic 16-bit accesses.

The STLinkV2 driver for OpenOCD emulates 16-bit accesses using two 8-bit accesses, causing all flash operations to fail. Fixing this was pretty simple, the 2 bytes following the relevant register aren't used, so I switched the 16-bit access to a 32-bit access. That solved the problem and I was able to flash the bootloader. I've submitted an OpenOCD patch including this upstream and pushed the OpenOCD fork to github.

Snek on the SnekBoard

Snek already supports the target processor; all that was needed for this port was to describe the GPIOs and configure the clocks. This port is on the master branch of the snek repository.

All of the hardware appears to work correctly, except that I haven't tested the 16MHz crystal which I plan to use for a more precise time source.

SnekBoard and Lego Motors

You can see a nice description of pretty much every motor Lego has ever made on Philo's web site. I've got a small selection of them, including:

  1. Electric Technic Mini-Motor 9v (71427)
  2. Power Functions Medium motor (8883)
  3. Power Functions Large motor (88003)
  4. Power Functions XL motor (8882)
  5. Power Functions Servo Motor 88004

In testing, all of them except the Power Functions Medium motor work great. That motor refused to start and just sat on the bench whinging (at about 1kHz). Reading through the DRV8838 docs, I discovered that if the motor consumes more than about 2A for more than 1µs, the chip will turn off the output, wait 1ms and try again.

So I hooked the board up to my oscilloscope and took a look and here's what I saw:

The upper trace is the 9V rail, which looks solid. The lower trace is the motor control output. At 500µs/div, you can see that it's cycling every 1ms, just like the chip docs say it will do in over current situations.

I zoomed in to the very start of one of the cycles and saw this:

This one is scaled to 500ns/div, and you can see that the power is high for a bit more than 1µs, and then goes a bit wild before turning off.

So the Medium motor draws so much current at startup that the DRV8838 turns it off, waits 1ms and tries again. Hence the 1kHz whine heard from the motor.

I tried to measure the current going into the motor with my DVM, but when I did that, just the tiny additional resistance from the DVM caused the motor to start working (!).

Swapping out the Motor Controller

I spent a bunch of time looking for a replacement motor controller; the SnekBoard is a bit special as I want a motor controller that takes direction and PWM instead of PWM1/PWM2, which is what you usually find on an H-bridge set. The PWM1/PWM2 mode is both simpler and more flexible as it allows both brake and coast modes, but it requires two PWM outputs from the SoC for each controller. I found the DRV8876, which provides 3.5A of current instead of 1.5A. That "should" be plenty for even the Medium motor.

Future Plans

I'll get new boards made and loaded to make sure the updated motor controller works. After that, I'll probably build half a dozen or so in time for class this October. I'm wondering if other people would like some of these boards, and if so, how I should go about making them available. Suggestions welcome!