The scariest part of Halloween is failure.
So last week I gave myself a one day project to create a motor driven-device that would drop a spider on unsuspecting trick-or-treaters whenever the sensor detected them.
I gave myself only the day of Halloween itself Saturday, the 31st. Knowing that if I started the project on Wednesday, it would take Wednesday, Thursday, Friday, and Saturday to finish.
What does the project consist of?
- Two 3D printed parts, a pulley and a bracket to hold the motor.
- A 12V, 78:1 gearmotor with encoder, scavenged from an old school project.
- A Pololu 8384 motor driver board
- An ESP32
- A VL530LX Range Finder
To start the day off, I assembled the motor driver first, which was quick, since I had already soldered the header pins to the daughterboard.
The operation is relatively straightforward. Two pins, drive the motor driver forward and/or backward.
Only seven pins are needed to operate the board with one motor
- Logic power
- Motor power
- Ground
- Motor A forward (input)
- Motor A reverse (input)
- Motor A + (output)
- Motor A - (output)
To connect the encoder, I had to connect encoder power and ground to logic power and ground as well as connect to sensor signals to the microcontroller.
The range sensor worked pretty much out of the box with libraries that I found for MicroPython and ESP32. It required only four connections: power, ground, SCL and SDA.
Putting the code together for this project was quick and easy. I wrote a script that did the following things:
Motor waits at its starting point until it senses an object that is blocking its path. Motor rotates 500 counts in one direction Motor dwells at that position for two seconds. Motor rotates 500 counts in the other direction. The microcontroller loop begins again and it checks the distance sensor for a new obstacle in its path.
To make this possible, I used the pin interrupt function in MicroPython, which is under-documented.
Failure
The code is simple, the devices are simple, and yet the motor would not repeatedly rotate in one direction the same amount that it rotated in the other. Why? My encoder counts were off.
Apparently, Micropython's implementation of interrupts is heavily dependent on the hardware that it's connected to. The ESP32 port of micropython only supports "soft" interrupts. Micropython's overhead also makes it impossible for interrupt code to run quickly enough -- even following its best practices -- such another encoder transition will come before the last function is finished executing.
The fix
I didn't get my project finished before Halloween. Next year, I will be working in either Rust or C, to ensure that I have low-level access to device I/O that is fast enough to keep up with the devices that I'm using.
This doesn't come without a cost, however. MicroPython is super convenient for prototyping because of its vast trove of libraries that work out of the box and with little extra programming effort. migrating to C or Rust will require a lot more integration between libraries, and extra functionality that I want to tack on will come at a much higher cost.
The motor goes up a different number of counts than it goes down. I suspect performing other hardware functions in micropython have the effect of blocking the interrupt from running quickly
The first reason is that my leads are very long.