Hi,
I'm trying to use digitalWrite to create a square wave output from the digital pin of my Arduino Uno.
Here is the code that I'm using:
int frequency = 100; //Set frequency in Hertz
double delayTime = 1000 / (frequency * 2);
void setup()
{
pinMode(13, OUTPUT);
pinMode(11, OUTPUT);
}
void loop()
{
digitalWrite(11, LOW);
digitalWrite(13, HIGH);
delay(delayTime);
digitalWrite(13, LOW);
digitalWrite(11, HIGH);
delay(delayTime);
}
I checked with an oscilloscope and its able to output a square wave, however the frequency is slightly off.
Here's a table of the frequencies that I'm inputing via the code and the frequencies that I'm measuring with the oscilloscope.
This is not true. On Arduino UNO 1 machine code instruction takes from 1 to 4 CK. But the rest is important - one Arduino IDE (C++) command is translated into anything from one to thousands (or more?) machine code instructions.
If you want to generate exact square wave you must use timers (or assembly). If you don't mind some glitches can occur you may try to generate it in software via C but it is very crude way.
EDIT: I have read "same time" instead "some time". I am sorry for this.
Smajdalf:
This is not true. On Arduino UNO 1 machine code instruction takes from 1 to 4 CK. But the rest is important - one Arduino IDE (C++) command is translated into anything from one to thousands (or more?) machine code instructions.
If you want to generate exact square wave you must use timers (or assembly). If you don't mind some glitches can occur you may try to generate it in software via C but it is very crude way.
"This is not true."
I did not realize this, which instruction(s) take no time to execute?
Instead of delay(), use delayMicroseconds().
So 3.333 = 3333, and the result will be a number that is a multiple of 4uS (0.004mS).
3333/2 = 1666.5
Can also make the code account for that - write it blink without delay style, have one half check for say 1664 and the other for 1668, will get you pretty close to 3333.
"I did not realize this, which instruction(s) take no time to execute?"
Only the hardware running in the background kind, like the set & forget PWM outputs, or the 8 bits being clocked in & out of shift registers during a serial transfer.
CrossRoads:
"I did not realize this, which instruction(s) take no time to execute?"
Only the hardware running in the background kind, like the set & forget PWM outputs, or the 8 bits being clocked in & out of shift registers during a serial transfer.
Yes, after that fact, it is in hardware and not part of the program flow unless changed.
"Also, is there a way to make the output of pin 10 be the inverse of pin 9's output? Or should I use an inverter circuit instead?"
You could, but a simple transistor inverter circuit would work too.
Rizadon:
Also, is there a way to make the output of pin 10 be the inverse of pin 9's output?
Doing it in s/w will cause a delay between having both pins in the desired state that is much longer than if it is done in h/w from pin 9's output as you will have to set the output of both pins.
Depending on core you are using (AVR being the slowest), and the compiler version you are using, and the actual type of parameters being passed into digitalWrite(), that delay
can be in order of microseconds like around 4-6 on a 16mHz AVR.
(It can be MUCH longer if there are lots of interrupts being processed)
The delay/latency would be much smaller on parts like the pic32 or the ESP8266 which are in the 10s of nanoseconds to update a pin ouput since they have much better implementation of digitalWrite() and better internal h/w registers inside the micro-controller.
DigitalWrite() is particularly painful on the AVR because of the combination of the semantics of the API the digitalWrite() function and the wimpy way the AVR i/o ports work and AVR instructions needed to work around it to ensure atomicity of the register update.
Now if you use Pauls AVR Teensy boards, he ships his own core that did a MUCH better job of coding digitalWrite(). Under certain circumstances you can get around 140ns on a 16mhz AVR.
It requires using constants for the pin and value parameters.
But as larryd pointed out, a transistor is pretty simple and the latency between the update pin 9 and the transistor output will be measured in nano seconds and be very consistent regardless of what processor is driving the pin and regardless of what else is going on in the part like interrupts.