This project demonstrates how to build a piano with an eight push button keypad and three piezo speakers so you can be able to make chords when pressing up to three button simultaneously, and all the logic will be written using Netduino.Foundation library.
Piezo speakers (or piezoelectric speaker) is a loudspeaker that uses the piezoelectric effect for generating sound. The initial mechanical motion is created by applying a voltage to a piezoelectric material, and this motion is typically converted into audible sound using diaphragms and resonators.
Netduino.Foundation is a platform for quickly and easily build connected things using the.NET MicroFramework on Netduino. Created by Wilderness Labs, it's completely open source and maintained by the Netduino community.
If you're new in Netduino development, I suggest you go to the Getting started with Netduino project to properly set up your development environment.
Step 1 - Assemble the circuitFor this project, wire up your breadboard and Netduino as shown in the Fritzing diagram:
Create a Netduino project in Visual Studio 2015 for Windows or the latest Visual Studio for Mac; name the project Piano.
Step 3 - Add the Netduino.Foundation NuGet PackageWindows
Right-click on your Piano project and click Manage Nuget Packages. In the Browse tab, search for Netduino.Foundation; it should be the first search result. Click the Install button.
macOS
Alt-click on your Piano project in the Solution Explorer, and click Add => Add Nuget Package to open the NuGet Package window. Search for the Netduino.Foundation package and click Add Package to add it to your project.
Add App Class
For this project, we implement a common App software pattern that manages all the peripherals and main logic.
Add a new App class to your project, and paste the following code:
using Microsoft.SPOT;
using Microsoft.SPOT.Hardware;
using N = SecretLabs.NETMF.Hardware.Netduino;
using Netduino.Foundation.Audio;
using System.Threading;
using Netduino.Foundation.LEDs;
namespace Piano
{
public class App
{
Led onboardLed;
PiezoSpeaker[] speakers = new PiezoSpeaker[3];
bool[] isSpeakerPlaying = new bool[3];
InputPort[] pianoKeys = new InputPort[8];
float[] notes = new float[] { 261.6f, 293.7f, 329.6f, 349.2f, 392.0f, 440.0f, 493.9f, 523.3f };
//C4 , D4 , E4 , F4 , G4 , A4 , B4 , C5
public App()
{
InitializePeripherals();
}
private void InitializePeripherals()
{
pianoKeys[0] = new InputPort(N.Pins.GPIO_PIN_D7, true, Port.ResistorMode.PullUp);
pianoKeys[1] = new InputPort(N.Pins.GPIO_PIN_D6, true, Port.ResistorMode.PullUp);
pianoKeys[2] = new InputPort(N.Pins.GPIO_PIN_D5, true, Port.ResistorMode.PullUp);
pianoKeys[3] = new InputPort(N.Pins.GPIO_PIN_D4, true, Port.ResistorMode.PullUp);
pianoKeys[4] = new InputPort(N.Pins.GPIO_PIN_D3, true, Port.ResistorMode.PullUp);
pianoKeys[5] = new InputPort(N.Pins.GPIO_PIN_D2, true, Port.ResistorMode.PullUp);
pianoKeys[6] = new InputPort(N.Pins.GPIO_PIN_D1, true, Port.ResistorMode.PullUp);
pianoKeys[7] = new InputPort(N.Pins.GPIO_PIN_D0, true, Port.ResistorMode.PullUp);
speakers[0] = new PiezoSpeaker(Cpu.PWMChannel.PWM_2);
speakers[1] = new PiezoSpeaker(Cpu.PWMChannel.PWM_3);
speakers[2] = new PiezoSpeaker(Cpu.PWMChannel.PWM_5);
onboardLed = new Led(N.Pins.ONBOARD_LED);
isSpeakerPlaying[0] = isSpeakerPlaying[1] = isSpeakerPlaying[2] = false;
}
protected void Cycle()
{
Thread thread = new Thread(() =>
{
bool[] lastState = new bool[8];
int speakersPlaying = 0;
while (true)
{
Thread.Sleep(50);
bool[] currentState = new bool[8];
currentState[0] = pianoKeys[0].Read();
currentState[1] = pianoKeys[1].Read();
currentState[2] = pianoKeys[2].Read();
currentState[3] = pianoKeys[3].Read();
currentState[4] = pianoKeys[4].Read();
currentState[5] = pianoKeys[5].Read();
currentState[6] = pianoKeys[6].Read();
currentState[7] = pianoKeys[7].Read();
for (int i = 0; i < 8; i++)
{
if (lastState[i] != currentState[i])
{
if (!currentState[i] && speakersPlaying < 3)
{
speakers[speakersPlaying].PlayTone(notes[i]);
speakersPlaying++;
}
else if (speakersPlaying > 0)
{
speakers[speakersPlaying - 1].StopTone();
speakersPlaying--;
}
onboardLed.IsOn = (speakersPlaying > 0);
}
}
for (int i = 0; i < 8; i++)
lastState[i] = currentState[i];
}
});
thread.Start();
}
public void Run()
{
Debug.Print("Welcome to Piano");
Cycle();
}
}
}
First thing that happens in this class is calling InitializePeripherals to instantiate all the peripherals that are connected to the Netduino, which in this project, is an array of 8 digital InputPort pins, the onboard LED and 3 Piezo speakers.
Once that is all set, in the Run method, it calls the Cycle, which is the main method in this project.
The way Cycle method works is getting the state of each button on every iteration on an infinite loop, and based on the state of all those input pins, we call the PlayNote() piezo method that will play the corresponding note to the button that has been pressed, and if there are additional buttons pressed, we use the other two speakers. When a pressed button is released, in the next iteration, the program will pick up that change and it will call StopTone() to release that piezo from playing its note.
At the end of each iteration, it also checks if there are any Piezo speakers playing to turn the on-board LED of the Netduino on or off.
Program class
Finally, create a new App class object and invoke the Run method. Your code should look like this:
using System.Threading;
namespace Piano
{
public class Program
{
public static void Main()
{
var app = new App();
app.Run();
Thread.Sleep(Timeout.Infinite);
}
}
}
Step 5 - Run the projectClick the run button in Visual Studio to see your polyphonic piano in action! Press up to three buttons and hear the chords you can make with the three piezo speakers. It should look like the following GIF:
This project is only the tip of the iceberg in terms of the extensive exciting things you can do with Netduino.Foundation.
- It comes with a Huge Peripheral Driver Library with drivers for the most common sensors and peripherals available in the market.
- All the peripheral drivers are simplified with built-in functionality, exposed by a clean, modern API.
- This project is backed by a growing community that is constantly working on building cool connected things and always excited to help new-comers and discuss new projects.
Comments