40 Hz Square wave with 8kHz tone

Hi, I am a researcher working on creating a sound output that is a square wave with a tone of 8kHz at 40Hz with a 50% duty cycle. I am trying to use the tone function, with inputs of my audio pin, 8000 for tone, and a 12.5 ms duration (to create the 40Hz frequency). The problem is that the tone function only accepts duration values in ms, and it only accepts integer values. Is there a better way that I can ensure that the sound will have a duration of exactly 12.5 ms on and then off, either using the tone function or a different one? Currently, the code I have written for it is tone(AudioPin, 8000, 12.5). The problem is that because it only accepts integer values for the last argument, tone reads that as 12 instead of 12.5.

Is it important the 8kHz is a sine wave? Can it be a square wave?

According to the reference, the tone function accepts frequency.

I seem to have misunderstood the question.

So you want to produce an 8khz tone for 12.5ms then no tone for 12.5ms then . . . ?

12.5ms can be achieved with a TIMER you code using the millis( ) function.

I forgot to mention but it needs to be a square wave

Yes, but I need to use the frequency to create the tone, and then I need that tone to be on for 12.5 ms, and off for 12.5 ms to create a sound played at 40 Hz

I need to repeat on for 12.5 ms and off for 12.5 ms to create a 40Hz frequency with a 50% duty cycle.

So you wish to create:

  • 8kHz Square wave
  • On for 12.5ms and off for 12.5ms

Is the processor doing anything else?

So you want to produce an 8khz tone for 12.5ms then, no tone for 12.5ms then, 8khz tone for 12.5ms then, no tone for 12.5ms etc. ?

Yes, that is ideal. I am also using the digitalWrite frunction to create a 40Hz blinking light.

Do you know how to create a TIMER using the millis( ) function ?

I do not. Would this also be able to generate the 8kHz tone?

Waiiting to see how that works.



  //is it time to toggle the heartbeat LED ?
  if (millis() - heartbeatMillis >= 250)
    //restart the TIMER
    heartbeatMillis = millis();

    //toggle the heartbeat LED
    digitalWrite(heartbeatLED, !digitalRead(heartbeatLED));

Above is a millis( ) TIMER that toggles a LED every 250ms.

You can use the tone( ) function for generating the sound and noTone( ) to turn it OFF

Yes, of course. :upside_down_face:

@wdunne welcome to the forum.
All these messages where we ask what you want is normal. It is not easy to describe exactly what you want, and we would like to know that because there are so many ways to make that signal.

Do you want the 8kHz in sync with the blinking light ? I assume you do.
How accurate do you want the 40 Hz ?
Can you add additional hardware ? A logic AND gate could create perfectly timed signals.
Which Arduino board do you want to use ? The most basic Arduino board is a Arduino Uno, and that one is perfect for these timing things.

For a not-so-accurate solution, I see the Arduino tone() function and a millis-timer for 40Hz.
For a reasonable accuracy, I see two hardware timers. One at 40Hz with a interrupt that turns on and off the light and the 8kHz timer. Since 40Hz is 200 times slower than 8kHz, perhaps it can be done with a single timer.
For a top-accurate solution, I see two hardware timers and a extra hardware AND logic chip.

That's not all ! Do you want a full pulse of the 8kHz or is it okay if that pulse it cut off in the middle.

I would suggest using delays. I know this is a bad word but I think, at least to get you going it would be the best way.

I'm not great with code but essentially you would:

  • Setup up a timer for 8kHz
  • Turn on the timer
  • delay(12)
  • delaymicroseconds(500)
  • turn off the timer
  • delay(12)
  • delaymicroseconds(500)
    Loop forever

I am looking for the 8kHz tone and the lights to be on for 12.5 ms and then off for 12.5 ms, and to repeat that. So I do need them to be synchronized. I am trying to make the circuit with as precise as possible with as little complexity as possible, so I cannot add additional hardware.

If I can use delayMicroseconds could I just use 12500 microseconds instead of doing it in two parts?

1 Like

The great thing about Arduino is you can try things out to see if they work :wink:

And you can look things up in the reference section :wink:


If you will be doing more than one thing at a time, you will need to write non-blocking code as in post #14.

1 Like