Skip navigation
2017

Arduino-Based Automatic Guitar Tuner

 

One of the most important things when playing guitar is making sure that the instrument is in tune. Even the best guitar player will not sound any good with an out-of-tune guitar. Tuning guitars by hand using a standard tuner has always been common, but an automatic tuner makes things much easier, and more fun! This Arduino-based project will tune your guitar for you.

Here is a video showing the project in action: https://www.mathworks.com/videos/automatic-guitar-tuner-using-simulink-and-arduino-1501787185047.html

Overview

 

The figure above shows an overview of the automatic guitar tuner.

  • The push button is used to select the string to tune
  • A six-LED display is used to indicate which string has been selected
  • The gripper connected to the motor is used to turn the tuning peg until the string is in tune.

The inputs and outputs are controlled by the four circuits mentioned above: a digital input circuit for the push button, an analog audio input circuit for the guitar, a digital output circuit for the LED display, and a motor-driving circuit for the tuning peg gripper. These four circuits interact with an Arduino Due, which is running an algorithm that was developed using Simulink.

Digital Input and Output Circuits

 

The circuit for the push button is a simple switch with a pull-down resistor. The LED display circuit involves 6 LEDs and a current-limiting resistor. The circuits are connected to the Arduino as shown in the diagram below.

 

Audio Input Circuit

The guitar is connected to the tuner via a standard guitar cable. The end of a guitar cable has two connections, called the tip and the sleeve. One end of the cable will be connected to an input jack, which has leads for the tip and the sleeve. Wires are soldered onto these leads to connect the tip and the sleeve to the audio input circuit.

 

The analog input pin ‘A0’ on the Arduino is used to read the audio signal coming from the guitar. The Arduino Due reads voltages between 0 V and 3.3 V. The signal coming from the guitar, however, is very low in amplitude and oscillates around 0 V, meaning it contains some negative voltages that the Arduino cannot read. To fix this, the input circuit needs to amplify the signal and add a DC offset. The circuit also needs to provide a low pass filter to eliminate high-frequency components from the signal. Any sampled signal should not contain frequencies above half of the sampling rate. Since the tuner samples the audio at a rate of 5 kHz, my circuit eliminates frequencies above 2.5 kHz. The circuit is shown below.

A TL972 op amp is recommended for this circuit. It is a very-low-noise, rail-to-rail amplifier that can operate at very low supply voltages.

Motorized Tuning Peg Gripper

 

I controlled the motorized tuning peg gripper using three digital output pins from the Arduino connected to an L293D H-bridge chip. This chip allows us to turn the motor in either direction or stop the motor based on the states of these three pins. One of the pins is called the enable pin, and the motor will only turn when the enable pin is set to high. The other two pins determine the direction of the motor. I connected the circuit as shown below.

I couldn’t use just any DC motor for this project. I needed a geared motor with a low speed and a high torque. The motor I used has a speed of 6 RPM and a maximum torque of 613 oz-in. It has a voltage range of 3-12 V, and so I used a 9 V battery as the power source.

On the shaft of the motor, I assembled a simple gripping mechanism using a clamp hub, four screws, and some tape.

Software

I used Simulink and its support package for Arduino to develop the algorithm for the tuner. Simulink is a block-diagram environment used for developing algorithms and modeling dynamic systems. The support package allows me to read from and write to pins on the Arduino using Simulink blocks. Using the software’s external mode capabilities, I can simulate an algorithm on the Arduino with automatic code generation and tune parameters while the simulation is running, without having to recompile any code. I can then deploy the algorithm to the hardware for standalone execution. The model I created is shown below.

External mode allows the use of scope blocks to monitor portions of the algorithm while it is running on the hardware. This is especially useful to monitor the digital input from the button and the analog input from the guitar. From the button scope, we can see that the input changes from 0 to 1 when the button is pressed.

I want this change from 0 to 1 to trigger a change in the selected string. This is known as a rising trigger. I created a Stateflow chart called “Select String” that has six states, one for each string, and changes from one state to the next based on this rising trigger input. Here is a more detailed look at the Stateflow chart.

Upon entry to each state, the LED pin for the corresponding string is set to high. Upon exiting each state, the pin is set to low. I chose the low E string, the lowest of the six strings, as my default. When I first power the tuner on, it will start in this default state.

There are seven outputs on the Stateflow chart: one for the LED for each of the six strings, and one called “periodRange,” which I will discuss later. The six LED outputs go straight to Arduino digital output blocks to power the appropriate LED on or off.

Now let’s look at the audio processing portion of the model. The guitar signal comes in through the analog input block. I set the sample time of the block to be 0.0002 seconds for a 5-kHz sampling rate. When I played the guitar and opened the audio scope block, I was able to see a waveform like the one below.

The scope block helped me tune the potentiometer in the audio circuit to change the gain of the input. The gain should be set as high as possible without the waveform’s peak reaching the maximum value of 1023. This will allow for the most precise reading of the signal.

When the guitar is not played, the input signal should be a flat line somewhere between 500 and 700. In my case, it was around 550. It is important to know this value because the tuner should process the audio only when there is a note being played. I chose a value of 575, just above this flat line, to be my threshold. The audio will be processed only when the signal is above this threshold value. Since Simulink allows me to tune parameters while a simulation is running, I was easily able to set my threshold value.

When a single note is played on a guitar, the waveform generated is periodic. The period of the waveform corresponds to a certain musical pitch. The tuning algorithm estimates the pitch of the string by determining the period of the waveform. I wrote a MATLAB function that performs this pitch estimation, and included it in my Simulink model using the MATLAB function block. To determine whether the string is in tune, the MATLAB function needs an input indicating what range of periods is considered in tune for each string. This is the output “periodRange” from the Stateflow chart. The function determines whether the pitch of the string is too high, too low, or in tune based on the period range, and generates outputs for the motor accordingly.

The outputs of the MATLAB function are the three pins that control the motor. These outputs go straight to Arduino digital output blocks.

Once I ensured everything was just right with my algorithm, I was able deploy it to the hardware so that it could run standalone, without being connected to the PC and independent of Simulink.

Now I can tune my guitar automatically!

All the necessary files for this project are available here:

https://www.mathworks.com/matlabcentral/fileexchange/63697-automatic-guitar-tuner-using-simulink-and-arduino

Overview

The figure above shows an overview of the automatic guitar tuner.

  • The push button is used to select the string to tune
  • A six-LED display is used to indicate which string has been selected
  • The gripper connected to the motor is used to turn the tuning peg until the string is in tune.

The inputs and outputs are controlled by the four circuits mentioned above: a digital input circuit for the push button, an analog audio input circuit for the guitar, a digital output circuit for the LED display, and a motor-driving circuit for the tuning peg gripper. These four circuits interact with an Arduino Due, which is running an algorithm that was developed using Simulink.

Digital Input and Output Circuits

The circuit for the push button is a simple switch with a pull-down resistor. The LED display circuit involves 6 LEDs and a current-limiting resistor. I connected these circuits to the Arduino as shown in the diagram below.

Audio Input Circuit

The guitar is connected to the tuner via a standard guitar cable. The end of a guitar cable has two connections, called the tip and the sleeve. One end of the cable will be connected to an input jack, which has leads for the tip and the sleeve. I soldered wires onto these leads to connect the tip and the sleeve to the audio input circuit.

I used the analog input pin ‘A0’ on the Arduino to read the audio signal coming from the guitar. The Arduino Due reads voltages between 0 V and 3.3 V. The signal coming from the guitar, however, is very low in amplitude and oscillates around 0 V, meaning it contains some negative voltages that the Arduino cannot read. To fix this, the input circuit needs to amplify the signal and add a DC offset. The circuit also needs to provide a low pass filter to eliminate high-frequency components from the signal. Any sampled signal should not contain frequencies above half of the sampling rate. Since the tuner samples the audio at a rate of 5 kHz, my circuit eliminates frequencies above 2.5 kHz. I assembled the circuit as shown below.

I would recommend using a TL972 op amp for this circuit. It is a very-low-noise, rail-to-rail amplifier that can operate at very low supply voltages.

Motorized Tuning Peg Gripper

I controlled the motorized tuning peg gripper using three digital output pins from the Arduino connected to an L293D H-bridge chip. This chip allows us to turn the motor in either direction or stop the motor based on the states of these three pins. One of the pins is called the enable pin, and the motor will only turn when the enable pin is set to high. The other two pins determine the direction of the motor. I connected the circuit as shown below.

I couldn’t use just any DC motor for this project. I needed a geared motor with a low speed and a high torque. The motor I used has a speed of 6 RPM and a maximum torque of 613 oz-in. It has a voltage range of 3-12 V, and so I used a 9 V battery as the power source.

On the shaft of the motor, I assembled a simple gripping mechanism using a clamp hub, four screws, and some tape.

Software

I used Simulink and its support package for Arduino to develop the algorithm for the tuner. Simulink is a block-diagram environment used for developing algorithms and modeling dynamic systems. The support package allows me to read from and write to pins on the Arduino using Simulink blocks. Using the software’s external mode capabilities, I can simulate an algorithm on the Arduino with automatic code generation and tune parameters while the simulation is running, without having to recompile any code. I can then deploy the algorithm to the hardware for standalone execution. The model I created is shown below.

External mode allows the use of scope blocks to monitor portions of the algorithm while it is running on the hardware. This is especially useful to monitor the digital input from the button and the analog input from the guitar. From the button scope, we can see that the input changes from 0 to 1 when the button is pressed.

I want this change from 0 to 1 to trigger a change in the selected string. This is known as a rising trigger. I created a Stateflow chart called “Select String” that has six states, one for each string, and changes from one state to the next based on this rising trigger input. Here is a more detailed look at the Stateflow chart.

Upon entry to each state, the LED pin for the corresponding string is set to high. Upon exiting each state, the pin is set to low. I chose the low E string, the lowest of the six strings, as my default. When I first power the tuner on, it will start in this default state.

There are seven outputs on the Stateflow chart: one for the LED for each of the six strings, and one called “periodRange,” which I will discuss later. The six LED outputs go straight to Arduino digital output blocks to power the appropriate LED on or off.

Now let’s look at the audio processing portion of the model. The guitar signal comes in through the analog input block. I set the sample time of the block to be 0.0002 seconds for a 5-kHz sampling rate. When I played the guitar and opened the audio scope block, I was able to see a waveform like the one below.

The scope block helped me tune the potentiometer in the audio circuit to change the gain of the input. The gain should be set as high as possible without the waveform’s peak reaching the maximum value of 1023. This will allow for the most precise reading of the signal.

When the guitar is not played, the input signal should be a flat line somewhere between 500 and 700. In my case, it was around 550. It is important to know this value because the tuner should process the audio only when there is a note being played. I chose a value of 575, just above this flat line, to be my threshold. The audio will be processed only when the signal is above this threshold value. Since Simulink allows me to tune parameters while a simulation is running, I was easily able to set my threshold value.

When a single note is played on a guitar, the waveform generated is periodic. The period of the waveform corresponds to a certain musical pitch. The tuning algorithm estimates the pitch of the string by determining the period of the waveform. I wrote a MATLAB function that performs this pitch estimation, and included it in my Simulink model using the MATLAB function block. To determine whether the string is in tune, the MATLAB function needs an input indicating what range of periods is considered in tune for each string. This is the output “periodRange” from the Stateflow chart. The function determines whether the pitch of the string is too high, too low, or in tune based on the period range, and generates outputs for the motor accordingly.

The outputs of the MATLAB function are the three pins that control the motor. These outputs go straight to Arduino digital output blocks.

Once I ensured everything was just right with my algorithm, I was able deploy it to the hardware so that it could run standalone, without being connected to the PC and independent of Simulink.

Now I can tune my guitar automatically!

All the necessary files for this project are available here:

https://www.mathworks.com/matlabcentral/fileexchange/63697-automatic-guitar-tuner-using-simulink-and-arduino

Disclaimer: I’m an engineer, not a pro film maker. Be advised.

Disclaimer: I’m an engineer, not a pro film maker. Be advised.

 

 

 

 

 

motion detection system 1.jpg

The wireless motion detector project. Three drop-modules report to the monitor in the foreground.

 

 

Motion detectors are cool but running wires out to them is a drag. We wanted to secure an area quickly and conveniently and without sirens or bells letting intruders know that we know that they are trespassing. That means no wires.

And so, it was decided, a wireless motion detecting system would be built.

 

We could picture it in our minds, a portable, self-contained system that would let us know when our parents got home or when Derek was breaching the perimeter around our couch-cushion fort. Derek doesn’t respect perimeters.

 

Design considerations – selecting components

We started with Arduino Micros and went from there. We chose these because they are small and have an on-board USB controller. This allows them to be programmed simply by plugging them into a USB port, just like the UNO. No FTDI adaptors would be needed like as is necessary for compact boards like the Arduino NANO. The version of the Micro used came without pin headers soldered on. This for ease of assembly and to conserve space. The pins would have been harder to solder to and would have taken up a lot more room.

 

nRF24 1.jpg  

For the wireless bit, we selected the nRF24L01+ radios. Note the + at the end of the name. The “plus” models that have a male SMA connector for an external antenna and they have an alleged open-air range of 1000 meters when operated at maximum power.

 

nRF24 adapter 1.jpg

nRF24 radios are extremely finicky when it comes to their power. They do not tolerate supply noise at all. To put the stop to any issues of this sort before they start, we used an adapter board like this. They come with an AMS1117 linear regulator to keep the voltage to the radio at a steady 3.3 volts. They also have a few noise filtering capacitors to keep the power clean.

 

OLED screen 1.jpg 

An 128x64 i2c OLED screen was used to display the status of the sensors. An i2c connection was chosen on purpose. The nRF24 radio communicates via SPI. So, to prevent any conflicts that might arise from having the screen and radio on the same data bus, it was decided use i2c for the screen. Yes, theoretically there should be no problem with putting the two devices on the same data bus. But all too often, reality swings in to ruin your day and you are left screaming about how everything worked fine on paper. To minimize any handholds for Murphy’s and Sod’s Law, communications to the screen and the radio were kept completely separate.

 

PIR sensor 1.jpg

This is the PIR motion sensor used for the drop-modules. The potentiometers on the side control how sensitive the device is and how long the output stays high after motion is detected.

 

battery 1.jpg 

Lithium-polymer battery in the shape of 9-volt batteries was chosen as a power source for the drop-modules and the monitor. Originally, the intention was to use disposable alkaline or lithium 9-volt batteries. However, these types of batteries will not meet the power demands of the nRF24 radios. This point demands a bit of explanation. nRF24 radios draw very little “on” but quiescent. During the short period that they are transmitting their power requirement spikes abruptly. A typical 9-volt battery cannot provide the energy fast enough for the nRF24. This problem can sometimes be mitigated by installing a fairly large capacitor (100uF) in parallel with the battery. Another solution is to do what we did, use a lithium-polymer battery. The particular batteries we chose are very convenient for projects because they combine a lithium-polymer battery with a battery management circuit, a battery protection circuit, and a boost converter. They also have a micro USB port for charging. It’s like five components packed into the shape of a 9-volt battery. Note the tiny hole in the bottom of the battery. This is for a red LED that lights up when charging. The LED shuts-off when the battery is fully charged.

 

Monitor BOM

 

Drop-module BOM

 

 

The Code (Attached to this article)

Code was written up for the drop modules and the monitor. The code for each of the drop modules is identical. During the drop-module’s setup routine, the address selection pins are polled to see what the modules address is. Two modules cannot have the same address. If they did, the monitor will interpret all the received data as coming from the same drop-module, and the system will not work as intended.

 

An ad-hoc protocol was developed for communicating drop-module status back to the monitor. The drop-modules encapsulate all of their data into an unsigned long variable. Each byte of this variable would represent a specific alarm code or the status of the battery. Then, the entire unsigned long variable is sent to the monitor.

 

At the monitor, this variable is broken back down into bytes, and the data is used to determine what drop-modules are active, what its status is and if the signal from any module is dropped.

 

The code for the drop-modules and the monitor share a number of details. They both us the RF24.h library to handle interactions with the radios. Also, they both use the TimerOne.h library. Timer one is used to make sure events like transmitting status and updating the OLED display happen at regular intervals.

 

The monitor uses the U8g2 library to control the OLED.  This library is very easy to use, and it is loaded with easy to use functions for drawing lines and shapes and placing text on the screen. There is a huge selection of fonts to choose from too.

 

At a glance, the code, especially the monitor code looks complicated but don’t let it scare you. It is lengthy, but you have a couple things going for you. It is commented extensively, and it is written out in a longhand of sorts. This makes the code take up a lot more space than it needs to, but it is also easier to understand for the less experienced coder. Oh, and the bulk of the monitor code is subroutines used to refresh the OLED display.

 

 

The mechanical design (Files needed for 3D printing, attached to this article)

All the parts that we knew were going into the project were mocked-up in SolidWorks. The Arduino Micro, the nRF24, the 9-volt battery, the OLED screen. These mock-ups are mostly rough geometric approximations of the real parts. We don’t need a high level of detail to effectively design enclosures for the project.

 

SW monitor 1.png  

From here the enclosure for the monitor was drawn up. The enclosure takes style cues from sources like the Aliens movies and the short videos of Neill Blomkamp.

 

SW drop module 1.png 

Then the drop-module was drawn up. It is designed around a clear plastic toothpick container. The container is clear and just the right size to house all the parts.

 

Putting it all together

The monitor enclosure and the parts for the drop-modules were 3D printed in a pleasing dark blue color. There was nothing very complicated about the build. The components were wired together with short leads, soldered and then covered with heat-shrink tubing. The notable points of the build are illustrated in the pictures below.

 

 

The monitor

schematic - monitor .JPG

The monitor wiring diagram. Start here.

 

 

 

 

{gallery:autoplay=false} Monitor Assembly

monitor module 5 - nRF24 radio.pngHere is the radio installed in the monitor. Notice the two spacers around the SMA connector.

These keep the radio square to the interior surface when the antenna is threaded on - they were made by trimming an old credit card into washer shape with a hobby knife.

monitor module 2 - nRF24 adapter.pngThe pins and headers were de-soldered from the adapter board; this was done to conserve space.

Then, wires were soldered to the adapter and then the whole board was covered with a big piece of heat-shrink tubing.

monitor module 3 - power button.png

The on-off switch slides into the pocket designed to hold it.

monitor module 4 - resistor bridge 1.pngThe voltage divider network for monitoring the battery status was constructed with a pair of 10k resistors.

The entire assembly was covered in heat-shrink - the yellow wire runs to and ADC input on the Arduino MICRO.

monitor module 6.JPG

The reset buttons are pressed into their slots. Friction keeps them in place.

screen & bezel 2.jpg

The conserve space, the OLED screen sits in a 3D printed bezel.

screen & bezel 3.jpg

The screen drops right into the rear of the bezel.

screen & bezel 1.JPG

The screen installed on the outside of the monitor enclosure.

monitor module 8.jpg

Fold everything into the enclosure - be careful not to break anything.

monitor module 7.jpg

Once everything is tucked inside the monitor, fasten the rear covers down with #2 machine screws.

monitor module 1.jpg

Completed monitor - human hand for scale.

 

 

 

 

Building the drop-modules

 

schematic - drop module.JPG

The schematic for the drop modules. Notice the address selection pins 8, 9, and 10. To set the address of the module, a single pin must be connected to ground. Modules cannot share addresses.

 

 

{gallery} Building the drop module

drop module 1.png

The drop modules are assembled with the same methods as the monitor - you can see here that all the components are wired up and protected with heat-shrink tubing.

drop module 2.png

You can see here where the headers and pins have been de-soldered from the adapter board and the nRF24 and wire leads have been soldered in their place - the assembly is covered in heat-shrink after soldering.

drop module 3.png

The PIR sensor is hot-glued into its 3D printed shell.

drop module 4.png

To finish, carefully fold the everything into the containers and seat the tops. Then Slide the retaining ring over the bottom of the containers. Finally, fasten everything together with the long #6-32 screws and nuts. It is a good idea to label the drop-modules too.

 

 

 

How to use it all

 

 

 

 

Conclusion

 

There were a lot of different ways we could have come at this project. We could have used a mesh network that would have allowed for dozens or over a hundred drop-modules, but instead, we went with three. Also, the code could have been written far more efficiently. Especially the monitor code. For anyone who attempts this project we strongly suggest having a go at optimizing the code.

 

We used 3D printed parts and toothpick containers to house our project, but you don’t have to do any of that. Use breadboards and cardboard. Or use plastic food containers. It doesn’t matter. The code and the hardware are oblivious to how good (or bad) they look. Also, for your version of this project, you can use different sensors. You don’t have to use PIR motion detectors. You could use the drop-modules to keep an eye on anything. Use photoresistors to see if someone turns on a light. Replace the PIR sensor with a momentary pushbutton or a pressure sensitive doormat to make a wireless doorbell. Maybe you could use a drop-module with just a tilt sensor to let you know if someone is messing with your bike. Whatever you ultimately decide to do, this project gives you a solid basis to work from.

 

But for now, Derek won’t know what hit him.

 

 

-----------------------------------------------------------------------------------------------------

Have a story tip? Message me at: cabe(at)element14(dot)com

http://twitter.com/Cabe_Atwell