Arduino Metronome

Timing is essential in music and periodic signal generation. Metronome is a device that produces regular beats. Here is how you can build a metronome with Arduino. In this metronome user can change the beat timing, stop the metronome and play gain using a push button.

Arduino Metronome

Following is the circuit diagram of Arduino metronome.

Arduino Metronome Circuit Diagram

The circuit is very simple. A speaker of 4 to 8Ohm is connected to pin 10 via 100Ohm resistor. A push button is connected to the pin 9. A 10KOhm potentiometer is connected to the analog input pin A0.

The following is the program code for Arduino based Metronome.


//alias name for pins
#define SpkPin 10
#define BtnPin 9
#define PotPin A0

//variables for program use
const int F = 396;	//frequency in Hz
const int Tp = 50;	//time period in millisecond
int PotValue;

//variable to track pushbutton status
int BtnStatus = HIGH;
//boolean variable to track push button state
boolean ON = false;

unsigned int BPM=60;		//beats per minute
unsigned int msPerBeat = 0;		//milliseconds per beats
unsigned int mspm = 1000 * 60;	//milliseconds per min
long last_time = 0;		//Variable to track time

void setup(){
	//setup push button for input with internal pullup
	pinMode(BtnPin, INPUT_PULLUP);
    //setup the speaker pin as output
	pinMode(SpkPin, OUTPUT);
	//Calculate millisecond per beat based on tempo in BPM	
	msPerBeat = mspm/BPM;
}

void loop(){
	//check push button state
	checkPushButton();
	//check the potentiometer
	checkPot();
	
	//generate tone if the metronome is ON
	long current_time = millis();
		if((current_time - last_time >= msPerBeat) && ON == true){
		//generate tone
		tone(SpkPin, F, Tp);
		last_time = current_time;
		}
}

void checkPot(){
	//check the status of the potentiometer:
	int value = analogRead(PotPin);
	//re-calculate the tempo if the value has changed.
	if(value != PotValue){
		//Map the value to metronome range of 30 to 350 BPM
		BPM = map(value, 0, 1023, 30, 350);
		//recalculate the delay time
		msPerBeat = mspm/BPM;
		//update potValue
		PotValue = value;
		}
}

void checkPushButton(){
	//read push button state
	int btnstate = digitalRead(BtnPin);
	//check for button press
	if(btnstate == LOW && btnstate != BtnStatus){
	//swap on/off states
	ON =! ON;
	//update buttonStatus;
	BtnStatus = btnstate;
	//delay to cancel any debouncing faulty read
	T2delayms(20);
	}

	//check for button release
	if(btnstate == HIGH && btnstate != BtnStatus){
	//updtate the pushbutton status to off
	BtnStatus = btnstate;
        //delay to cancel any debouncing faulty read
	T2delayms(20);
	}
}

void T2delayOnems(){
    //setup Timer 2
   TCNT2 = 248;		//load count value for 1ms time delay
   TCCR2A = 0x00;
   TCCR2B = 0b00000111;	 //normal mode with 1024 pre-scalar
    
   while(!(TIFR2 & (1<<TOV2)));	//wait until TOV2 flag is set
   TCCR2B = 0;		//turn off timer 0
   TIFR2 |= (1<<TOV2);	//clear TOV0 flag
}

void T2delayms(int n){   
   for(int i = 0; i <= n; i++){
    T2delayOnems();
   }
}

Now the above arduino metronome code is explained. The program code consist of the following parts

Pin and Variable declaration: At the top is variable declaration for pins and variables names that are required for the program.

Supporting Functions: This program has supporting functions.

1. T2delayOnems()

This function creates 1 ms delay using Timer 2 of Arduino. This was explained in the tutorial Time Delay with Arduino Timer 2.

2. T2delayms(int n)

This function utilizes the T2delayOnems() function above to create n number of millisecond delay which is used in the program.

3. checkpot()

This function is used to monitor the potentiometer input at analog A0 pin. It reads in the potentiometer value which can be from 0 to 1023 and maps into the beat per minute value which has range from 30 to 350. Then millisecond per beat value(msPerBeat) is calculated by dividing the millisecond per minute with the ADC obtained beat per minute value. The variables value and potValue is used to update the ADC value.

4. checkPushButton()

This function is used to monitor the state/status of the push button connected to pin 9. When the push button is pressed(ON) then the Arduino sends out tone with frequency f=396Hz and duration Tp=50ms to the speaker pin(SpkPin) which is pin 10 with the msPerBeat value in between as calculated checkpot() function. 

5. setup()

In the setup() function we configure the speaker pin and the push button pin as output and input respectively. Then we calculate the initial value for the millisecond per beat.

6. loop()

In the loop() function we call the checkPushButton() and checkpot(). When the checkPushButton() is called the state of the push button is checked. It remembers that state of the last push button state as described about the function above. Then the checkpot() function is called in which the potetiometer status as well as the current value of the potentiometer value thus the BPM value is read. Then using comparison between the difference between the current value of time and the last value of time with the calculated millisecond per beat value and checking the status of the push button, tone of frequency f and period Tp is generated at the speaker pin.

Give it a try. Upload this arduino metronome code from the Arduino IDE and see the DIY metronome in action. The following video shows the demonstration of how this DIY Arduino metronome works.


Post a Comment

Previous Post Next Post