problem using a created function instead of tone()

Hi, well...i've been trying to use a created function to generate a square wave out of pin 13.
The idea is to play a melody, so i defined each note frequency value, created an array "Melody[]" for the notes and one called "Duration[]" for each note timing. Right now, im using Proteus 8 to simulate it; it works with tone() but it wont work with the created function, got any ideas??

The function i defined is this:

//void Square(int f) {
//int  t = (500/f);
//digitalWrite(spk,HIGH);
//delay(t);
//digitalWrite(spk,LOW);
//delay(t);
//}

//And my full code is this:

#define C4  261.63 
#define C4S 277.18
#define D4  293.66 
#define D4S 311.13
#define E4  329.63 
#define F4  349.23
#define F4S 369.99 
#define G4  392.00
#define G4S 415.30 
#define A4  440.00
#define A4S 466.16
#define B4  493.88 
#define C5  523.25
#define spk 13

int Melody[] =    {C4,C4,C4,F4,A4,
                   C4,C4,C4,F4,A4,
                   F4,F4,E4,E4,D4,D4,C4,
                   C4,C4,C4,E4,G4,
                   C4,C4,C4,E4,G4,
                   A4S,A4S,A4,A4,G4,G4,F4};
                   
int Duration[] = {100,200,200,100,100,
                  100,200,200,100,100,
                  100,100,100,100,100,200,400,
                  100,200,200,100,100,
                  100,200,200,100,100,
                  100,200,100,200,100,200,500};
                  
int i=0;

void setup() {
  pinMode(spk,OUTPUT);
  Serial.begin(9600);
}

void Square(int f) {
int  t = (500/f);
  digitalWrite(spk,HIGH);
  delay(t);
  digitalWrite(spk,LOW);
  delay(t);
}

void loop() {
  square(Melody[i]);
  delay(Duration[i]);
  i++;
  if (i>33) i=0;
}

Many problems there....

First, the math:

Square(C4);

will do:

int t = (500/f) = (int)(500 / 261.63) = (int)(1.911) = 1;

Square will then:

Set spk HIGH, delay 1mSec, set spk Low, delay 1mSec, then return. You then delay some 100's of mSec, and repeat for the next note. For each "note", you output a single high-going pulse to the speaker, not a square wave, and your cycle timing is way off, because of the integer math you're using to calculate the required period.

What you'll hear is, at best, a faint "pop" or "tick" from the speaker at intervals of 100, or 200, or 400, or 500 mSec.

You should look at how tone() works before trying to "improve" it.

Regards,
Ray L.

Thanks for the help and fast response Ray,

i just realized many mistakes i made (my bad ::slight_smile: ) and another way to make it work!

Oh and, just for the cause i corrected the function and the array type:

void Square(double f) {
double t = 1/(2*f);
  digitalWrite(spk,HIGH);
  delay(t);
  digitalWrite(spk,LOW);
  delay(t);
}

Now it needs to be in a looping state to generate the wave, ill deal with that some other day...

Drakkar:
Thanks for the help and fast response Ray,

i just realized many mistakes i made (my bad ::slight_smile: ) and another way to make it work!

Oh and, just for the cause i corrected the function and the array type:

void Square(double f) {

double t = 1/(2*f);
  digitalWrite(spk,HIGH);
  delay(t);
  digitalWrite(spk,LOW);
  delay(t);
}




Now it needs to be in a looping state to generate the wave, ill deal with that some other day...

You've actually changed nothing, because delay takes an integer argument. For finer resolution, you need to convert t to micro-seconds, and use something other than delay to do the delay. The right way to do it would be to use one of the hardware timers to generate the square wave. Doing it in software is never going to work terribly well.

Regards,
Ray L.

Once again, thank you Ray for the reply and help,

i was going to pay attention to another code i had, but i actually made it work. Therefore, to conclude the post, this is the code:

void Square(int f) {
int t = (1.0/(2*f))*1000000;
  digitalWrite(spk,HIGH);
  delayMicroseconds(t);
  digitalWrite(spk,LOW);
  delayMicroseconds(t);
}

After that, i just called the function in the loop as i needed, and it worked just fine.

Thanks again for the patience Ray, i was confused, but this was helpful.