Operácie

Acrob005: Rozdiel medzi revíziami

Z SensorWiki

(Advanced example)
 
(7 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 33: Riadok 39:
 
=== How it works ===
 
=== How it works ===
  
=== Why robot needs to play music? ===
+
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.
  
=== Advanced example ===
+
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.
  
Following example shows more sound effects. It comes from the http://www.arduino.cc/en/Tutorial/PlayMelody
+
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.  
with just one minor (but important) change:  variable <TT>tone</TT> is renamed to <TT>note</TT> as the name tone
+
  tone(SPEAKER, 2000);        // 2kHz, forever
makes collision with the same command.  
+
  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
  
<source lang="cpp">
+
=== Your turn ===
/* Play Melody
 
* -----------
 
*
 
* 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
+
Try to examine loudness of the speaker at the different frequencies. Did You notice the change?
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  ==========================================
 
// 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 ============================================
+
=== Why robot needs to play music? ===
// 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() {
+
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.
  pinMode(speakerOut, OUTPUT);
 
  if (DEBUG) {
 
    Serial.begin(9600); // Set serial out if we want debugging
 
  }
 
}
 
  
// MELODY and TIMING  =======================================
+
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.  
//  melody[] is an array of notes, accompanied by beats[],
 
//  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
+
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
long tempo = 10000;
+
batteries are weak), this also generates the RESET signal. This is unfortunately not visible so You can sometimes find Your robot behaviour very strange.
// 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
+
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.
int note = 0;
 
int beat = 0;
 
long duration  = 0;
 
  
// PLAY TONE  ==============================================
+
'''And why there is a label on the speaker?''' (Remove seal after washing)
// Pulse the speaker to play a tone for a particular duration
 
void playTone() {
 
  long elapsed_time = 0;
 
  if (note > 0) { // if this isn't a Rest beat, while the tone has
 
    //  played less long than 'duration', pulse speaker HIGH and LOW
 
    while (elapsed_time < duration) {
 
  
      digitalWrite(speakerOut,HIGH);
+
See http://www.sonitron.be/site/subpage.php?primid=7&hid=8
      delayMicroseconds(note / 2);
 
  
      // DOWN
+
=== Advanced example ===
      digitalWrite(speakerOut, LOW);
 
      delayMicroseconds(note / 2);
 
  
      // Keep track of how long we pulsed
+
Following example shows more sound effects. It comes from the  http://www.arduino.cc/en/Tutorial/Melody
      elapsed_time += (note);
+
with just one minor (but important) change: the pinnumber is 4, not 9.
    }
 
  }
 
  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 =============================
+
<source lang="cpp">
void loop() {
+
#define SPEAKER_Pin 4
  // 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
+
  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;
  
    playTone();
+
void playTone(int tone, int duration)
    // A pause between notes...
+
{
    delayMicroseconds(pause);
+
  for (long i = 0; i < duration * 1000L; i += tone * 2)
 
+
  {
    if (DEBUG) { // If debugging, report loop, tone, beat, and duration
+
    digitalWrite(SPEAKER_Pin, HIGH);
      Serial.print(i);
+
    delayMicroseconds(tone);
      Serial.print(":");
+
    digitalWrite(SPEAKER_Pin, LOW);
      Serial.print(beat);
+
    delayMicroseconds(tone);
      Serial.print(" ");   
+
  }
      Serial.print(note);
 
      Serial.print(" ");
 
      Serial.println(duration);
 
    }
 
  }
 
 
}
 
}
  
/*
 
* 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'
 
*/
 
  
 
+
void playNote(char note, int duration)
</source>
+
{
 
+
   char names[] = { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' };
<source lang="cpp">
+
  int tones[] = { 1915, 1700, 1519, 1432, 1275, 1136, 1014, 956 };
 
 
int speakerPin = 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(speakerPin, HIGH);
 
    delayMicroseconds(tone);
 
    digitalWrite(speakerPin, 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
 
   // play the tone corresponding to the note name
Riadok 226: Riadok 117:
 
}
 
}
  
void setup() {
+
 
   pinMode(speakerPin, OUTPUT);
+
 
 +
void setup()
 +
{
 +
   pinMode(SPEAKER_Pin, OUTPUT);
 
}
 
}
  
void loop() {
+
 
 +
void loop()
 +
{
 
   for (int i = 0; i < length; i++) {
 
   for (int i = 0; i < length; i++) {
 
     if (notes[i] == ' ') {
 
     if (notes[i] == ' ') {
Riadok 239: Riadok 135:
  
 
     // pause between notes
 
     // pause between notes
     delay(tempo / 2);  
+
     delay(tempo / 2);
 
   }
 
   }
 
}
 
}
Riadok 245: Riadok 141:
 
</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 >