Arduino Speed

Hi everyone. I am trying to implement a code which has to output values at a very high rate. I figured out that Arduino should be good enough for that as it has 16 MHz clock. I tried simple few lines of code just to see the time it takes to write data. So i used micros() to get the time just before the write command, and micros() just after the write command. I printed the time on serial monitor, and I got two values, 64 and 220. If I am not wrong, it means the arduino is taking almost 156us to execute one write statement,one serial printing statement, and one time calculating statement.

int led = 13;
long int time;

void setup() {                
  Serial.begin(9600);
 
  pinMode(led, OUTPUT); 
  time = micros();   //this gives output as 64
  Serial.println(time);
  digitalWrite(led, HIGH);
  time = micros();  //this gives output as 220
  Serial.println(time);  
}

void loop() {
}

I think 156us is too much, because according to 16MHz clock the timescale should be in nanoseconds. I think I am missing something while checking the time with this method. Or is this really the speed of arduino? For my program I need data to be output around every 10us. Is it possible?

Thank You

Well, depends on what you mean by "data to be output". If you are using Serial at 9600 baud, you'll be fairly fast up to 64 bytes, but the buffer only sends out 1 byte every millisecond or so. At 115200 baud, the picture is a little better, but that will send out one byte every 87 microseconds or so.

Remember, you are writing in C++, and while the clock is 16 MHz, many statements require a number of cycles, and libraries such as Serial will tend to take a great many cycles... keeping track of a pointer for the character going into the buffer, a pointer for the character being sent out, and other housekeeping duties, not the least of which is overhead for the subroutine call and exit.

Have you counted the number of characters being Serial.printed and then calculated the time required at 9600 baud?

For my program I need data to be output around every 10us.

(10/1000000)/(1/16000000) = ~160 machine instructions per value. With so little CPU time available there is an extremely low probability you will be able to use the Arduino functions.

Is it possible?

You have provided no details making it impossible to answer the question.

Actually even my reference to the baud is irrelevant here as the UART does the sending asynchronously. But it's still the serial.print that's hogging the time. If you trace the code right through the for each byte being sent to the uart, it probably accounts for that missing time.

It does a lot of stuff just to print that number.

Print()

size_t Print::print(long n, int base)
{
  if (base == 0) {
    return write(n);
  } else if (base == 10) {
    if (n < 0) {
      int t = print('-');
      n = -n;
      return printNumber(n, 10) + t;
    }
    return printNumber(n, 10);
  } else {
    return printNumber(n, base);
  }
}

calls printNumber()

size_t Print::printNumber(unsigned long n, uint8_t base) {
  char buf[8 * sizeof(long) + 1]; // Assumes 8-bit chars plus zero byte.
  char *str = &buf[sizeof(buf) - 1];

  *str = '\0';

  // prevent crash if called with base == 1
  if (base < 2) base = 10;

  do {
    unsigned long m = n;
    n /= base;
    char c = m - base * n;
    *--str = c < 10 ? c + '0' : c + 'A' - 10;
  } while(n);

  return write(str);
}

which calls write(s)

size_t Print::write(const uint8_t *buffer, size_t size)
{
  size_t n = 0;
  while (size--) {
    n += write(*buffer++);
  }
  return n;
}

which calls the hardware serial write(c)

size_t HardwareSerial::write(uint8_t c)
{
  int i = (_tx_buffer->head + 1) % SERIAL_BUFFER_SIZE;
	
  // If the output buffer is full, there's nothing for it other than to 
  // wait for the interrupt handler to empty it a bit
  // ???: return 0 here instead?
  while (i == _tx_buffer->tail)
    ;
	
  _tx_buffer->buffer[_tx_buffer->head] = c;
  _tx_buffer->head = i;
	
  sbi(*_ucsrb, _udrie);
  // clear the TXC bit -- "can be cleared by writing a one to its bit location"
  transmitting = true;
  sbi(*_ucsra, TXC0);
  
  return 1;
}

Actual transmission is interrupt driven:

ISR(UART_UDRE_vect)
{
  if (tx_buffer.head == tx_buffer.tail) {
	// Buffer empty, so disable interrupts
#if defined(UCSR0B)
    cbi(UCSR0B, UDRIE0);
#else
    cbi(UCSRB, UDRIE);
#endif
  }
  else {
    // There is more data in the output buffer. Send the next byte
    unsigned char c = tx_buffer.buffer[tx_buffer.tail];
    tx_buffer.tail = (tx_buffer.tail + 1) % SERIAL_BUFFER_SIZE;
	
  #if defined(UDR0)
    UDR0 = c;
  #elif defined(UDR)
    UDR = c;
  #else
    #error UDR not defined
  #endif
  }
}

DigitalWrite() takes on the order of 10 us. You can used "direct port access" to go faster. Extensive discussion here:
http://forum.arduino.cc/index.php?topic=4324.0