Clapping music with Arduino: Difference between revisions

From XPUB & Lens-Based wiki
No edit summary
 
(29 intermediate revisions by 3 users not shown)
Line 1: Line 1:
Arduino!
This exercise relies on the following topics in [[C]]:
* variable types (int, char)
* character arrays (strings)
* loops
* nested loops
 
== Hello world.c ==
Arduino is [[C]]!
 
<source lang="c">
#include <stdio.h>
 
main ()
{
  printf("hello world\n");
}
</source>
 
== Blink music ==


<source lang="c">
<source lang="c">
Line 15: Line 33:
</source>
</source>


<source lang="c">
</source>


change the argument to the delay...
change the argument to the delay...
Line 34: Line 50:
   }
   }
}
}
void loop () {}
</source>
</source>


== tone ==


* http://www.arduino.cc/en/Tutorial/Tone
* http://www.arduino.cc/en/Tutorial/Tone
* Starting point is the Example > Digital > toneMelody
* Starting point is the Example > Digital > toneMelody
'''Important''': ''tone'' is a unique command in that it is ''asynchronous'', meaning that when you call the function it starts playing the tone, but immediately returns control to your program. In Bash terms, it's like starting the program with the '&' character at the end -- the command runs "in the background". This is important to know, because you '''need to use the delay''' command to play consecutive tones, otherwise each call to tone undoes the previous ones.
'''So, the wrong way would be:'''
<source lang="c">
int speakerPin = 13;
void setup() {
  tone(speakerPin, 500, 100);
  tone(speakerPin, 600, 100);
  tone(speakerPin, 700, 100);
  tone(speakerPin, 800, 100);
  tone(speakerPin, 900, 100);
}
void loop() {}
</source>
'''And the right way is instead:'''
<source lang="c">
int speakerPin = 13;
void setup() {
  tone(speakerPin, 500, 100);
  delay(100);
  tone(speakerPin, 600, 100);
  delay(100);
  tone(speakerPin, 700, 100);
  delay(100);
  tone(speakerPin, 800, 100);
  delay(100);
  tone(speakerPin, 900, 100);
  delay(100); 
}
void loop() {}
</source>
== Clapping music.c ==
Now, using a [[C]] string with the [[Clapping music]] pattern.
The clapping pattern can be implemented using calls to tone & delay:
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
void setup() {}
void loop () {
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  delay(thedelay*10); // pause between repetitions
}
</source>
Now, we move from a hard coded pattern into using a C string (or char array), and the code becomes...
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
void setup() {}
void loop () {
  if (pat[0] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[1] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[2] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[3] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[4] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[5] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[6] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[7] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[8] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[9] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[10] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[11] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay*10); // pause between repetitions
}
</source>
Notice how above the code is highly repetitive -- perfect for a loop!
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
void setup()
{
}
void loop ()
{
    int i = 0;
   
    while (i<patlen) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(thedelay);
        i = i+1;
    }
    delay(thedelay*10);
}
</source>
If you prefer, a for loop can be used instead (they are identical! the for statement is in fact shorthand for doing what the ''while'' loop does above.
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
void setup()
{
}
void loop ()
{
    int i;
    for (i=0; i<12; i+=1) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(thedelay);
    }
    delay(thedelay*10);
}
</source>
Now, we remove the hard-coded length of the pattern (12) to use C's ''strlen'' function so that the pattern can be any length.
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
char pat[]  = "x xx xxx xxxx xxxxx ";
int patlen = strlen(pat);
void setup()
{
}
void loop ()
{
    int i = 0;
    while (i<patlen) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(10);
        i = i+1;
    }
    delay(thedelay*10);
}
</source>
Here's a start at playing two parts (nearly simultaneously):
<source lang="c">
int speakerPin = 13;
int thedelay = 100;
char pat[]  = "x xx xxx xxxx xxxxx ";
int patlen = strlen(pat);
void setup()
{
}
void loop ()
{
    int i = 0;
    int i2 = 0;
    while (i<patlen) {
        i2 = i+5;
        if (i2 >= patlen) i2 = i2 - patlen;
        //  maybe the % modulo operator could help here!!!
       
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(10);
        if (pat[i2] == 'x') tone(speakerPin, 800, 10);
        delay(thedelay);
        i = i+1;
    }
    delay(thedelay*10);
}
</source>
[[User:Laura Macchini/prototyping/ArduinoClappingMusic | Laura's Clapping Music with Arduino]]
[[User:Laurier Rochon/prototyping/clapping music button | Laurier's Clapping Music with Arduino and button]]

Latest revision as of 18:37, 26 October 2010

This exercise relies on the following topics in C:

  • variable types (int, char)
  • character arrays (strings)
  • loops
  • nested loops

Hello world.c

Arduino is C!

#include <stdio.h>

main ()
{
  printf("hello world\n");
}

Blink music

void setup()   {                
  pinMode(8, OUTPUT);
  for (int i=0; i<1000; i++) {
    digitalWrite(8, HIGH);
    delay(1);
    digitalWrite(8, LOW);
    delay(1);
  }
}

void loop () {}


change the argument to the delay...

for my refined control, try delayMicroseconds

void setup()   {                
  int x;
  // initialize the digital pin as an output:
  pinMode(8, OUTPUT);
  for (int i=0; i<1000; i++) {
    digitalWrite(8, HIGH);
    delayMicroseconds(250);
    digitalWrite(8, LOW);
    delayMicroseconds(250);
  }
}

void loop () {}

tone

Important: tone is a unique command in that it is asynchronous, meaning that when you call the function it starts playing the tone, but immediately returns control to your program. In Bash terms, it's like starting the program with the '&' character at the end -- the command runs "in the background". This is important to know, because you need to use the delay command to play consecutive tones, otherwise each call to tone undoes the previous ones.

So, the wrong way would be:

int speakerPin = 13;
void setup() {
  tone(speakerPin, 500, 100);
  tone(speakerPin, 600, 100);
  tone(speakerPin, 700, 100);
  tone(speakerPin, 800, 100);
  tone(speakerPin, 900, 100);
}
void loop() {}

And the right way is instead:

int speakerPin = 13;
void setup() {
  tone(speakerPin, 500, 100);
  delay(100);
  tone(speakerPin, 600, 100);
  delay(100);
  tone(speakerPin, 700, 100);
  delay(100);
  tone(speakerPin, 800, 100);
  delay(100);
  tone(speakerPin, 900, 100);
  delay(100);  
}

void loop() {}

Clapping music.c

Now, using a C string with the Clapping music pattern.

The clapping pattern can be implemented using calls to tone & delay:

int speakerPin = 13;
int thedelay = 100;
 
void setup() {}

void loop () {
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  tone(speakerPin, 400, 10);
  delay(thedelay);
  delay(thedelay);

  delay(thedelay*10); // pause between repetitions
}

Now, we move from a hard coded pattern into using a C string (or char array), and the code becomes...

int speakerPin = 13;
int thedelay = 100;

char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
 
void setup() {}

void loop () {
  if (pat[0] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[1] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[2] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[3] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[4] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[5] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[6] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[7] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[8] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[9] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[10] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);
  if (pat[11] == 'x') tone(speakerPin, 400, 10);
  delay(thedelay);

  delay(thedelay*10); // pause between repetitions
}

Notice how above the code is highly repetitive -- perfect for a loop!

int speakerPin = 13;
int thedelay = 100;

char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
 
void setup()
{
}
 
void loop ()
{
    int i = 0;
    
    while (i<patlen) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(thedelay);
        i = i+1;
    }
    delay(thedelay*10);
}

If you prefer, a for loop can be used instead (they are identical! the for statement is in fact shorthand for doing what the while loop does above.

int speakerPin = 13;
int thedelay = 100;

char pat[] = "xxx xx x xx ";
int patlen = strlen(pat);
 
void setup()
{
}
 
void loop ()
{
    int i;
    for (i=0; i<12; i+=1) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(thedelay);
    }
    delay(thedelay*10);
}

Now, we remove the hard-coded length of the pattern (12) to use C's strlen function so that the pattern can be any length.

int speakerPin = 13;
int thedelay = 100;

char pat[]  = "x xx xxx xxxx xxxxx ";
int patlen = strlen(pat);
 
void setup()
{
}
 
void loop ()
{
    int i = 0;
    while (i<patlen) {
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(10);
        i = i+1;
    }

    delay(thedelay*10);
}

Here's a start at playing two parts (nearly simultaneously):

int speakerPin = 13;
int thedelay = 100;

char pat[]  = "x xx xxx xxxx xxxxx ";
int patlen = strlen(pat);
 
void setup()
{
}
 
void loop ()
{
    int i = 0;
    int i2 = 0;
    while (i<patlen) {
        i2 = i+5;
        if (i2 >= patlen) i2 = i2 - patlen;
        //  maybe the % modulo operator could help here!!!
        
        if (pat[i] == 'x') tone(speakerPin, 400, 10);
        delay(10);
        if (pat[i2] == 'x') tone(speakerPin, 800, 10);
        delay(thedelay);

        i = i+1;
    }

    delay(thedelay*10);
}

Laura's Clapping Music with Arduino

Laurier's Clapping Music with Arduino and button