Pitch Detection on Arduino using Autocorrelation

This eight part of the Arduino Pitch Detector. article describes how MIDI events are send.\(\)

Sending MIDI events (midiserial.cpp)

The Arduino acts as a MIDI Controller and sends MIDI messages over a connection to a sequencer/synthesizer. The two main MIDI messages are:

  • note on, to start playing a particular pitch on a particular channel at a particular volume
  • note off, to stop playing a particular pitch on a particular channel

More and more MIDI equipment connects using USB-MIDI, carried over standard USB cables. This is convenient, because the Arduino already as a USB port.


The Arduino has an USB port, but uses this port to talks USB-SERIAL with the host computer. That is how the Serial.print() statements end up on the serial monitor. A small companion chip (ATmega16U2) on the Arduino acts a UART/USB-serial bridge.

For the computer to receive USB-MIDIinstead of USB-SERIAL, we have two options:

  1. using extra software on the host computer
  2. reprogramming the companion chip on the Arduino

During development, I used the software approach. The Arduino sends MIDI messages over its usual USB-SERIAL port. Software on the host (e.g. hairless), packetizes the serial byte stream and forwards the packets to a virtual MIDI port (e.g. loopmidi). Advantage of this approach is that you can still use Serial.print() statements during development, but the disadvantage is that you can’t directly connect the Arduino to a stand-alone synthesizer.

Once the Arduino Pitch Detector matured, reprogrammed the companion chip on the Arduino. This mades the Arduino UNO R3 appear as a MIDI peripheral (HID). It required installing dualMocoLUFA firmware on the 16U2m so that it can act as a UART/USB-MIDI bridge. By connecting two pins (see hardware), you can power-cycle to switch between UART/USB-MIDI and UART/USB-SERIAL mode. This is important, because USB-SERIAL is the default method of uploading new sketches. Patching, compiling and installing the firmware will test your patience. First you need to find a computer environment, such as Linux or OS/X, that supports make.

  1. Download the sources
    • LUFA-100807, unzip and remove the contents of the Projects directory.
    • dualMocoLUFA, unzip and move the files to the LUFA Projects directory.
  2. Verify USB Vendor and Product Id
    • Windows Device Manager » Ports (COM & LPT) » Arduino UNO » Properties » Details should be USB\VID_2341&PID_0043&REV_0001
  3. Patch to specify the IDs, microcontroller and reverse the pin logic.
    • The main LUFA makefile
      • change it so that it only builds the Projects directory
    • makefile (specify target)
      • line 65: MCU = atmega16u2
      • line 72: ARDUINO_MODEL_PID = 0x0043
    • Descriptors.c (fix compile error and specify identifiers)
      • search and replace “PROGMEM” with “PROGMEM const
      • line 80: .VendorID = 0x2341
      • line 82: .ProductID = ARDUINO_MODEL_PID
    • Descriptors.c (change the USB device name)
      • line 452: .Header = {.Size = USB_STRING_LEN(14), .Type = DTYPE_String}
      • line 454: .UnicodeString = L"Pitch Detector"
    • Descriptors.h (specify ID)
      • line 57: ARDUINO_UNO_PID 0x0043
    • dualMoco.c (reverse the logic)
      • line 48: mocoMode = 0
      • line 340: mocoMode = 1
  4. Build
    • change to the LUFA Projects directory and run “make clean“, “make -s” to create dualMoco.hex. Move the file over to your Windows environment.
    • For your piece of mind, the original firmware is still available in the Arduino directory as hardware\arduino\avr\firmwares\atmegaxxu2\arduino-usbserial\Arduino-usbserial-atmega16u2-Uno-Rev3.hex.
  5. Upload using Device Firmware Update (DFU)
    • Download and install Atmel DFU tool (Windows).
    • Put Arduino in DFU mode by touching RESET2 to GND (the two leftmost pins (#5 and #6) on the ICSP1 header near the USB connector)(http://forum.arduino.cc/index.php?topic=88022.0, http://arduino.cc/en/uploads/Main/Arduino_Uno_Rev3-schematic.pdf)
    • In Windows Device Manager, it should show up as “Atmel USB Devices > ATmega16U2“. If you encounter “unknown device“, install the driver from FLIP directory. “C:\Program Files (x86)\Atmel\Flip 3.4.7\usb\atmel_usb_dfu.inf
    • Start Atmel DFU tool (flip)
      • Device » Select » ATmega16U2
      • Settings » Communication » USB
      • File » Load HEX File » dualMoco.hex
      • Run
  6. Test
    • Unplug Arduino, and plug back in. In Windows device manager, it should show up as usual under “Ports (COM & LPT) > Arduino UNO
    • Unplug Arduino, connect MOSI2 to GND, and plug back in. (pin #4 and #6 on the ICSP1 header near the USB connector). In device manager, it should appear as “Sound, video and game controllers > Pitch Detector


If you’re ready to play with software sequencers to record and play back MIDI events, take a look at the free MidiEditor, and Anvil Studio. Others are musescore, midisheetmusic and scorecloud.

The next part of this article describes the verification methods.

Student at MVHS
I see education as the foundation upon which entrepreneurs are able to build innovative organizations and execute their vision for the future.

4 Replies to “Pitch Detection on Arduino using Autocorrelation”

  1. Hello,

    I want to know the frequency of the power grid, but harmonic frequencies in the power grid are a huge problem.
    Can you send me a code for ‘filtering’ fundamental? (0-150Hz max)

  2. Hello,

    First of all, this a great work ! Not only just a sample stuff but very documented, you shoudl be proud !

    I’d like to use it for a guitare. Do you think it will work ? Did you test it ?

    Finally, did you make a video of it to see how good it works ? :)

    Thanks for the sharing and keep having fun making all these things :)

  3. Hello. Bravo for this work …
    I am a retired electronic engineer, and I designed a tuner working with FFT on a PC with a professional tool : Labview from National Instrument, which offers huge signal processing libraries. I wanted a very precise instrument to tune the reeds of a vintage italian accordion (Paolo Soprani, 1915). I am also playing bassoon, and then concerned with bass notes. I encountered many difficulties with low frequency cut off of the microphones, giving signals with harmonics far higher than fundamental (up to 20 dB). The lowest note of my accordion is a Bb at 58.27 Hz, on the left hand chords. This is also the lowest note of the basson. Precise measurement need very long sampling of several seconds !
    Well, now, I want to buid a little funny gadget which will animate a “snake” poping out of a basket in relation with the recognised notes … I am very interested by your work, but I think i will use a more powerfull processor than the Arduino uno, and then higher sampling frequency and 500 or 1000 samples.

Leave a Reply

Your email address will not be published. Required fields are marked *


This site uses Akismet to reduce spam. Learn how your comment data is processed.