Hardware

Describes the hardware for pitch detection on Arduino. Part of the project Arduino Pitch Detector.\(\)

The Arduino receives input through a microphone, displays results on display and outputs the MIDI commands through USB Serial on the Arduino itself.

Schematic

This project uses input from amplified microphone and outputs to a TFT display and USB-midi connection. It reuses the USB connector by replacing the firmware on the ATmega16U2 companion chip as described on the page Sending MIDI Events.

Power

Logic

A few notes:

  • When lit, LED1 indicates that the signal exceeds the maximum level.
  • When connected, JP1 selects USB-MIDI output. Otherwise USB-SERIAL is selected. To upload the sketch, this jumper needs to be open, and the Arduino power cycled.
  • Push button, SW1 was used during development to replay stored MIDI notes.
  • Switch SW2, is for a future extension that corrects the pitch for transposing instruments.

Remember to connect the 3.3 Volt output from the Arduino to the AREF input on the Arduino. If you forget this, no notes will be displayed.

Bill of Materials

The price comes down to under $40 based on single quantity, excluding shipping and taxes. However, note that some items, such as the PCB, have minimum order quantities.

Name Description Suggested mfr and part# Paid
PCB1 Electret microphone w/ auto gain control Adafruit 1713 $7.95
PCB2 Arduino METRO 328, or Arduino Uno R3 Adafruit 2488 $17.50
PCB3 ST7735R 1.8″ Color TFT display w/ MicroSD shield Adafruit 802 $34.95
HDR Shield stacking headers for Arduino Adafruit 85 $1.95
LED1 LED, Amber Clear 602 nm, 1206 Lite-On LTST-C150AKT $0.33
R1 Resistor, 330 Ω, 1/8 W, 0805 YAGEO RC0805FR-0768RL $0.10
JP1 Connector header, vertical 3 pos, 2.54mm Metz Connect PR20203VBNN $0.10
SW1 Switch tactile, SPST-NO, 0.05A/24V TE Connectivity 1825910-3 $0.15
SW2 Switch rotary dip BDC comp, 100mA/5V Nidec Copal SH-7030TB $2.00

Considerations

Microphone

For the microphone, I use the Adafruit microphone breakout, because it has a 1.25 Volt DC bias and includes an automatic gain control. The “max gain” is set to 40 dB by connecting the GAIN to 5V. Other microphones will work for as long as they have a DC biased output, and the output signal is strong enough.

Arduino

The popular Arduino UNO R3 forms the heart of the system.

If you’re going to reprogramming the Atmega16u2, you need access the companion chip header (ICSP1) as marked in the illustration below.

Arduino pins

Display

For the display, I chose an 1.8″ TFT LCD screen. I went back and forth between using the Adafruit breakout and Shield. The advantage of this particular LCD screen is that it comes with a library and includes a μSD card reader. The module connects to the Arduino using the SPI interface. More details about SPI can be found in the article Math Talk.

Replay Push push button

Occasionally, I use a push button to replay stored MIDI notes. The push button is active low. To use this, you need to enable USB_MIDI in the config.h file.

USB-midi switch

When this switch is closed during power-up, the companion chip functions as a UART/USB-MIDI bridge. Otherwise, it does its usual UART/USB-SERIAL conversion. Refer to MIDI events for details.

The next page of this article describes the signal path and introduce the software modules.

Continue reading to learn about the Signal path and software modules.

Introduction

By our entrepreneur in residence, Johan Vonk

Describes a device that uses pitch detection built on Arduino. It recognizes the notes played on a musical instrument such as a clarinet. It won 1st place in the Silicon Valley science competition.

Introduction

While playing my clarinet, I realized that it would be fun to hear other instruments playing alongside me. Instruments like guitar, piano or even a choir. It would also be nice if the melodies could be transcribed on paper. All existing solutions to these problems require a bulky computer or a cell phone. I realized that creating this compact device would combine my interest for music with my passion for engineering and math.

This project creates a small, affordable and accurate device that listens to a musical instrument and recognizes the notes played. These notes can then be sent to a synthesizer in the common MIDI format. This allows musician to hear other instruments playing alongside with them, and allows them store their compositions.\(\)

The implementation is in C++ and uses an Arduino UNO, breadboard, microphone and optional display. It displays the music as a piano roll and sends it to an external synthesizer.

Those that want to jump straight to the core, read at least the hardware page and download the code through

Background

Five years ago, I asked my dad “How do computer do math?”. Ever since, we have spent countless hours learning about the semiconductor physics, diode logic, programmable logic and microprocessors. I find it fascinating to learn about physics and engineering. With the help and dedication of my father, I then started programming. He has provided valuable insights and suggestions allowing me grow. While it can be frustrating at times, I also find it very enlightening to build programs with ever increasing complexity.

For this project, I conducted the research and development at home. As always, my father supervised the project and helped me with architecture and code reviews to keep it readable and maintainable. He also provided suggestions to organize the code to make modules reusable and testable. In particular, he helped me when the software appeared to have random crashes. He explained about heap and stack pointers, and suggested to test for at least a 50 bytes headroom after the data structures.

Goal, design criteria and constraints

The project creates a small embedded monophonic music transcription system. Monophonic means one sound, so you can transcribe one note at a time. Therefore you cannot use this device to analyze what a band is playing without each instrument playing separately.

The device samples an analog audio signal, processes it and creates a digital MIDI output. MIDI is a digital annotation for music that signals the beginning and ending of each note.

I set out to adhere to the following design criteria:

  1. It should detect the correct pitch for notes produced by a B♭ clarinet but also work for other monophonic instruments.
  2. The beginning and duration of each notes should be identified, regardless of it being followed by a rest, note change or note repetition. This process is called segmentation.
  3. There should be no noticeable delay between the incoming audio signal and the digital MIDI output.

The cost of the initial prototype, excluding the optional display, should be under $20 and fit on a credit card size PCB. To address these constraints, I chose to build the device around the commonly available Arduino UNO, an open source prototyping platform based on an 8-bit 16 MHz microcontroller with only 2 Kbyte SRAM. Using such a slow microcontroller with limited memory posed interesting challenges but also keeps the cost down. By creating a custom PCB, the final product can be approximately 1 inch in diameter what allows it to be clipped onto an instrument.

Methodology

The common method of detecting a note pitch is by using a fast Fourier transform (FFT). This project shows that similar results can be achieved using autocorrelation. This method has the advantage of requiring only half the amount of memory compared to a FFT. The algorithm incorporates optimizations such using a low sample rate, simplifying the autocorrelation formula, using interpolation and asynchronously sampling the audio signal.

Testing with public audio samples, I found that all clarinet notes from 155.6 Hz (Eb3) to 1568 Hz (G6) are recognized correctly. Using normalization, this range can be extended to 98 Hz (G2) to 1568 Hz (G6) for the wider range of the piano. This small device enhances the experience of playing an instrument.

The source code is shared through GitHub what allows others to learn and improve this product.

Following chapters describe my project in detail. From the hardware schematic to verification methods. I hope you enjoy learning from my experience.

Continue reading to learn about the Hardware used.

SilverLit RC driver

own work

This short write-up to documents the SilverLit Remote Control vehicle protocol. It implementation, allows you to control your Arduino creation using the remote control that came with the SilverLit RC set. This set was sold through Costco and included a dump truck, flatbed, bulldozer or crane.

Protocol

I reverse engineered the protocol. The remote control first transmits a header burst of 38 kHz infrared light. The bits are then transferred as short or longer period with no IR light (space) followed by short burst of IR light (mark).

encoding
header 1.778 msec mark
13 bits data bits
1 bit stop bit

The bits are encoded as

bit value encoding
“0” 0,400 msec space, followed by 0.722 msec mark
“1” 1.037 msec space, followed by 0.722 msec mark

The data bits

bit(s) meaning
[12:11] vehicle identifier (00=dumptruck, 01=flatbed, 10=bulldozer, 11=crane)
[10:9] no special meaning. 11 when bit[7] is 0, otherwise 00
[8] 0 for backward
[7] 0 for forward
[6] 1 for right
[5] 1 for left
[4] 1 for down
[3] 1 for up
[2] 1 for light on
[1:0] checksum (see below)

The CRC is calculated as follows

checksum = bit[11:12] ^ bit[10] ^ bit[9:8] ^ bit[7:6] ^bit[5:4] ^ bit[3:2]

Note that bit 11 and 12 are reversed.

Implementation

I added a few lines to implement support for SilverLit remote vehicle/car protocol. The library was forked from Chris Young’s IRLib. His rewrite made it easy to add this new protocol. The library is available at

Note that you can’t have the original IRLib library installed because it will conflict.

Sources

  • SilverLit Infrared demo, spi_master.ino
    /*
     * Display codes coming from SilverLit remote control
     * Detect an IR receiver such as TSOP38238 to RECV_PIN (see https://learn.adafruit.com/using-an-infrared-library/hardware-needed)
     * Protocol details can be found at https://coertvonk.com/technology/embedded/arduino-ir-for-silverlit-rc-vehicles-12970
     * By Sander Vonk, 2015
     */
    
    #include <IRLib.h>
    
    int RECV_PIN = 11;
    
    IRrecv My_Receiver( RECV_PIN );
    IRdecode My_Decoder;
    unsigned int Buffer[RAWBUF];
    
    void setup()
    {
        Serial.begin( 9600 );
        My_Receiver.enableIRIn();
        My_Decoder.UseExtnBuf( Buffer );
    }
    
    
    void loop()
    {
        if ( My_Receiver.GetResults( &My_Decoder ) ) {
            My_Receiver.resume();
            if ( My_Decoder.decode() ) {
                unsigned long const data = My_Decoder.value;
    
                if ( (data & 0b111111100L) != 0b110000000L ) {  // don't display idle codes
    
                    char const * vehicle;
                    switch ( data >> 11 ) {
                        case 0: vehicle = "dumptruck "; break;
                        case 1: vehicle = "flatbed "; break;
                        case 2: vehicle = "bulldozer "; break;
                        case 3: vehicle = "crane "; break;
                    }
                    Serial.print( vehicle );
    
                    if ( bitRead( data, 8 ) == 0 ) Serial.print( "backward " );
                    if ( bitRead( data, 7 ) == 0 ) Serial.print( "forward " );
                    if ( bitRead( data, 6 ) == 1 ) Serial.print( "right " );
                    if ( bitRead( data, 5 ) == 1 ) Serial.print( "left " );
                    if ( bitRead( data, 4 ) == 1 ) Serial.print( "down " );
                    if ( bitRead( data, 3 ) == 1 ) Serial.print( "up " );
                    if ( bitRead( data, 2 ) == 1 ) Serial.print( "light " );
                    Serial.println();
                }
            }
        }
    }

The hardware setup uses the TSOP38238 as described in AdaFruit’s Receiving and Decoding IR.

Copyright © 1996-2022 Coert Vonk, All Rights Reserved