Operácie

Acrob005: Rozdiel medzi revíziami

Z SensorWiki

(Make Music)
 
(8 medziľahlých úprav od rovnakého používateľa nie je zobrazených.)
Riadok 1: Riadok 1:
 +
 +
[[Acrob004|< Previous]] | [[Acrob|Home]] | [[Acrob006|Next >]]
 +
 
== Make Music ==
 
== Make Music ==
  
Riadok 11: Riadok 14:
 
void setup()
 
void setup()
 
{
 
{
 +
 
// Example 1: tone of specified frequency and duration
 
// Example 1: tone of specified frequency and duration
  
Riadok 16: Riadok 20:
  
 
   delay(500);    //small pause
 
   delay(500);    //small pause
 +
 +
// Example 2: tone of specified frequency without duration
 
    
 
    
   tone(SPEAKER, 3000);        // 2kHz, forever
+
   tone(SPEAKER, 2000);        // 2kHz, forever
 
   delay(1000);                 
 
   delay(1000);                 
 
   noTone(SPEAKER);            // turn off sound.
 
   noTone(SPEAKER);            // turn off sound.
Riadok 32: Riadok 38:
  
 
=== How it works ===
 
=== How it works ===
 +
 +
First, notice that we don't have anything in the loop section. This is OK, as we need just one tone, not
 +
eternal noisemaking board.
 +
 +
At the first line we define symbolic name for the pin to which is the speaker connected. It makes life easier.
 +
For generating tones there is a command (not surprisingly) <TT>tone</TT> Its first parameter is name of the pin where the sound should be sent. Second parameter is a frequency in [Hz] of the tone and (optional) third parameter is the length of the tone. Following example plays tone of the frequency
 +
4000 Hz (4kHz) for period of 1 second.
 +
 +
  tone(SPEAKER, 4000, 1000);  // 4kHz, 1 sec.
 +
 +
It is not necessary to specify the length of the tone, then it sounds until another command changes its state. The example below does the same as the previous one.
 +
  tone(SPEAKER, 2000);        // 2kHz, forever
 +
  delay(1000);
 +
  noTone(SPEAKER);            // turn off sound.
 +
The main (and important) difference is, that here the processor is stalled for 1 second whereas in the first example the sound is generated independently and after the sound start the processor continues with another commands.
 +
 +
 +
'''But how the piezospeaker works?'''
 +
 +
See http://www.sonitron.be/site/contentpage.php?primid=15
 +
 +
=== Your turn ===
 +
 +
Try to examine loudness of the speaker at the different frequencies. Did You notice the change?
 +
  
 
=== Why robot needs to play music? ===
 
=== Why robot needs to play music? ===
  
=== Advanced example ===
+
Microprocessor needs to be RESET before it starts its normal operation. This means that the processor will be setuped into the defined initial state. RESET signal is coming from various sources. One of them is the RESET button on Your board. So You can initialize the processor anytime You find it dead-locked. Another RESET signal comes from the programming interface. When You download new program to the board, it is also initialized before your program starts.
  
Following example shows more sound effects. It comes from the http://www.arduino.cc/en/Tutorial/PlayMelody
+
And last, but not least, there is also Power-Up reset system. There is a subcircuit in the internal processor system designed to watch the actual voltage level at the power pins. This prevents to start processor operation during the unstable power-up phase. The operation starts when the power supply is high enough to ensure proper operation of the processor.  
with just one minor (but important) change:  variable <TT>tone</TT> is renamed to <TT>note</TT> as the name tone
 
makes collision with the same command.  
 
  
<source lang="cpp">
+
This also means, that when Your processor is operated from the batteries and suddenly the battery voltage decreases (e.g when motors require more power and
/* Play Melody
+
batteries are weak), this also generates the RESET signal. This is unfortunately not visible so You can sometimes find Your robot behaviour very strange.
* -----------
 
*
 
* Program to play a simple melody
 
*
 
* Tones are created by quickly pulsing a speaker on and off
 
*  using PWM, to create signature frequencies.
 
*
 
* Each note has a frequency, created by varying the period of
 
*  vibration, measured in microseconds. We'll use pulse-width
 
*  modulation (PWM) to create that vibration.
 
  
* We calculate the pulse-width to be half the period; we pulse
+
To solve this problem it is a good idea to add single beep in setup() part of your programm. In the case Your batteries are too weak, you can be sure that Your robot will get into the RESET condition very often (e.g. during the motor start). So when You listen sudden beep during your robot operation, it's likely time to change (or recharge) batteries.  
the speaker HIGH for 'pulse-width' microseconds, then LOW
 
*  for 'pulse-width' microseconds.
 
*  This pulsing creates a vibration of the desired frequency.
 
*
 
* (cleft) 2005 D. Cuartielles for K3
 
* Refactoring and comments 2006 clay.shirky@nyu.edu
 
* See NOTES in comments at end for possible improvements
 
*/
 
  
// TONES  ==========================================
+
'''And why there is a label on the speaker?''' (Remove seal after washing)
// Start by defining the relationship between
 
//      note, period, &  frequency.
 
#define  c    3830    // 261 Hz
 
#define  d    3400    // 294 Hz
 
#define  e    3038    // 329 Hz
 
#define  f    2864    // 349 Hz
 
#define  g    2550    // 392 Hz
 
#define  a    2272    // 440 Hz
 
#define  b    2028    // 493 Hz
 
#define  C    1912    // 523 Hz
 
// Define a special note, 'R', to represent a rest
 
#define  R    0
 
  
// SETUP ============================================
+
See http://www.sonitron.be/site/subpage.php?primid=7&hid=8
// Set up speaker on a PWM pin (digital 9, 10 or 11)
 
int speakerOut = 9;
 
// Do we want debugging on serial out? 1 for yes, 0 for no
 
int DEBUG = 1;
 
  
void setup() {
+
=== Advanced example ===
  pinMode(speakerOut, OUTPUT);
 
  if (DEBUG) {
 
    Serial.begin(9600); // Set serial out if we want debugging
 
  }
 
}
 
  
// MELODY and TIMING  =======================================
+
Following example shows more sound effects. It comes from the  http://www.arduino.cc/en/Tutorial/Melody
// melody[] is an array of notes, accompanied by beats[],
+
with just one minor (but important) change: the pinnumber is 4, not 9.  
// which sets each note's relative length (higher #, longer note)
 
int melody[] = {  C,  b,  g,  C,  b,  e,  R,  C,  c,  g, a, C };
 
int beats[]  = { 16, 16, 16,  8,  8,  16, 32, 16, 16, 16, 8, 8 };
 
int MAX_COUNT = sizeof(melody) / 2; // Melody length, for looping.
 
  
// Set overall tempo
+
<source lang="cpp">
long tempo = 10000;
+
#define SPEAKER_Pin 4
// Set length of pause between notes
 
int pause = 1000;
 
// Loop variable to increase Rest length
 
int rest_count = 100; //<-BLETCHEROUS HACK; See NOTES
 
  
// Initialize core variables
+
  int length = 15;                                              // the number of notes
int note = 0;
+
char notes[] = "ccggaagffeeddc ";                               // a space represents a rest
int beat = 0;
+
int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
long duration  = 0;
+
  int tempo = 300;
  
// PLAY TONE  ==============================================
+
void playTone(int tone, int duration)
// Pulse the speaker to play a tone for a particular duration
+
{
void playTone() {
+
   for (long i = 0; i < duration * 1000L; i += tone * 2)
   long elapsed_time = 0;
+
  {
  if (note > 0) { // if this isn't a Rest beat, while the tone has
+
    digitalWrite(SPEAKER_Pin, HIGH);
    //  played less long than 'duration', pulse speaker HIGH and LOW
+
    delayMicroseconds(tone);
    while (elapsed_time < duration) {
+
    digitalWrite(SPEAKER_Pin, LOW);
 +
    delayMicroseconds(tone);
 +
  }
 +
}
  
      digitalWrite(speakerOut,HIGH);
 
      delayMicroseconds(note / 2);
 
  
      // DOWN
+
void playNote(char note, int duration)
      digitalWrite(speakerOut, LOW);
+
{
      delayMicroseconds(note / 2);
+
  char names[] = { 'c',  'd',  'e',  'f',  'g',  'a',  'b', 'C'  };
 +
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
  
      // Keep track of how long we pulsed
+
  // play the tone corresponding to the note name
      elapsed_time += (note);
+
  for (int i = 0; i < 8; i++) {
     }  
+
    if (names[i] == note) {
 +
      playTone(tones[i], duration);
 +
     }
 
   }
 
   }
  else { // Rest beat; loop times delay
 
    for (int j = 0; j < rest_count; j++) { // See NOTE on rest_count
 
      delayMicroseconds(duration); 
 
    }                               
 
  }                               
 
 
}
 
}
  
// LET THE WILD RUMPUS BEGIN =============================
 
void loop() {
 
  // Set up a counter to pull from melody[] and beats[]
 
  for (int i=0; i<MAX_COUNT; i++) {
 
    note = melody[i];
 
    beat = beats[i];
 
  
    duration = beat * tempo; // Set up timing
 
  
    playTone();
+
void setup()
    // A pause between notes...
+
{
    delayMicroseconds(pause);
+
  pinMode(SPEAKER_Pin, OUTPUT);
 +
}
  
    if (DEBUG) { // If debugging, report loop, tone, beat, and duration
+
 
      Serial.print(i);
+
void loop()
      Serial.print(":");
+
{
      Serial.print(beat);
+
  for (int i = 0; i < length; i++) {
      Serial.print(" ");   
+
    if (notes[i] == ' ') {
       Serial.print(note);
+
       delay(beats[i] * tempo); // rest
      Serial.print(" ");
+
    } else {
       Serial.println(duration);
+
       playNote(notes[i], beats[i] * tempo);
 
     }
 
     }
 +
 +
    // pause between notes
 +
    delay(tempo / 2);
 
   }
 
   }
 
}
 
}
 
/*
 
* NOTES
 
* The program purports to hold a tone for 'duration' microseconds.
 
*  Lies lies lies! It holds for at least 'duration' microseconds, _plus_
 
*  any overhead created by incremeting elapsed_time (could be in excess of
 
*  3K microseconds) _plus_ overhead of looping and two digitalWrites()
 
 
* As a result, a tone of 'duration' plays much more slowly than a rest
 
*  of 'duration.' rest_count creates a loop variable to bring 'rest' beats
 
*  in line with 'tone' beats of the same length.
 
*
 
* rest_count will be affected by chip architecture and speed, as well as
 
*  overhead from any program mods. Past behavior is no guarantee of future
 
*  performance. Your mileage may vary. Light fuse and get away.
 
 
* This could use a number of enhancements:
 
* ADD code to let the programmer specify how many times the melody should
 
*    loop before stopping
 
* ADD another octave
 
* MOVE tempo, pause, and rest_count to #define statements
 
* RE-WRITE to include volume, using analogWrite, as with the second program at
 
*          http://www.arduino.cc/en/Tutorial/PlayMelody
 
* ADD code to make the tempo settable by pot or other input device
 
* ADD code to take tempo or volume settable by serial communication
 
*          (Requires 0005 or higher.)
 
* ADD code to create a tone offset (higer or lower) through pot etc
 
* REPLACE random melody with opening bars to 'Smoke on the Water'
 
*/
 
 
  
 
</source>
 
</source>
  
 
 
[[Acrob02|Predošlá úloha...]] | [[Acrob|Späť do menu]] | [[Acrob03|Pokračovanie...]]
 
  
 
[[Acrob004|< Previous]] | [[Acrob|Home]] | [[Acrob006|Next >]]
 
[[Acrob004|< Previous]] | [[Acrob|Home]] | [[Acrob006|Next >]]

Aktuálna revízia z 12:05, 12. jún 2010

< Previous | Home | Next >

Make Music

Speaker is a small electronic device which can make sounds if appropriate driven. Lets connect the speaker to the Arduino pin D4 (see schematic diagram and connection diagram below) and program it to make few tones.

ArduinoSpeaker.png
#define SPEAKER 4  // Piezospeaker connected to pin 4

void setup()
{

// Example 1: tone of specified frequency and duration

  tone(SPEAKER, 4000, 1000);   // 4kHz, 1 sec.

  delay(500);     //small pause

// Example 2: tone of specified frequency without duration
  
  tone(SPEAKER, 2000);         // 2kHz, forever
  delay(1000);                 
  noTone(SPEAKER);             // turn off sound.
}

void loop()
{
  /* do nothing */
}

For more details about the tone command see the Reference


How it works

First, notice that we don't have anything in the loop section. This is OK, as we need just one tone, not eternal noisemaking board.

At the first line we define symbolic name for the pin to which is the speaker connected. It makes life easier. For generating tones there is a command (not surprisingly) tone Its first parameter is name of the pin where the sound should be sent. Second parameter is a frequency in [Hz] of the tone and (optional) third parameter is the length of the tone. Following example plays tone of the frequency 4000 Hz (4kHz) for period of 1 second.

 tone(SPEAKER, 4000, 1000);   // 4kHz, 1 sec.

It is not necessary to specify the length of the tone, then it sounds until another command changes its state. The example below does the same as the previous one.

 tone(SPEAKER, 2000);         // 2kHz, forever
 delay(1000);
 noTone(SPEAKER);             // turn off sound.

The main (and important) difference is, that here the processor is stalled for 1 second whereas in the first example the sound is generated independently and after the sound start the processor continues with another commands.


But how the piezospeaker works?

See http://www.sonitron.be/site/contentpage.php?primid=15

Your turn

Try to examine loudness of the speaker at the different frequencies. Did You notice the change?


Why robot needs to play music?

Microprocessor needs to be RESET before it starts its normal operation. This means that the processor will be setuped into the defined initial state. RESET signal is coming from various sources. One of them is the RESET button on Your board. So You can initialize the processor anytime You find it dead-locked. Another RESET signal comes from the programming interface. When You download new program to the board, it is also initialized before your program starts.

And last, but not least, there is also Power-Up reset system. There is a subcircuit in the internal processor system designed to watch the actual voltage level at the power pins. This prevents to start processor operation during the unstable power-up phase. The operation starts when the power supply is high enough to ensure proper operation of the processor.

This also means, that when Your processor is operated from the batteries and suddenly the battery voltage decreases (e.g when motors require more power and batteries are weak), this also generates the RESET signal. This is unfortunately not visible so You can sometimes find Your robot behaviour very strange.

To solve this problem it is a good idea to add single beep in setup() part of your programm. In the case Your batteries are too weak, you can be sure that Your robot will get into the RESET condition very often (e.g. during the motor start). So when You listen sudden beep during your robot operation, it's likely time to change (or recharge) batteries.

And why there is a label on the speaker? (Remove seal after washing)

See http://www.sonitron.be/site/subpage.php?primid=7&hid=8

Advanced example

Following example shows more sound effects. It comes from the http://www.arduino.cc/en/Tutorial/Melody with just one minor (but important) change: the pinnumber is 4, not 9.

#define SPEAKER_Pin 4

  int length = 15;                                              // the number of notes
char notes[] = "ccggaagffeeddc ";                               // a space represents a rest
 int beats[] = { 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 2, 4 };
  int tempo = 300;

void playTone(int tone, int duration)
{
  for (long i = 0; i < duration * 1000L; i += tone * 2)
   {
     digitalWrite(SPEAKER_Pin, HIGH);
     delayMicroseconds(tone);
     digitalWrite(SPEAKER_Pin, LOW);
     delayMicroseconds(tone);
   }
}


void playNote(char note, int duration)
{
  char names[] = { 'c',  'd',  'e',  'f',  'g',  'a',  'b', 'C'  };
   int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };

  // play the tone corresponding to the note name
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}



void setup()
{
  pinMode(SPEAKER_Pin, OUTPUT);
}


void loop()
{
  for (int i = 0; i < length; i++) {
    if (notes[i] == ' ') {
      delay(beats[i] * tempo); // rest
    } else {
      playNote(notes[i], beats[i] * tempo);
    }

    // pause between notes
    delay(tempo / 2);
  }
}


< Previous | Home | Next >