#include
#include "piano_tones.h"
#define common_pin 2 // Common "send" pin for all keys
#define Buzzer A4 // Output pin of piezoelectric buzzer
#define recordbtn 12 // Recording button
#define CPin(pin) CapacitiveSensor (common_pin, pin)
At the beginning of the “piano_pcb.ino” file, we have the “CapacitiveSensor.h” and “piano_tones.h” header files. I then defined three macros for the respective GPIO pins. “common_pin” is used to set “digital pin 2” to the “Send Pin”, “buzzer” is used to define analog pin 4 (A4), and “recordbtn” is used to slide the “button” into “digital pin 12”. I then created the “CPin (pin)” macro so that we don’t need to pass the send pin (which is common_pin) and the receive pin (which is the pin of the individual resistors) multiple times in the CapacitiveSensor(common_pin,pin).
Integer comment[]={NOTE_C7, NOTE_D7, NOTE_E7, NOTE_F7, NOTE_G7, NOTE_A7, NOTE_B7, NOTE_C8};
//Startup sound
int soundOnStartUp[] = {
Attention_E7, Attention_E7, 0, Attention_E7,
0, Attention_C7, Attention_E7, 0,
NOTE_G7, 0, 0, 0,
NOTE_G6, 0, 0, 0 };
capacitivesensorkeys[] = {CPin(3), CPin(4), CPin(5), CPin(6), CPin(7), CPin(8), CPin(9), CPin(10)};
After calling the library and defining some macros, we need to create 3 arrays as mentioned above. These are notes[], soundOnStartUp[] and keys[]. The "notes[]" array stores the notes that correspond to the piano in a certain scale (e.g. NOTE_C7, NOTE_D7, etc.). You can change the scale by uncommenting the other "notes[]" that I have provided in the code. The soundOnStartUp[] array is used to store some tunes that I use during the startup of the piano. This array has been called in the setup() function. The capacitive sensor keys[] array is used to store the corresponding receiving pins, using the CPin() function that we defined earlier.
void recordButton(){
// Set the sensor's sensitivity.
long touch1 = keys[0].capacitiveSensor(sensitivity);
long touch2 = keys[1].capacitiveSensor(sensitivity);
long touch3 = keys[2].capacitiveSensor(sensitivity);
long touch4 = keys[3].capacitiveSensor(sensitivity);
long touch5 = keys[4].capacitiveSensor(sensitivity);
long touch6 = keys[5].capacitiveSensor(sensitivity);
long touch7 = keys[6].capacitiveSensor(sensitivity);
long touch8 = keys[7].capacitiveSensor(sensitivity);
pev_button = button;
// When we touch the sensor, the button will record the corresponding number.
if (touch1 > sensitivity)
button = 1;
if (touch2 > sensitivity)
button = 2;
if (touch3 > sensitivity)
button = 3;
if (touch4 > sensitivity)
button = 4;
if (touch5 > sensitivity)
button = 5;
if (touch6 > sensitivity)
button = 6;
if (touch7 > sensitivity)
button = 7;
if (touch8 > sensitivity)
button = 8;
// When we don't touch it, no tone is produced.
if (touch1<=sensitivity& touch2<=sensitivity& touch3<=sensitivity& touch4<=sensitivity& touch5<=sensitivity& touch6<=sensitivity& touch7<=sensitivity& touch8<=sensitivity)
button = 0;
/****Record the pressed buttons in an array***/
if (button != pev_button && pev_button != 0)
{
record button[button_index] = pev_button;
buttonIndex++;
recordButton[buttonIndex] = 0;
buttonIndex++;
}
/**Recording process ends**/
}
We read the capacitance value of each key using the "keys[0].capacitiveSensor(sensitivity)" function and compare it to some specified value to determine which key was pressed in the recordButtons() function above. We also keep track of the order in which the buttons were pressed in this function. The recorded values are saved in the recorded buttons[] array. We first check to see if a new key was pressed, and if so, we check again that it is not button 0. But no button was pressed, so button 0 has nothing. We save the value at the index specified by the variable button_index inside the if loop, and then we increment that index value to avoid overwriting the same location.
void playTone() {
/****Time delay between each button press in the Rcord array***/
if (button != pev_button)
{
note_time = (millis() - start_time) / 10;
if (note time != 0) {
note_time[time_index] = note_time;
time_index++;
startTime = milliseconds();
}
Serial.println(time_index);
}
/**Recording process ends**/
if (button == 0)
{
noTone(buzzer);
}
if (button == 1)
{
tone(buzzer, notes[0]);
}
if (button == 2)
{
tone(buzzer, note[1]);
}
if (button == 3)
{
tone(buzzer, note[2]);
}
if (button == 4)
{
tone(buzzer, note[3]);
}
if (button == 5)
{
tone(buzzer, note[4]);
}
if (button == 6)
{
tone(buzzer, note[5]);
}
if (button == 7)
{
tone(buzzer, note[6]);
}
if (button == 8)
{
tone(buzzer, note[7]);
}
}
Using various if conditions, we will play the appropriate tone for the key presses in the playTone() function. The full code for this function is shown above. We will also use an array called recorded time[] to hold the length of time the buttons were pressed. The process is similar to recording a sequence of buttons in that we use the millis() function to calculate how long each button was pressed and then divide that value by 10 to reduce the size of the variable. We do not play any tone during the same time period for button 0, which indicates that the user did not press anything.
void setup() {
SerialNumber.Start(9600);
// Turn off autocalibration for all channels:
for(int i=0; i<8; ++i) {
Key[i].set_CS_AutocaL_Millis(0xFFFFFFFF);
}
// Set the buzzer as an output:
pinMode(buzzer, OUTPUT);
pinMode(recordbtn,input);
noTone(buzzer);
delay(10);
int sizeed = sizeof(soundOnStartUp) / sizeof(int);
for (int thisNote = sizeed; thisNote > 0 ; thisNote--) {
sound(buzzer, soundOnStartUp[thisNote]);
delay(100);
}
noTone(buzzer);
delay(10);
}
There are two for loops in the setup() function. In the first loop, I set the keys using "keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF)". The second for loop is used to play the soundOnStartUp[] note by using tone(buzzer, soundOnStartUp[thisNote]).
void loop(){
Serial.println(digitalRead(recordbtn));
while (digitalRead(recordbtn) == 1) //If the toggle switch is set to recording mode
{
recordButton();
playSound();
}
while (digitalRead(recordbtn) == 0) //If the toggle switch is set to play mode
{
for (int i = 0; i < sizeof(recorded_button) / 2; i++)
{
delay((recordtime[i])*10); //wait for next song to be paid
if (recorded_button[i] == 0)
noTone(buzzer); //user did not touch any button
Other
sound(buzzer, note[(recorded_button[i] - 1)]); //play the sound corresponding to the button touched by the user
}
}
}
Then, to play the recorded tone, the user must push the slide switch to the other direction after recording. Once this is done, the program exits the previous while loop and enters the second while loop where we play the notes of the previously recorded length in the order in which the keys were hit. The code to accomplish this is provided above. You can watch the video attached below for more explanation.
Code
#include
#include "piano_tones.h"
#define common_pin 2 // Common "send" pin for all resistors
#define buzzer A4 // Output pin of piezoelectric buzzer
#define recordbtn 12 // Recording button
// This macro creates a capacitive sensor object for each resistor pin
#define CPin(pin) CapacitiveSensor(common_pin, pin)
char button = 0;
integer analog value;
char REC = 0;
int record button[200];
int pev_button;
int sensitivity = 2000;
int record time [200];
Character time index;
characterButtonIndex = 0;
unsigned long startTime;
int note_time;
// Each key corresponds to a note, defined here. Uncomment the scale you want to use:
//int notes[]={NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_B4, NOTE_C5}; // C major scale
//int notes[]={NOTE_A4,NOTE_B4,NOTE_C5,NOTE_D5,NOTE_E5,NOTE_F5,NOTE_G5,NOTE_A5}; // A-minor scale
//int notes[]={NOTE_C4, NOTE_D4, NOTE_E4, NOTE_F4, NOTE_G4, NOTE_A4, NOTE_C5, NOTE_D5}; // C blues scale
//int notes[] = {1300, 1500, 1700, 1900, 2000, 2300, 2600, 2700};
Integer comment[]={NOTE_C7, NOTE_D7, NOTE_E7, NOTE_F7, NOTE_G7, NOTE_A7, NOTE_B7, NOTE_C8};
//int notes[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
// Start the sound
int soundOnStartUp[] = {
NOTE_E7, NOTE_E7, 0, NOTE_E7,
0, NOTE_C7, NOTE_E7, 0,
Note_G7, 0, 0, 0,
Note_G6, 0, 0, 0
};
// Define the pins to which the registers are connected:
CapacitiveSensor keys[] = {CPin(3), CPin(4), CPin(5), CPin(6), CPin(7), CPin(8), CPin(9), CPin(10)};
void setup() {
Serial.begin(9600);
// Turn off autocalibration for all channels:
for (int i = 0; i < 8; ++i) {
keys[i].set_CS_AutocaL_Millis(0xFFFFFFFF);
}
// Set the buzzer as output:
pinMode(buzzer, OUTPUT);
pinMode(recordbtn,input);
noTone(buzzer);
delay(10);
int sizeed = sizeof(soundOnStartUp)/sizeof(int);
for (int thisNote = sizeed; thisNote 〉 0 ; thisNote--) {
tone(buzzer, soundOnStartUp[thisNote]);
delay(100);
}
noTone(buzzer);
delay(10);
}
void loop() {
Serial.println(digitalRead(recordbtn));
while (digitalRead(recordbtn) == 1) //If the toggle switch is set to recording mode
{
recordButtons();
playSound();
}
while (digitalRead(recordbtn) == 0) //If the toggle switch is set to play mode
{
for (int i = 0; i < sizeof(recorded_button) / 2; i++)
Previous article:How to Build a Gesture-Controlled Raspberry Pi Media Player
Next article:How to Build a Portable Humidifier Using Arduino
- Huawei's Strategic Department Director Gai Gang: The cumulative installed base of open source Euler operating system exceeds 10 million sets
- Analysis of the application of several common contact parts in high-voltage connectors of new energy vehicles
- Wiring harness durability test and contact voltage drop test method
- Sn-doped CuO nanostructure-based ethanol gas sensor for real-time drunk driving detection in vehicles
- Design considerations for automotive battery wiring harness
- Do you know all the various motors commonly used in automotive electronics?
- What are the functions of the Internet of Vehicles? What are the uses and benefits of the Internet of Vehicles?
- Power Inverter - A critical safety system for electric vehicles
- Analysis of the information security mechanism of AUTOSAR, the automotive embedded software framework
Professor at Beihang University, dedicated to promoting microcontrollers and embedded systems for over 20 years.
- Innolux's intelligent steer-by-wire solution makes cars smarter and safer
- 8051 MCU - Parity Check
- How to efficiently balance the sensitivity of tactile sensing interfaces
- What should I do if the servo motor shakes? What causes the servo motor to shake quickly?
- 【Brushless Motor】Analysis of three-phase BLDC motor and sharing of two popular development boards
- Midea Industrial Technology's subsidiaries Clou Electronics and Hekang New Energy jointly appeared at the Munich Battery Energy Storage Exhibition and Solar Energy Exhibition
- Guoxin Sichen | Application of ferroelectric memory PB85RS2MC in power battery management, with a capacity of 2M
- Analysis of common faults of frequency converter
- In a head-on competition with Qualcomm, what kind of cockpit products has Intel come up with?
- Dalian Rongke's all-vanadium liquid flow battery energy storage equipment industrialization project has entered the sprint stage before production
- Allegro MicroSystems Introduces Advanced Magnetic and Inductive Position Sensing Solutions at Electronica 2024
- Car key in the left hand, liveness detection radar in the right hand, UWB is imperative for cars!
- After a decade of rapid development, domestic CIS has entered the market
- Aegis Dagger Battery + Thor EM-i Super Hybrid, Geely New Energy has thrown out two "king bombs"
- A brief discussion on functional safety - fault, error, and failure
- In the smart car 2.0 cycle, these core industry chains are facing major opportunities!
- The United States and Japan are developing new batteries. CATL faces challenges? How should China's new energy battery industry respond?
- Murata launches high-precision 6-axis inertial sensor for automobiles
- Ford patents pre-charge alarm to help save costs and respond to emergencies
- New real-time microcontroller system from Texas Instruments enables smarter processing in automotive and industrial applications
- 【NXP Rapid IoT Review】+Hello world!
- 5G miniaturized terminal and base station antenna technology
- DIY retro game console based on Raspberry Pi Zero
- Transistor static operating point
- The History of DSP and Why No One Mentions DSP Anymore
- RISC-V MCU IDE MRS (MounRiver Studio) development: Add standard math library reference
- A brief introduction to the timer A function of the 430 microcontroller
- [Social Recruitment] Capital Securities Recruitment [Semiconductor Researcher]
- [Lazy self-care fish tank control system] PRINTF output in RTT mode under Keil environment
- This week's highlights