Need for (microcontroller) speed

A project log for Dextra

Open-source myoelectric hand prosthesis

Alvaro VillosladaAlvaro Villoslada 10/01/2016 at 17:430 Comments

Why did I chose a Teensy 3.1 as the "brains" of Dextra? At the beginning of the project, when the fingers were open-loop controlled, I used an Arduino Uno to send the motion commands to the motor drivers. Once I had the mechanical design of the hand more or less finished, I decided that it was time to start working on closing the control loop.

Since the fingers are underactuated, it didn't make much sense to put one angular sensor for each joint of the finger, as they cannot be independently controlled. So I thought that to close the control loop, I just needed to know the total linear displacement of the finger tendon. Instead of using a linear sensor, which would take a lot of space, I decided to measure the angular displacement (in radians) of the motor shaft with an encoder and transform this quantity into a linear displacement by multiplying it by the radius of the spool that winds and unwinds the tendon.

Pololu sells small quadrature magnetic encoders for their micro motors, that can be directly soldered to the motor power pins, so choosing the sensor was easy. After researching how quadrature encoders work, and how to implement them with an Arduino (I have never worked with encoders before), I realized that I needed a microcontroller with at least five external pin interrupts (a quadrature encoder can use one or two interrupts, depending on if you want to have half or full resolution). An Arduino Uno only has two pin interrupts, so I took an Arduino Mega I had lying around and started developing the control firmware.

After adjusting the PID gains and tweaking the code here and there, the first tests, where I moved only one finger at a time, went very well. But as soon as I started moving several fingers at the same time, the hand started to operate worse. After a few closing-opening cycles, some fingers closed more than commanded and others opened more than they should. To make an analogy with stepper motors, it was as if the motors were losing steps.

To better understand what was going on, I will explain how the finger controller works (it is very simple actually). Basically it consists of two elements: the encoder counter and the actual control function. Every time one of the encoders generates a pulse, a function that increments or decrements the number of encoder "ticks" is executed. This is the only thing that this function does, to reduce its computational cost so it runs as fast as possible. The conversion from the number of encoder "ticks" to the linear displacement of the tendon is done in the PID function. The five PID loops that control the five fingers of Dextra are executed sequentially, from the thumb to the little finger, every 10 ms inside a timer interrupt (using the fantastic MsTimer2 library).

So, what do we have here? A lot of interrupts. Being a timer interrupt, I know when the controller interrupt runs, but there is no way of knowing when the encoder interrupts are going to execute, or if they are blocking each other. Going back to the problem I had with the fingers not moving as they were commanded, I assumed that what was happening was that sometimes, for some fingers, the function that counts the pulses of the encoders was not executed. I thought this was happening because the speed of the microcontroller was not enough to run a counting function before the interrupt of another encoder was fired. My reasoning was as follows: if while the counting function of a finger is running the encoder of another finger triggers its interruption, the counting function of the second finger will not run because the counting function of the first finger is still running, and thus, the motor of the second finger will skip a pulse while it is moving, causing the finger to close or open more than it should.

With that reasoning in mind, I switched to a Teensy 3.1 which has enough pin interrupts for my purposes, runs at 72 MHz (96 MHz if overclocked) and is Arduino-compatible. After making some small changes to the code and connecting everything, I started a closing-opening cycle test. After half an hour running, the fingers were still closing and opening as commanded, so it seemed I was right and I simply needed more microcontroller speed.