Go Down

Topic: Timing of various functions on ATMEGA 328P chip (Arduino Uno, Arduino Nano, etc) (Read 454 times) previous topic - next topic

ElectricLove

Hi, I spent some time today with my Oscilloscope and testing various functions of the ATMEGA chip.  I thought it would be worth it to someone else out there for me to share my findings.  These are taken with TekTronix TDS 2024C Oscilloscope, I used a digitalWrite (pin, HIGH); digitalWrite (pin, LOW); sequence to serve as the time marker and then just ran various sequences after that in order to see how long it would take to repeat the digitalWrite(pin, HIGH) command...  Since this allows for a detectable signal by the scope.

Pretty basic stuff and if anyone is interested in a more advanced functionality/sequence I'd be happy to test for you!

Here are the results:

Execute a digitalWrite(pin, value); ~4.1uS
Execute a digitalRead(pin); ~7uS
Execute a Serial.print(""); ~4uS PLUS ~1.04mS per character printed (example; Serial.print("hello"); 5 characters so it takes ~5.204mS.   NOTE: same timing regardless of baud-rate
Execute analogRead(pin); ~112uS
Execute analogWrite(pin, value); ~8.4uS
Generate a random number; random(); ~50uS
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); no perceptible time change

AWOL

Quote
Execute a Serial.print(""); ~4uS PLUS ~1.04mS per character printed (example; Serial.print("hello"); 5 characters so it takes ~5.204mS.   NOTE: same timing regardless of baud-rate
...but only if the transmit buffer is already full.
Not sure why it's the same value, irrespective of bit rate.

Quote
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); no perceptible time change
Need to try harder. You're fighting the optimiser.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Robin2

Pretty basic stuff and if anyone is interested in a more advanced functionality/sequence I'd be happy to test for you!
Please post the program you used to produce your results and explain how you use the 'scope to do the measurements


I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

larryd

Please post the program you used to produce your results and explain how you use the 'scope to do the measurements


I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R
Here is one way to measure code timing:
https://forum.arduino.cc/index.php?topic=445951.msg3597772#msg3597772   











No technical PMs.
The last thing you did is where you should start looking.

Robin2

Two or three hours spent thinking and reading documentation solves most programming problems.

AWOL

Indeed. But how did the OP do it ?

...R
Quote
These are taken with TekTronix TDS 2024C Oscilloscope, I used a digitalWrite (pin, HIGH); digitalWrite (pin, LOW);
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Robin2

I'd prefer to see the OP's program and his/her own description of the timing process.

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

ElectricLove

I'd prefer to see the OP's program and his/her own description of the timing process.

...R
The code is super basic; just activate the respective pins and run the short program.  I used the digitalWrite High followed by digitalWrite Low in order to create a visible time-stamp on the Oscilloscope, the length of that time-stamp also represents the amount of time it takes for a digitalWrite High...  digitalWrite Low command to execute.

Then I just put different functions in after that part of the code and used the scope to identify how much time between the peaks passed by, if it went from 4uS to 8uS then we can identify that it took 4uS for whatever was added to execute.

It is super basic but here it is...

"
void setup()
{
Serial.begin(9600);
pinMode(7, OUTPUT);
}

void loop()
{
  digitalWrite(7, HIGH);
  digitalWrite(7, LOW);
  //WHATEVER FUNCTION WE ARE MEASURING TIMING OF
}
"

And, yes regardless of whether Serial.begin(value) is set to 9600 or 115200 or even 250000; the results of the timing of Serial.print(""); are the same...

I will try the digitalWriteFast commands and see what difference it makes.

Also; what do you mean by "fighting the optimiser" give me a math function to test and I'll be happy to see the effect...


Robin2

Also; what do you mean by "fighting the optimiser" give me a math function to test and I'll be happy to see the effect...
If the compiler sees that the result of a calculation is never used it just leaves the calculation out of the code.

One way to deal with that is to declare your variables volatile as in
Code: [Select]
volatile int myVal;

...R
Two or three hours spent thinking and reading documentation solves most programming problems.

ElectricLove

Please post the program you used to produce your results and explain how you use the 'scope to do the measurements


I would be interested to see the results for digitalWriteFast() and digitalReadFast() from the digitalWriteFast library

...R
To test digitalWriteFast()

Executed the following code:

"
#include <digitalWriteFast.h>

#define PIN 12

void setup()
{
volatile byte pin;
pinModeFast(PIN, INPUT);
pinModeFast(PIN, OUTPUT);
digitalWriteFast(PIN, LOW);
digitalWriteFast(PIN, HIGH);
pin = digitalReadFast(PIN);  // save a proper high/low value
}


void loop()
{
digitalWriteFast(PIN, HIGH);
digitalWriteFast(PIN, LOW);
}
"

And results are, wow it is WAY faster than a digitalWrite()

~504nS

I've attached a screenshot of the scope reading; I got a different scope yesterday which I am trying out today and so this is not taken on the TekTronix but is instead a Siglent SDS1104X-E; I double-checked for sanity that the digitalWrite(); function was still ~4.1uS as discovered previously.

AWOL

If the compiler sees that the result of a calculation is never used it just leaves the calculation out of the code.
...or the compiler may simply substitute a constant, calculated at compile-time.
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

ElectricLove

So here is the updated list of values;

Execute a digitalWrite(pin, value); ~4.0uS
Execute a digitalRead(pin); ~7uS
Execute a Serial.print(""); ~4uS PLUS ~1.04mS per character printed (example; Serial.print("hello"); 5 characters so it takes ~5.204mS.   NOTE: same timing regardless of baud-rate
Execute analogRead(pin); ~112uS
Execute analogWrite(pin, value); ~8.5uS
Generate a random number; random(); ~50uS
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); ~250nS
Execute a digitalWriteFast(pin, value); ~500nS
Starting Loop() over; ~250ns

AWOL

Quote
Execute math functions; examples; INT =+ 1, VAR = sqrt(VAR), cos(), sin(), tan(); ~250nS
Four cycles at 16MHz?

Dream on
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

ElectricLove

Four cycles at 16MHz?

Dream on

What am I doing wrong?

I run this code:

"
#include <digitalWriteFast.h>
#define PIN 14
void setup()
{
  volatile byte pin;
  pinModeFast(PIN, INPUT);
  pinModeFast(PIN, OUTPUT);
  digitalWriteFast(PIN, LOW);
  digitalWriteFast(PIN, HIGH);
  pin = digitalReadFast(PIN);  // save a proper high/low value
}
void loop()
{
  volatile int myVal;
  digitalWriteFast(PIN, HIGH);
  digitalWriteFast(PIN, LOW);
  //myVal = tan(6000);
}
"
and get 500nS between the start of digitalWrite events (refer to attached image)

Then run this code:
"
#include <digitalWriteFast.h>
#define PIN 14
void setup()
{
  volatile byte pin;
  pinModeFast(PIN, INPUT);
  pinModeFast(PIN, OUTPUT);
  digitalWriteFast(PIN, LOW);
  digitalWriteFast(PIN, HIGH);
  pin = digitalReadFast(PIN);  // save a proper high/low value
}
void loop()
{
  volatile int myVal;
  digitalWriteFast(PIN, HIGH);
  digitalWriteFast(PIN, LOW);
  myVal = tan(6000);
}
"

and get 750nS between the start of digitalWrite events (refer to attached image)

Since the only difference is whether or the myVal = tan(6000); (and time is same even if it is tan(1)) that means that the action of myVal = tan(6000); took exactly 250nS;

How else would you explain this?

AWOL

tan(6000); is a compile-time constant, and you never use it.

You can verify this by looking at the compiled object code.

Please, start thinking.

Quote
What am I doing wrong?
Apart from not using code tags?
"Pete, it's a fool (who) looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.
I speak for myself, not Arduino.

Go Up