I found the HIGH time significantly longer than the LOW time. I thought maybe the processing of the "if" conditional might actually make some difference so I swapped HIGH/LOW and still the HIGH signal is about 3 times longer than the LOW signal averaging about 11.5us HIGH and 3.7us LOW with the above code regardless.
Is there something that's inherently more difficult / time consuming to raise vs lower the signal? 3x timing difference is pretty significant. I haven't looked into the low level programming on the UNO to see how the control registers are modified but there seems to be something wrong.
LarryD, is that using my sketch or your sketch and which Arduino?
Your sketch did make the HIGH and LOW signal times the same. Unfortunately, they are both now 11.7us. The goal really wasn't to make the HIGH and LOW signal times the same but determine why directly writing HIGH and LOW takes different amounts of time.
Adding the significant CPU cycle overhead of digitalRead-ing what I was tracking via the static integer wasn't what I had in mind but thanks for the cool snippet for future use.
I can't think of a faster way to turn pins on and off ... What does your scope meter show... Mine isn't the best to look at this? but it still looks quite interesting.
void setup() {
DDRD = DDRD | B11111100;// Pins 2-7 digital out
}
void loop() {
// cycle the pins 2~7 on and off 4 times before looping
PORTD = B11111100;//Pins 2~7 0n
PORTD = B00000000;//Pins 2~7 0ff
PORTD = B11111100;//Pins 2~7 0n
PORTD = B00000000;//Pins 2~7 0ff
PORTD = B11111100;//Pins 2~7 0n
PORTD = B00000000;//Pins 2~7 0ff
PORTD = B11111100;//Pins 2~7 0n
PORTD = B00000000;//Pins 2~7 0ff
}
To be precise you would need to be Deactivating timer0 to prevent millis to run at the wrong time and also don't use the loop default behavior to switch because tons of invisible tests and actions happens before returning to the top of the loop. A while(true) inside the loop with 10000 PORTB pairs of commands as of the previous post will lead to no extra parasiting activities for quite many cycles enough for your scope to offer reasonable measure. I'll try on mine later today and share
So I ran your original code on my arduino UNO and it does not appear to be massively different between on and off
(1 horizontal division is 4 micro second)
scope has hard time to sync because of jitter introduced by the looping. a full on / off cycle is about 12,8 micro seconds
Now if you use the low level controls on PORT, in a while loop, with on and off repeated thousands of time, you get this
(1 horizontal division is 200 nano second)
in that case a full on off cycle is 280 nano seconds - This is almost 46 times faster and that gives you a sense for the cost of the abstraction code for digitalWirte....
this is the code, for upload size reason I removed almost all the on/off lines, just copy & past the 2 lines plenty of times instead of the comment in the middle of the loop
#define JPIN 8
void setup() {
pinMode(JPIN, OUTPUT); // PORTB on UNO = digital pin 8 to 13
}
void loop() {
while (true) { // avoid looping cost
PORTB |= B00000001; // pin 8 HIGH
PORTB &= B11111110; // pin 8 LOW
PORTB |= B00000001; // pin 8 HIGH
PORTB &= B11111110; // pin 8 LOW
// ... REPEAT THIS PATTERN 10000 TIMES
PORTB |= B00000001; // pin 8 HIGH
PORTB &= B11111110; // pin 8 LOW
}
}
Thanks sailogreg for your post. I knew there was some overhead each time we looped but I didn't realize how much it added up!
This is the main() function that calls the loop function:
Simplified version full code is found in main.cpp
int main(void)
{
init();
initVariant();
setup();
for (;;) {
loop();
if (serialEventRun) serialEventRun();
}
return 0;
}
calls code in HardwareSerial.cpp every time you release for looping
Now my question is how close does it get with out releasing our loop back to the main program
#define JPIN 8
void setup() {
pinMode(JPIN, OUTPUT); // PORTB on UNO = digital pin 8 to 13
}
void loop() {
for (;;) {
PINB = 1;
PINB = 4;
}
}
How fast is this?
My scope shows a frequency of near 2MHZ
but I also see a gap that appears but I i am not able analyze this
I also compared it to using the loop() to cycle which is about 500kHz:
Why does digitalWrite HIGH vs digitalWrite LOW take different amounts of time?
The supporting code is what makes the time interval different. if you skip the serial input check and turn of the timer as I did here but still use digitalWrite() the times look to be close if not exact.
void setup() {
pinMode(8, OUTPUT);
TIMSK0 = 0; // disable timer0 interrupts
}
void loop() {
bool i; // don't need to make it static
for (;;) {
digitalWrite( 8,i);
i=!i;
}
This ran at 95.2kHz I'm not sure of the difference in times. They look close according to my scope meter but could you check? My scope meter isn't designed to measure this closely.
What is interesting is, if you don't need to test for serial input (Adding if( ; ; ){your code}) and you disable timer0 ( TIMSK0 = 0 ; // disable timer0 interrupts ) you could end up with a super fast cycle time without any interrupts during execution with a max loop rate of about 2 MHz with only one direct command to pins.