Go Down

Topic: speed of digitalWrite and digitalRead on Arduino Due. (Read 6181 times) previous topic - next topic

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: [Select]

#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.

stimmer

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!
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html

stimmer

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  :0
Due VGA library - http://arduino.cc/forum/index.php/topic,150517.0.html


so I've changed my test like this:

Code: [Select]

//#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.

sam0737

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.

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.

jiblets

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

#8
Jun 06, 2013, 06:45 pm Last Edit: Jun 06, 2013, 06:53 pm by timKnapen Reason: 1
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

Go Up