$5 USB MIDI adapter with ATmega32u4

This article will detail how to build a USB MIDI adapter (one-directional: you connect the adapter with USB cable to your computer, and it receives notes and pedal data from your keyboard’s MIDI OUT and transmits them to your computer) with ATmega32u4, 6N137 optocoupler, a few resistors and spare MIDI connector or cable. Read on for details!

Preamble

Last year I wrote how you can turn Teensy LC into an inexpensive USB MIDI adapter. I used it to replace a non-working Chinese MIDI-USB adapter that did not send controller messages (i.e. piano pedal) properly to PC.

However, since the Teensy still costs $12, and you have to get some additional components, it doesn’t make sense to use it in a dedicated MIDI adapter, since you can get a working USB MIDI adapter for around $15 from Thomann and probably many other places.

But how about other boards? After making my Teensy LC adapter, I actually tinkered with Adafruit Pro Trinket, and got that working as well (the standard Trinket does not have hardware UART so V-USB and software UART is somewhat risky). But there is even a better board for this: The ATmega32u4 board I previously showed how it can be made into USB HID mouse. Let’s see how to turn it into a USB MIDI adapter!

Required hardware

To build this, you will need roughly $5.40 worth of components:

  • SparkFun Pro Micro (clones with ATmega32u4 can be had for $3.50 from AliExpress, eBay, etc.)
  • 6N137 optocoupler, which can be had for ~$0.30 a piece (I suggest sourcing a couple in case you burn one by accident)
  • 330 ohm and 2 kohm resistors ($0.10) and 1N4148 diode if you want to be safe
  • MIDI connector or alternatively you can just cut a short cheap MIDI cable and wire it to your project, let’s say $1.50

Continue reading $5 USB MIDI adapter with ATmega32u4

Split MIDI Files with Python

In my previous post I showed how to use Raspberry Pi to automatically record MIDI files from digital piano whenever you turn it on. However, if you sit down and play for an hour, and get one big MIDI file, it is not very useful. So what to do?

Pianoteq has a feature that splits your playing session based on breaks you take between playing notes. So I decided to mimick this feature with a simple Python script that:

  1. Keeps tab on keys and pedals pressed
  2. Whenever X seconds elapse without any keys or pedals down, a new MIDI file is started
  3. Additionally, if user presses and releases sustain pedal several times in the end, filename for that MIDI is altered to “highlight” that file

I first thought to learn enough of MIDI file format to do everything from scratch, but there’s quite a bit of small details to handle, so in the end I decided to use an external toolkit from Craig Stuart Sapp called midifile to do the heavy lifting. You should be able to just clone the Git repo and make it with Raspberry Pi:

pi@raspberrypi:~ $ git clone https://github.com/craigsapp/midifile
pi@raspberrypi:~ $ cd midifile
pi@raspberrypi:~/midifile $ make

You should now have two useful commands in ~/midifile/bin: toascii to read a MIDI file and dump an ASCII (text) version of it, and tobinary to do the reverse. With Python’s Popen and smart piping, we can read and write the binary MIDI files as they were in this text format. You can check out how the format looks like with some MIDI file you have:

~/midifile/bin/toascii somemidi.mid | less

Here’s a sample of a MIDI file recorded by arecordmidi (I added the note in square brackets):

"MThd"
4'6
2'0
2'1
2'384

;;; TRACK 0 ----------------------------------
"MTrk"
4'50044
v0      ff 51 v3 t120
v0      ff 58 v4 '4 '2 '24 '8
v7147   90 '58 '29
v88     b0 '64 '5
v1      b0 '64 '7

[LOTS OF MIDI EVENTS]

v0      ff 2f v0

There’s some header data in the beginning, and each MIDI event is comprised of a deltatime field starting with ‘v’, and then fairly standard MIDI events in straightforward syntax. I hardcoded my program to expect single track which starts with tempo and speed data (ff 51 and ff 58 lines) which I use to calculate how many deltatime units is one second. I copy this header part to start of every MIDI file, and append the final “ff 2f v0” (END TRACK) event to the end. Here’s the full code:
Continue reading Split MIDI Files with Python

Using Raspberry Pi as an automatic MIDI logger

During my summer holidays I got an interesting idea: Pianoteq has a very nice feature of “always on MIDI logging” that saves everything you play on your keyboard while Pianoteq was on. I’ve previously made some MIDI projects and had a great idea:

How about building a small device that records everything I play on my piano, and save it as MIDI files?

This would enable me to later grab a good performance, and eliminate the “recording anxiety” I get if I know I’m recording and should definitely not do any mistakes during the next 1000+ notes. Furthermore, even with easy MIDI recording to USB stick, it’s still several manual steps plugging the memory stick in, starting recording, stopping it, lugging it to a computer, etc.

My first idea was to use some WLAN-enabled embedded device, but MIDI IN would require optoisolators and some custom electronics, and more modern digital pianos often come with only USB MIDI, so it could easily become an exercise in communication protocols. Fast forward a couple of minutes to my next revelation:

Raspberry Pi Model 0 W already has USB and WLAN, and it’s small. Why not use that?

Turns out using a RaspPi as fully automated MIDI logger is really easy. Read on for instructions!

Update: Also check out my follow-up post to split the recorded MIDI files automatically!

Recording MIDI with Raspbian

Turns out recording MIDI from a USB MIDI enabled device is really easy. When I plug in my Kawai CS-11 (sorry for the unsolicited link, I love my CS11 :) to the Pi (or just turn it on when it’s plugged in), dmesg shows that the Pi automatically notices the new MIDI device:

[  587.887059] usb 1-1.5: new full-speed USB device number 4 using dwc_otg
[  588.022788] usb 1-1.5: New USB device found, idVendor=0f54, idProduct=0101
[  588.022800] usb 1-1.5: New USB device strings: Mfr=0, Product=2, SerialNumber=0
[  588.022807] usb 1-1.5: Product: USB-MIDI
[  588.074579] usbcore: registered new interface driver snd-usb-audio

Once the USB MIDI device is found, you can use arecordmidi -l to list available MIDI ports:

pi@raspberrypi:~ $ arecordmidi -l
 Port    Client name                      Port name
 14:0    Midi Through                     Midi Through Port-0
 20:0    USB-MIDI                         USB-MIDI MIDI 1

Continue reading Using Raspberry Pi as an automatic MIDI logger

Picoscope 2208B MSO Review

There are few tools that are essential for an electronics hobbyist. When I started, I had a soldering iron, a multimeter and some components, and that was about it. That got me quite far because you can do simple debugging even with a multimeter, but once you start to do any communications, you will either work in the dark or get a signal analyzer, oscilloscope, or both. I reached that point about 9 months into my hobby, and eventually decided to get an entry-level PicoScope from Picotech. You can read the whole story from my PicoScope 2204 review from four years ago.

Long story short, I was extremely happy with my Picoscope, and I’ve been using Picotech’s products ever since in various projects. In the past years, I’ve also been collaborating with Picotech, so I’ve had the chance to use also their higher end models, including the frighteningly powerful 4-channel, 200 MHz, 16 bit PicoScope 5444B, which is really great but maybe even too hefty for my use. So when I was offered the chance to try out Picotech’s latest generation of their entry-level 2000 series published just a month ago, I was immediately in.

Without further ado, let’s get reviewing!

PicoScope 2000 series overview

The new PicoScope 2000 series is divided into roughly two groups of equipment: The entry models 2204 and 2205 range in price from 139€ for the 10 MHz 2-channel 2204A to 419€ 2205A and 2405A which are 25 MHz and have MSO (mixed-signal oscilloscope, i.e. it has 16 channel digital part as well) capability and 4-channels, respectively. Don’t let the low bandwith confuse you, even these models have sampling rates ranging from 100 MS/s to 500 MS/s, so you will get quite a lot of measuring power out of them.

Biggest limitation with 2204 and 2205 models is the buffer size, which ranges from 8 kS to 48 kS, so for longer captures than a few waveforms, only option is the continuous capture over USB which worked at a steady rate of 1 MS/s the last time I used it. So you can do unlimited capturing of signals around 100 kHz, but above that it’s the normal oscilloscope triggering business — that’s the way scopes have always worked from their beginnings, so it gets the job done as well.

  2204 2205 2206 2207 2208
Bandwith 10 MHz 20 MHz 50 MHz 70 MHz 100 MHz
Sample rate 100 MS/s 200 MS/s 500 MS/s 1000 MS/s 1000 MS/s
Resolution * 8 bit 8 bit 8 bit 8 bit 8 bit
Memory 8 kS 16 kS (48 kS w. MSO/4ch) 32 MS 64 MS 128 MS
Price (2015-22-05) 139 € 209 € 319 € 459 € 629 €
Options MSO or 4ch MSO or 4ch MSO or 4ch MSO or 4ch

*) Resolution for repeating signals can be increased to 12 bit with multiple samples
Continue reading Picoscope 2208B MSO Review

New Picotech 2208B Unboxing Video!

Picotech launched a new set of very compact but powerful 2000 series oscilloscopes just a few weeks ago, and with my long-term collaboration with them (they really rock :) they were kind enough to send me a unit for reviewing! The review will hopefully come quite soon, but meanwhile, enjoy this amazing unboxing video. And with “amazing”, I mean “I did not completely fail the lighting and achieved 90 % intelligible pronunciation”.

The unit in question is the high-spec 100 MHz 2208B with 16 channel logic analyzer unit built in. I knew that this replacement line to the old light blue 2000 series scopes was small, but I was still amazed by the compactness of this beast. Having had a top end 5000 series Picoscope for a few years, I’m seriously considering the “downgrade”, as I mostly use just one or two channels of the scope, and even those are in many cases digital signals. But I’ll return to this in the review later.

Let me know what you think, either here on in the Youtube comments section!

IR signal recorder with Arduino Uno

I’ve been tinkering with IR and the TSOP38238 IR receiver modules I got from Adafruit and Sparkfun. That’s right, plural, as I burned the first one — be REALLY sure not to mix ground and VCC with this one! I ordered 10 more from AliExpress just to make sure I have spares in case I burn my second one as well…

There are IR libraries for Arduino already, but they were a bit complex to my taste, as I’m first planning just to record one IR code from my bulky Sony projector remote and make a small trinket to send that on button press. The TSOP382 already demodulates the signal, so I just want to record the times the remote IR led is on, off, on, off, and so on. So I made an Arduino sketch to do just that: Count loop cycles, detect when signal goes from high (no IR signal detected) to low and vice versa:
Continue reading IR signal recorder with Arduino Uno

BeagleBone Black GPIO Benchmark

Look what the mailman brought: It’s a shiny (or maybe matte?) BeagleBone Black, freshly arrived (actually it’s been over a month, but time sure flies…) from Newark element14! I’ve been doing Raspberry Pi related hacking for a while, but especially when the Pi was still fresh and new, I did from time to time consider if the grass would be greener on other side of the fence. Or blacker, in this case, as I mean BeagleBone Black.

BeagleBone was long very much more powerful than Raspberry Pi, but now that Pi2 has come out, price and specification-wise they are closer than ever. A quick personal comparison chart:

  BeagleBone Black Raspberry Pi 2 (B)
Price 46 € (Element14) 32 € (Element14)
Processor 1GHz single-core Cortex-A8 0.9GHz quad-core Cortex-A7
Memory 512MB DDR3 1GB
Connections USB host, USB device, micro-HDMI 4x USB, HDMI, 3.5mm Audio/analog video
GPIO 2x 46 pin headers (65 digital I/O) 40 GPIO pins (26 digital I/O)
Other 4GB integrated flash, works as USB device camera and display interface on board

When Pi1 was out, the BeagleBone Black with the more modern Cortex-A8 chip and higher clockrate was definitely the more powerful, but now with 4-core Pi2, the tables have somewhat turned. Still, the clockrate is higher and there’s more GPIO. And speaking of GPIO, my Raspberry Pi vs. Pi2 GPIO benchmark has gotten a lot of interest, so I thought the best way to take this black beauty for a test drive would be to benchmark BeagleBone Black GPIO in a similar way.

Test setup

Test bench

The test subject is the most recent revision C of BeagleBone Black. I followed the (a bit lacking in detail and readability) Getting Started guide and downloaded the latest Debian Jessie image (8.3, 2016-01-24), flashed it to card and ran apt-get update and apt-get dist-upgrade (2016-04-14).
Continue reading BeagleBone Black GPIO Benchmark

Bottle.py PyMySQL Plugin

I’ve been playing around today with BottlePy, an excellent mini-framework for Python web development. However, getting Python MySQL support is always a hassle, I never know if MySQLdb has died or not, so I thought I’d try PyMySQL for a change.

In addition to being just generally awesome, Bottle has a nice plugin syntax, and even a great 60-line sample of a SQLite plugin. So I adapted it for PyMySQL, turns out this was quite easy:

import pymysql.cursors
import inspect

class PyMySQLPlugin(object):
    ''' This plugin passes a pymysql database handle to route callbacks
    that accept a `db` keyword argument. If a callback does not expect
    such a parameter, no connection is made. You can override the database
    settings on a per-route basis. '''

    name = 'pymysql'
    api = 2

    def __init__(self, db, user, password, host='localhost', charset='utf8mb4', keyword='db'):
        self.host = host
        self.user = user
        self.password = password
        self.db = db
        self.charset = charset
        self.keyword = keyword

    def setup(self, app):
        ''' Make sure that other installed plugins do not affect the same
            keyword argument.'''
        for other in app.plugins:
            if not isinstance(other, PyMySQLPlugin): continue
            if other.keyword == self.keyword:
                raise PluginError("Found another %s plugin with "
                "conflicting settings (non-unique keyword)." % self.name)

    def apply(self, callback, context):
        # Override global configuration with route-specific values.
        #conf = context.config.get('sqlite') or {}
        #dbfile = conf.get('dbfile', self.dbfile)

        # Test if the original callback accepts a 'db' keyword.
        # Ignore it if it does not need a database handle.
        args = inspect.getargspec(context.callback)[0]
        if self.keyword not in args:
            return callback

        def wrapper(*args, **kwargs):
            # Connect to the database
            db = pymysql.connect(host=self.host,
                    user=self.user,
                    password=self.password,
                    db=self.db,
                    charset=self.charset,
                    cursorclass=pymysql.cursors.DictCursor)

            # Add the connection handle as a keyword argument.
            kwargs[self.keyword] = db

            try:
                rv = callback(*args, **kwargs)
                #if autocommit: db.commit()
            #except sqlite3.IntegrityError, e:
                #db.rollback()
                #raise HTTPError(500, "Database Error", e)
            finally:
                db.close()
            return rv

        # Replace the route callback with the wrapped one.
        return wrapper

As you may see, there is no autocommit support and graceful recovery from database errors is something that is missing as well, but it’s a great start. There were a couple of GitHub projects with similar aims, but those seemed a bit behind the times (one was adding Python 3.4 support, and I’m already on 3.5, for example). A little NIH syndrome for me, maybe. Using the above library is quite easy:

from bottle import install, route
from somefile import PyMySQLPlugin

pymysql = PyMySQLPlugin(user='dbuser',
        password='dbpass', db='dbname')
install(pymysql)

@route('/demo')
def demo(db):
    # This method has a "db" parameter, and the plugin activates
    with db.cursor() as cursor:
        sql = "SELECT `id`, `password` FROM `users` WHERE `username`=%s"
        cursor.execute(sql, ('johndoe',))
        result = cursor.fetchone()
        return str(result)

Hope you found this useful!

RedBear Duo First Impressions

Look what a little beauty the mailman brought! I participated the Red Bear Duo Kickstarter Campaign a while ago, and the folks at Redbear did a really professional job in delivering on the promises of that campaign.

Headline features include ARM Cortex M3 120 MHz microcontroller with plenty of RAM and flash, and of course dual WiFi and Bluetooth connectivity. Setting up the Duo was quite simple by following the instructions provided, once I realized I’ll need to use the Zadig tool as instructed in this sub-howto (Redbear guys: I think 4-5 separate pages to get one started on Windows is something that might be optimized), I got the firmware updated and everything set up. Basic outline of my installation was about this:

  1. Plug in the board and see LEDs light up
  2. Try to install the serial driver, only to realize I already had working serial (I probably have all usb serial drivers between heaven and earth installed due to encounters with various devboards)
  3. Connect to COM6, 9600 with Putty to verify it works as it should, note down device ID
  4. Install dfu-util, and wonder why I cannot connect to the device, even with the yellow LED (looked more like yellow-green though) was blinking as it should
  5. Use Zadig tool to install drivers when in DFU mode
  6. Successfully update firmware and stuff
  7. Reboot the board a couple of times and connect with Putty to COM6 to see the IP address
  8. Visit the IP address to see the LED demo is working as it should! Nice!

Particle.io Cloud Programming

Once I had the basics figured out, I wanted to try out the Particle.io cloud development platform. It seems like an Arduino on cloud steroids, meaning that instead of flashing the device over USB cable, you write the software in a web interface, and flashing the device will upload the sketch to your device using the active wifi connection on Redbear Duo (I believe the device is periodically polling Particle.io service to see if there is a new sketch to download).
Continue reading RedBear Duo First Impressions

USB Mouse with ATmega32U4 Pro Micro Clone and LUFA

I have spent a fair amount of time with 8-bit AVR microcontrollers and one of the cooler things has been the V-USB library which implements low-speed USB with clever (and very time-critical) bit-banging. The popularity of my USB tutorials is a testament to its usefulness, and I’ve gotten lots of mileage out of that.

There are, however, some limitations to software USB with such a low spec microcontroller. USB communication hogs up the MCU completely during USB communication, which means you lose dozens of microseconds in random (or in many cases 8 ms) intervals. This rules out things like software UART at reasonable speeds (which I discovered when trying to implement MIDI on Adafruit Trinket). And more powerful ATmega328-based dev boards like Pro Trinket start to get quite large.

ProMicro on a breadboard

Not so with this tiny beauty shown in the image. It’s a ATmega32U4 based board, where the U4 means it has hardware USB support. The form factor is extremely compact 12 pin header length, which leaves 5 rows free on the smallest prototyping breadboards. That means you can have a DIP8 component with a few resistors on the same breadboard (such as a 6N137 optocoupler which is nice for MIDI… ;).

And the best part is, that because the chip is flashed with same firmware used in Arduino Leonardo (and a largely matching pinout), you can use Arduino for programming, and avrdude supports it out of the box.

Actually, scratch the above statement. The best part is the price. The board is based on Sparkfun Pro Micro 16 MHz, but it’s actually a Chinese clone, which you can get for $4 via DealExtreme and from quite many places in AliExpress: Just search for ATmega32U4 and they will come up. This means you can just order five and solder them into whatever project you’ll make permanently. And unlike Arduino Micro (for which clones exist as well), this has the micro-USB port already in place.

Using Pro Micro without Arduino IDE

Now you can just follow SparkFun’s instructions on how to use that thing on Arduino (short version: select Leonardo as board type, and look up the schematic if you are unsure which pins are connected to LEDs, etc.). But if you’re like me and want to get to raw metal, avr-gcc and avrdude is the way to go. Here’s a simple blinky demo:
Continue reading USB Mouse with ATmega32U4 Pro Micro Clone and LUFA