Tuesday, September 7, 2010

MIDI For Your Motor

 Might as well start off with the good part...before launching into a post about how much I hate programming. 

What's going on there? Well, it's what I said it would be: a functional brushless motor controller that plays three tracks of MIDI music while it's doing its normal motor controller routine. In other words, it can still control the speed and/or torque of the motor independently of the music being played. So, not exactly the same as some other music motors like the classic[al] scanner or these musical steppers. It uses the PWM frequency, not the mechanical frequency, to play notes. And since there are three phases to play with on a brushless motor, it can play three tracks on one motor.

Before last week, I had taken care of what I thought to be the two hardest parts of making a motor controller that plays MIDI files. Namely, the motor controller part, and the MIDI part. Without too much trouble, I ported the 3ph Duo controller code over to the STM32F103 and found plenty of left-over processing power [to squander on processing MIDI]. Also without too much trouble I wrote a MIDI file parser in Visual Basic (shut up) and even wrote a rudimentary visualizer so I could see the notes.

Then I got to the part where I needed to send the MIDI data to the motor controller. So began the epic combo of mechanical, electrical, and software problems that tied me up for a week. First, the stupid USB connector on the board stopped connecting.

Stupid USB connector.

Then, the stupid XBees from 2006 with firmware/malware version 10C0 stopped responding to commands altogether.

 Stupid 10C0 XBees.

Basically, with both of my communication channels nonfunctional, I had no way of even programming the motor controller, let alone sending it MIDI data. So I did the MechE thing and procured all new USB connectors and XBees. The XBees were easy to change. The connector, since I am averse to using the heat gun, involved some brute force desoldering, but ultimately gave way.

Hardware problems really can't stop me in my tracks, though. At least, not any longer than Digi-Key's two-day shipping. Cue total software meltdown. Here's the problem: I can't buffer the entire MIDI song on the STM32F103C4. It's only got 16KB of flash. Each note requires at least 3 bytes of data, one for the note number and two for the time stamp. And the Top Gear theme song, in particular, has thousands of notes per track. So I needed a clean way to send pieces of the song from my Visual Basic MIDI parser to the controller.

The first attempt was a 16-note buffer. Transmitting at 57.6kbps, with 3 tracks of 16 notes, 3 bytes per note, and 8 bits per byte, plus extra bytes for checksums and the actual motor control stuff, this should finish in about 30ms. The problem is, the buffer is filled asynchronously while notes are still being played. (Everything is event-driven, if you're an OS programmer, or interrupt-driven, if you're an embedded programmer.) So, I needed a clean way of making sure that while notes are being filled in, they don't interfere with the ones being played (and vice versa). I tried a system of double buffers and locks that I thought was clever, but no matter what, I kept running into problems of skipping notes or playing notes ahead of their timestamp in groups of 2-5, depending on the MIDI tempo.

After two days of that, I scrapped the entire buffer system and wrote a new one from scratch in 30 minutes. The key realization was that, while I was somewhat limited to 16-note transmissions by the XBee speed, my buffer could in fact be larger... So, I made a 32-note buffer and just insert the 16 transmitted notes 16 places ahead of the note being played. Thus, they never overlap. (If they do, it means a bunch of packets have been dropped or the guitar solo is a just a little too aggressive.) On a scale of programming nightmares, this is nothing compared to the 3ph Duo, but it was a bit frustrating.

Next: Bigger motor. (Don't you know me by now?!)

1 comment:

  1. I had a good laugh with this one. No idea how you're still doing all the fancy FOC control while modulating the PWM frequency?!? That is one heck of a trick!!