Go Down

Topic: piezo + leds (Read 1 time) previous topic - next topic

nmuturi

May 11, 2012, 04:50 am Last Edit: May 11, 2012, 11:22 pm by AWOL Reason: 1
I'm doing a project where I'm trying to correspond a flashing led with a note made by my piezo element. I have 6 different notes and therefore 6 leds. Some leds will flash more than others depending on how many times that note is played in the song (twinkle twinkle little star)
I'm trying to add an if then statement in the loop but I do not know how to do one in this situation. I'm trying to say if note 'a' played led '3' high for example (not literal example in this code) but I do not know how to separate the piezo notes from their current 'i' increments
here is what i have so far
Code: [Select]
int speakerPin = 9;

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;
int ledPins[] = {2,3,4,5,6,7};

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
  for (int i = 0; i < 8; i++) {
    if (names[i] == note) {
      playTone(tones[i], duration);
    }
  }
}

void setup() {
  pinMode(speakerPin, OUTPUT);
  pinMode(ledPins[0],OUTPUT);
  pinMode(ledPins[1],OUTPUT);
  pinMode(ledPins[2],OUTPUT);
  pinMode(ledPins[3],OUTPUT);
  pinMode(ledPins[4],OUTPUT);
  pinMode(ledPins[5],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);
     digitalWrite(ledPins[0], HIGH);
  delay (100);
  digitalWrite(ledPins[0], LOW); 

    }
   


Moderator edit: There are really, really good reasons we use [font=Verdana][[/font]code] [font=Verdana][[/font]/code] tags when posting code.
Did you read this before posting?

marco_c

#1
May 11, 2012, 10:55 pm Last Edit: May 11, 2012, 11:03 pm by marco_c Reason: 1
The delay() statement in the main loop will stop anything happening for 100ms. This is probably going to make your music sound jerky.

One solution is to turn the LED on before you ptay the note, play the note, and then turn it off afterwards. The LED is on while the note is playing and it sounds more seamless. Like this:
Code: [Select]

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


Now to address which LED pin you should be using. I am not sure how you have one LED per note when you have 8 notes { 'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C' } and only 6 LED pins {2,3,4,5,6,7}, so that is one problem you need to fix. However, the key for you is that in playNote() you work out the array index of the note. That can be used as the array index of the ledpins array BUT you need to be turning the LED on and off to the playNote function:

Code: [Select]

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 < (sizeof(names)/sizeof(char)); i++) {
    if (names[i] == note) {
      digitalWrite(ledPins[i], HIGH);
      playTone(tones[i], duration);
      digitalWrite(ledPins[i], LOW); 
    }
  }
}


You'll note I have also changed some other stuff in the function - 'magic' numbers like 8 are always a problem in code when you come back later in life, so writing a formula to work out the size is more maintainable (you may want to think about length = 15 in the same way). Also, the comparison needs to be to names indexed by i, not names - a big clue is if you are doing a loop and are not using the loop index anywhere in the loop then you may have a issue with the code. You have the same problem with the notes variable in the main loop, but I will let you discover and fix it for yourself  :)

Clearly if you are using this new function you need to remove turning the LED on in the main loop:
Code: [Select]

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


Arduino libraries http://arduinocode.codeplex.com
Parola for Arduino http://parola.codeplex.com

kculm

Hay nmuturi,

Did you ever get this to work. I am trying to do the same thing but with El Wire. I tool you code that you had posted. (Hope that's ok) and modified it a bit.

I got it to work. Well I got sound and things light up that is.  But not the way I would like to. Right now it's light up a different El wire per tone not note.

If you worked it out can you post the code.

I am working on it but, I just started playing with Arduion a few days ago and I am just learning the code.

Thanks

kculm

HI sydney.

Like I was saying in my last post I am just starting out with all of this.  I needed a hobby.

Can you explain what you mean by "you work out the array index of the note" and maybe point me in the right direction


Thanks

Go Up