Hi, I am working on a project in which I need to play a melody on a monophonic buzzer, what I need is to apply 5v to the buzzer to make it sound, a simple example of what I need is the "blink" sketch, now the thing is that while that is happening I have to read some sensors and stuff, so I cannot do it with delay, then comes the option blinkWithoutDelay (https://www.arduino.cc/en/Tutorial/BlinkWithoutDelay) using millis(), that is pretty useful, but still it is very inconvenient to access a function that checks if the buzzer should be on or off to follow the melody while doing other things.
After all my question is if there is another simpler way, keep in mind that the melody may not be a simple waveform like the blink, it may be for example --.--.-.--.-.--.-..-.--- (- silence, . sound) and then repeat. One thing I thought about is about a library that can make a pin work in that way by assigning it the melody that i want to play or something (i don't know how to create libraries however but if may be helpful I can learn)
Thanks in advance =]
If that is like morsecode, you can store the pattern in EEPROM.
One bit for each time-tick.
Your pattern : "--.--.-.--.-.--.-..-.---" can be stored as 001001010010100101101000 (3 bytes)
Rggmiranda:
After all my question is if there is another simpler way, keep in mind that the melody may not be a simple waveform like the blink, it may be for example --.--.-.--.-.--.-..-.--- (- silence, . sound) and then repeat.
First you think what you will need.
Then you think about a suitable data structure to use.
It's not morse code you are talking about, or is it?
And the melody you are playing is not only "monophonic" (only one tone at the same time), but it is also "monotone" (always the same tone pitch)?
So it's not more than on/off switching in a given time pattern?
knut_ny:
If that is like morsecode, you can store the pattern in EEPROM.
One bit for each time-tick.
Your pattern : "--.--.-.--.-.--.-..-.---" can be stored as 001001010010100101101000 (3 bytes)
jurs:
First you think what you will need.
Then you think about a suitable data structure to use.It's not morse code you are talking about, or is it?
And the melody you are playing is not only "monophonic" (only one tone at the same time), but it is also "monotone" (always the same tone pitch)?
So it's not more than on/off switching in a given time pattern?
Thanks for answering, both of you are right, it is just morsecode basically, the thing would be to access different combinations (songs), besides that i want to be able to do a volume increase, but that can be achieved by injecting a pwm on a transistor apart from the morse generation, so no worries about it .
What do you suggest then?
a quarter note takes 300ms (@ 200 beats/min) =>2.4 sec of 'music' /byte
UNO has 1KB of EEPROM => 40 min total... or eg. 10 different 4 patterns og 4 mins
knut_ny:
a quarter note takes 300ms (@ 200 beats/min) =>2.4 sec of 'music' /byte
UNO has 1KB of EEPROM => 40 min total... or eg. 10 different 4 patterns og 4 mins
Can you please explain me how to implement that? i know how to write in EEPROM but I am not understanding how to play "music" with that
It is extremely complex coding. Are you prepared for that?
aarg:
It is extremely complex coding. Are you prepared for that?
I am ready, come at me bro!
It would involve using a hardware timer. I would have a look around to see if other people have done it already...
aarg:
It would involve using a hardware timer. I would have a look around to see if other people have done it already...
Would i still be able to compile it with arduino? I've checked the tone function which creates a waveform of a specified frequency at a duty cicle of 50%, something similar may be possible but with my morse code?
Yes, but I think the tone() function is blocking, so you can't continue to read sensors like you said you wanted to.
Also, you have me a little confused. Are you doing morse code, or music?
aarg:
Yes, but I think the tone() function is blocking, so you can't continue to read sensors like you said you wanted to.Also, you have me a little confused. Are you doing morse code, or music?
Ahh, I understand, I though it could work on parallel, I actually implemented a method with millis, but I have to call it all the time while going into the other method for reading the sensors, and it is very inconvenient, I may do it that way if nothing else is possible.
I am trying to play a morse-code-like melody, for an alarm, like a bip bip biiiip bip biiiip bip bip bip...
millis() isn't a magic solution to running tasks concurrently. It usually won't work with any functions that block (i.e. don't return within a few hundred microseconds).
Why do you need to continue sampling the sensors while the alarm is playing?
aarg:
Yes, but I think the tone() function is blocking,
It is not.
oqibidipo:
It is not.
In my defense, that's not documented. Or, at least, you have to read between the lines:
Only one tone can be generated at a time. If a tone is already playing on a different pin, the call to tone() will have no effect. If the tone is playing on the same pin, the call will set its frequency.
If it was blocking, you couldn't call it while it is playing. So yes, it couldn't be blocking. But it's about as clear as mud. Perhaps the tutorial makes it clearer?
Anyway, for a " bip bip biiiip bip biiiip bip bip bip" you have to let the tone expire before you start another one or you would get a continuous tone.
However since you said, "what I need is to apply 5v to the buzzer to make it sound", I worry that you may be trying to use a buzzer with an internal oscillator. If that is the case, you can't use tone(), you would just toggle the buzzer with a transistor connected to a pin. Incidentally, you shouldn't connect a piezo directly to a pin. You need some kind of current limiting.
So, yeah, you can assemble this program from available code. You just have to specify, break it down and code it.
this code 'plays' from EEPROM.. (any rubbish in there)
/*
Timer 1, Interrupt test.
(timer 1 used by servo_lib .. and others)
*/
#include <EEPROM.h>
#define ledPin 13 // change pin to buzzer
const int timer1_counter = 50000; // 65500=superfast, 1=sloooow
int playStart, playNow, playEnd=1000; // all reffering til bit_number in EEPROM
// note: "music bit 0" is MSB of address 0
boolean musicOn=false;
byte aa; //test purpose
void setup()
{
Serial.begin(9600);
pinMode(ledPin, OUTPUT);
noInterrupts();
TCCR1A = 0;
TCCR1B = 0;
TCNT1 = timer1_counter; // load timer
TCCR1B |= (1 << CS12); // prescale: 256
TIMSK1 |= (1 << TOIE1); // timer1 mask register. (set bit 0 i timer mask)
interrupts();
}
void start_music (int startAddr, int numberOfBits)
{
playStart = startAddr; // start playing from beginning of this 'track'
playNow = startAddr;
playEnd = numberOfBits;
musicOn=true;
TIMSK1 |= (1); // timer1 mask register. (set bit 0 i timer mask)
}
void stop_music()
{
TIMSK1 &= (0xFE); // clear bit 0 (TOIE1)
digitalWrite(ledPin,0); // Turn off sound
}
ISR(TIMER1_OVF_vect) // now play this 'tone', then point to next
{
TCNT1 = timer1_counter; // reload..
int myByte=playNow>>3; // get byte address of EEPROM
// get the byte from EEPROM
byte value = EEPROM.read(myByte);
byte myBit = playNow & 7; // low 3 bit
digitalWrite(ledPin, (value & (0x80 >> myBit))); // set or clear buzzer
playNow++;
if (playNow>playEnd) playNow=playStart; // restart track - no overshoot into 'next' track
}
void loop()
{
if (!musicOn) // if no music ? turn on
{
start_music(0,1000); // send values for playStart and playEnd (add parameter for speed ?)
}
Serial.print('.');
aa+=1;
if (aa>60) {aa=0; Serial.println(); }
// code
// something to stop/restart music
}