I need to control a 24 kHz ultrasonic transducer and decided to use an arduino uno I have lying around.
Using tone()
or the atmega's hardware pwm is not very suitable because I need two 50/50 square waves with a phase difference of pi (which is equal to two XOR'ed pins) to switch the output polarity of the h-bridge synchronously. As the uC dosen't have anything else to do I wrote the following sketch where I just wait for an interrupt and toggle pins 2&3:
bool do_task=false;
void timer_init () {
TCCR0A |= (1 << WGM01);
OCR0A = 83;
TIMSK0 |= (1 << OCIE0A);
TCCR0B |= (1 << CS01);
}
ISR (TIMER0_COMPA_vect) {
do_task=true;
}
bool state=false;
void toggle() {
state=!state;
digitalWrite(2,state);
digitalWrite(3,!state);
}
void setup() {
pinMode(2,OUTPUT);
pinMode(3,OUTPUT);
timer_init();
}
void loop() {
if(do_task) {
do_task=false;
toggle();
}
}
I expected the output to have a frequency of ~24 kHz, but it is 500 Hz instead.
From my understanding:
- 16 MHz CPU frequency
- timer0 prescaler is 8 (
TCCR0B |= (1 << CS01)
) - output compare value (
OCR0A
) is 83
would result in a frequency of 16 MHz / 8 / 83 = 24096,4 kHz
-but as I mentioned- it's 500 Hz and doesn't seem to depend on the prescaler.
digitalWrite()
are taking to long. It`s a rather big function. Use direct portmanipulation|=
digitalWrite()
so damn slow??! Why isn't it just a wrapper function for direct port manipulation?