Pages: [1]   Go Down
Author Topic: speed of digitalWrite and digitalRead on Arduino Due.  (Read 4890 times)
0 Members and 1 Guest are viewing this topic.
Antwerp, Belgium
Offline Offline
Jr. Member
**
Karma: 2
Posts: 64
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hi all,

I'm think about using the Arduino Due as the brains of a Reprap like machine. It will read commands from an SD card (or from it's memory, maybe Due has enough?), parse them and control stepper motors.
So I ordered one and started doing some tests. I've found that digitalWrite and digitalRead are remarkably slower on the Due than the UNO.

I used this sketch as a test:
Code:
#include <digitalWriteFast.h>

/*
I'm trying to see how fast some instructions are on Arduino UNO and Arduino DUE
*/

int sampleSize = 1000000; // do a million times!
long lastTime;

//-----------------------------------------------------------------------------
void setup(){
  delay(50); // wait a bit. (Arduino Due prints nonsense to the serial port...??)
  Serial.begin(115200); // go really fast serial!
 
  // I will store my value in this:
  int n;
 
  // and use these pins for writing or reading
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);

  Serial.println("digitalWrite:");
  lastTime = micros();
  for(int i =0; i < sampleSize; i++){
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
  printTime( micros() - lastTime);

#ifdef digitalWriteFast // not working with Arduino Due
  Serial.println("digitalWriteFast:");
   lastTime = micros();
   for(int i =0; i < sampleSize; i++){
   digitalWriteFast(2, HIGH);
   digitalWriteFast(2, LOW);
   }
   printTime( micros() - lastTime);
#endif

  Serial.println("digitalRead:");
  lastTime = micros();
  for(int i =0; i < sampleSize; i++){
    n = digitalRead(3);
  }
  printTime( micros() - lastTime);
 
#ifdef digitalReadFast
  Serial.println("digitalReadFast:");
  lastTime = micros();
  for(int i =0; i < sampleSize; i++){
    n = digitalReadFast(3);
  }
  printTime( micros() - lastTime);
#endif

}

//-----------------------------------------------------------------------------
void loop(){
  // do nothing
}


//-----------------------------------------------------------------------------
void printTime( long microsecs){
  int mins, secs, msecs, usecs;

  msecs = floor(microsecs / 1000);
  usecs = microsecs % 1000;

  secs = floor(msecs / 1000);
  msecs = msecs % 1000;

  mins = floor(secs / 60);
  secs = secs % 60;
  Serial.print("time: ");
  Serial.println(microsecs);

  Serial.print(mins);
  Serial.print(" min ");
  Serial.print(secs);
  Serial.print(" sec ");
  Serial.print(msecs);
  Serial.print(" msec ");
  Serial.print(usecs);
  Serial.println(" usecs");
  Serial.println("");
  delay(20);
}

I commented out "#include <digitalWriteFast.h>" when compiling for the Due.

These are the results:

Arduino Due:
digitalWrite:
time: 5196306
0 min 5 sec 196 msec 306 usecs

digitalRead:
time: 1156070
0 min 1 sec 156 msec 70 usecs

Arduino UNO:
digitalWrite:
time: 142964
0 min 0 sec 142 msec 964 usecs

digitalWriteFast:
time: 8624
0 min 0 sec 8 msec 624 usecs

digitalRead:
time: 87508
0 min 0 sec 87 msec 508 usecs

digitalReadFast:
time: 7544
0 min 0 sec 7 msec 544 usecs

Sanguino ATMEGA664A  (Reprap motherboard v1.2)
digitalWrite:
time: 142964
0 min 0 sec 142 msec 964 usecs

digitalWriteFast:
time: 8628
0 min 0 sec 8 msec 628 usecs

digitalRead:
time: 86440
0 min 0 sec 86 msec 440 usecs

digitalReadFast:
time: 7548
0 min 0 sec 7 msec 548 usecs

Does anyone know why I find this difference? Is there already a digitalWriteFast library for Due available?

best,
tim.
Logged

Offline Offline
God Member
*****
Karma: 32
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

This can't be right,1 million digitalWriteFast pairs in 8ms on a Uno is an output frequency of 125MHz which is clearly way beyond the specification of the chip!
Logged


Offline Offline
God Member
*****
Karma: 32
Posts: 507
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I just realised where you went wrong:

int sampleSize = 1000000;

On a Uno int is 16 bits, so this will actually set sampleSize to 16960  smiley-mad
Logged


Antwerp, Belgium
Offline Offline
Jr. Member
**
Karma: 2
Posts: 64
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

nice catch stimmer!  smiley-red
Logged

Antwerp, Belgium
Offline Offline
Jr. Member
**
Karma: 2
Posts: 64
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

so I've changed my test like this:

Code:
//#include <digitalWriteFast.h> // uncomment for Arduino UNO

/*
I'm trying to see how fast some instructions are on Arduino UNO and Arduino DUE
*/

long sampleSize = 1000000; // do a million times!
long lastTime;

//-----------------------------------------------------------------------------
void setup(){
  delay(50); // wait a bit. (Arduino Due prints nonsense to the serial port...??)
  Serial.begin(115200); // go really fast serial!
  Serial.print("Sample size: ");
  Serial.println(sampleSize);
  // I will store my value in this:
  int n;
 
  // and use these pins for writing or reading
  pinMode(2, OUTPUT);
  pinMode(3, INPUT);

  Serial.println("digitalWrite:");
  lastTime = micros();
  for(long i =0; i < sampleSize; i++){
    digitalWrite(2, HIGH);
    digitalWrite(2, LOW);
  }
  printTime( micros() - lastTime);

#ifdef digitalWriteFast // not working with Arduino Due
  Serial.println("digitalWriteFast:");
   lastTime = micros();
   for(long i =0; i < sampleSize; i++){
   digitalWriteFast(2, HIGH);
   digitalWriteFast(2, LOW);
   }
   printTime( micros() - lastTime);
#endif

  Serial.println("digitalRead:");
  lastTime = micros();
  for(long i =0; i < sampleSize; i++){
    n = digitalRead(3);
  }
  printTime( micros() - lastTime);
 
#ifdef digitalReadFast
  Serial.println("digitalReadFast:");
  lastTime = micros();
  for(long i =0; i < sampleSize; i++){
    n = digitalReadFast(3);
  }
  printTime( micros() - lastTime);
#endif

}

//-----------------------------------------------------------------------------
void loop(){
  // do nothing
}


//-----------------------------------------------------------------------------
void printTime( long microsecs){
  int mins, secs, msecs, usecs;

  msecs = floor(microsecs / 1000);
  usecs = microsecs % 1000;

  secs = floor(msecs / 1000);
  msecs = msecs % 1000;

  mins = floor(secs / 60);
  secs = secs % 60;
  Serial.print("time: ");
  Serial.println(microsecs);

  Serial.print(mins);
  Serial.print(" min ");
  Serial.print(secs);
  Serial.print(" sec ");
  Serial.print(msecs);
  Serial.print(" msec ");
  Serial.print(usecs);
  Serial.println(" usecs");
  Serial.println("");
  delay(20);
}

and the new results are:

Arduino UNO
Sample size: 1000000
digitalWrite:
time: 8991484
0 min 8 sec 991 msec 484 usecs

digitalWriteFast:
time: 754608
0 min 0 sec 754 msec 608 usecs

digitalRead:
time: 5721828
0 min 5 sec 721 msec 828 usecs

digitalReadFast:
time: 691724
0 min 0 sec 691 msec 724 usecs


Arduino Due
Sample size: 1000000
digitalWrite:
time: 5148742
0 min 5 sec 148 msec 742 usecs

digitalRead:
time: 1275278
0 min 1 sec 275 msec 278 usecs

Much better! :-)
So I guess I won't be needing to worry about the speed of digitalWrite or read.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 6
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Just to let you know I intend to do the same - Due for Reprap. But I would take the rewrite from scratch, with an RTOS (ChibiOS/RT) instead of porting existings firmware.

I would create a macro to manipulate the pin directly using PIOA->SODR/CODR instead of using digitalWrite. digitalWrite does too much magic that makes it 10 times slower than direct pin manipulation.
Logged

Antwerp, Belgium
Offline Offline
Jr. Member
**
Karma: 2
Posts: 64
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi Sam,
Very cool! I'm not really using it for Reprap, but something very similar: a drawing machine (this one: http://www.flickr.com/photos/worldreceiver/8215231164/in/set-72157622815511236 ) but it's easier to say "reprap-like"
I think digitalWriteFast is implemented only with macros if I'm not mistaken. If you get direct pin manipulation to work on the Due, would you mind releasing it? I for one would find it very interesting.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 25
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Reading through these other threads will give you a pretty good idea of how to use port manipulation on the due.

http://arduino.cc/forum/index.php/topic,155431.0.html
http://arduino.cc/forum/index.php?topic=129868.0
Logged

Antwerp, Belgium
Offline Offline
Jr. Member
**
Karma: 2
Posts: 64
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I've finally cleaned up the source of my drawing machine and did an initial commit to github.
It's Arduino Due + micro sD reader + 3 A4988 stepper drivers
You can check it here http://github.com/timknapen/Longhand-Firmware
« Last Edit: June 06, 2013, 11:53:32 am by timKnapen » Logged

Pages: [1]   Go Up
Jump to: