Maximum speed of arduino Uno output switching

Hi,

I'd like to know what the maximum speed Arduino Uno can switch its outputs. In a project I need to generate a 125kHz square wave (I'm trying to do something similar to this: http://scanlime.org/2008/08/simplest-rfid-reader/). So I put together a piece of code closely mirroring the 'BlinkWithoutDelay' example; but using micros() instead of millis(); and using a 4 microsecond switching interval (half-period) I expected to get a ~125kHz square wave.

When I measured it on the scope it was only about 30kHz. I think uploaded the following code:

================ void setup() { pinMode(13, OUTPUT); }

void loop() { digitalWrite(13, HIGH); digitalWrite(13, LOW);

}

i.e. Blink example but without any delays; and the square wave I measured a frequency of about 119kHz on my scope. So to me it seems that I cannot implement this project on an arduino Uno because I need a 125kHz square wave generated in the background whilst a whole load of other stuff is going on; but if I tell it to do nothing but toggle I can still only get 119kHz out of it.

This doesn't seem right given a clock speed of 16MHz. Am I missing something obvious or is there a better way of doing this?

  • Khalid

A quick update - I have just discovered the 'tone()' function which appears to be able to do what I need; and have tested it at 125kHz - and it seems to put that out OK (and I presume I can run other code after calling tone() without this being affected).

However; I ideally want to produce a differential square wave; for example to produce it between pin 2 and 4 I had intended to do a loop of:

  • put pin 2 high, and pin 4 low
  • wait half a period
  • put pin 2 low and pin 4 high
  • wait half a period

so that the carrier wave measured from pin 2 to pin 4 went from +5V to -5V. I could see how to do this with 'delayMicroseconds()' or 'micros()', but not sure if/how I can do it using the tone() function. Any ideas?

how I can do it using the tone() function

Hack the tone library and output the complementary signal as well. You could also change the PWM frequency and use that to generate the signal. If it were me I would just put an inverter on the output because any software solution is going to involve both outputs being the same for a short time and that is going to cause you shoot through problems on the FET coil drivers.

Hi, Mike is right about just using hardware inverter...

Some How-To about changing the PWM frequency here: http://arduino-info.wikispaces.com/Arduino-PWM-Frequency

Regards, Terry King ...In The Woods In Vermont terry@yourduino.com

Or you may use a transistor to inverted without inverter if a alight voltage drop is not a problem.

Or use direct port manipulation.

AWOL: Or use direct port manipulation.

When using direct port manipulation you can use the PINx registers (PINB, PINC, PIND) to toggle a set of output pins in a single output port with a single write:

PIND = 0b00001100; // Toggle digital pins 2 and 3 (PORTD, bit 2 and PORTD, bit 3)

PIND = 0b00001100; // Toggle digital pins 2 and 3

Toggle or set?

PaulS:

PIND = 0b00001100; // Toggle digital pins 2 and 3

Toggle or set?

Toggle. Invert. Flip. XOR with 1. That's what the PIN register does. That's what makes it different from the PORT register.

That's what makes it different from the PORT register.

I'll try to remember that. Don't hold your breath, though.