Pages: 1 2 [3] 4 5   Go Down
Author Topic: Max Baud Rate for Arduino Uno  (Read 14650 times)
0 Members and 1 Guest are viewing this topic.
Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Post your testcode, to see if it can be optimized,

If 2.8K is the max speed you can get then the serial bandwidth needs becomes less too.
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@dc42: But, isn't Atmega8 at Arduino Uno  also natively support USB protocoll? What difference it will make anyhow?

No. The atmega328p in the Uno does serial transmit and receive, and a separate chip converts this into serial-over-USB. The Teensy uses a different AVR chip that has built-in USB support, so there is no need to go via serial. The manufacturer of the Teensy claims "the Teensy has direct 12 MBit/sec USB access" and also claims for the RAWHID library functions "You can send up to 1000 packets per second in each direction", where each packet is 64 bytes (that's equivalent to 640k baud or more).
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

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

@robtillaart:

Test Codes for Sensor:

Code:
// AVAGO ADNS 5020 - Optical Navigation Sensor
// Copyright Nitin Kumar, 2011
// TU Dortmund, Germany
// Email: nitin29@gmail.com, nitin.kumar@tu-dortmund.de

#define SCLK 5     // Serial clock pin on the Arduino
#define SDIO 11    // Serial data (I/O) pin on the Arduino
#define NRESET 6   // Sensor's Hardware Reset
#define NCS 7      // Chip Select, LOW - Chip Activate, HIGH - Chip Deactivate
#define Product_ID 0x00
#define DeltaX 0x03
#define DeltaY 0x04
// Other Sensor's registers can be defined and retrived in similar way.

void setup()
{
  Serial.begin(9600);
  SPI.begin();
  pinMode(NCS, OUTPUT);
  digitalWrite(NCS, LOW);
  pinMode (SCLK, OUTPUT);
  digitalWrite (SCLK, LOW);
  pinMode (SDIO, OUTPUT);
  ResetByPin();
  ChangeCPI();
  
  // Test Code from robtillaart, Arduino Forum
  Serial.print("start");
  unsigned long before = micros();
  for(long i=0; i<1000; i++){ProductID();}
  unsigned long duration = micros() - before;
  Serial.println(duration);
  // Test Code End
  Serial.println(ProductID(), DEC);
}

void loop(){}
//{
//  // 4 Bytes - 32 bit of data, at 921600 bps, 28800 set of value retreived
//  Serial.print(Dx());
//  Serial.print(",");
//  Serial.print(Dy());
//  Serial.print(";");
//  //delay(1); // Delay could be set higher or lower as per required
//}

void ResetByRegister(void)
{
  // Initiate chip reset by writing 0x5a to 0x3a register
  WriteRegister(0x3a, 0x5a);
  delayMicroseconds(55);   // Delay (Twakeup) is min. 50ms, max. 55ms as per sensor's datasheet
}

void ChangeCPI(void)
{
  // Set 1000cpi resolution
  WriteRegister(0x0d, 0x01);
}

void ResetByPin()
{
  pinMode(NRESET, OUTPUT);
  digitalWrite(NRESET, LOW);
  delayMicroseconds(1);         // Reset Pulse Width >= 250ns
  digitalWrite(NRESET, HIGH);
  delayMicroseconds(55);   // Delay is min. 50ms, max. 55ms as per sensor's datasheet
}

signed char ProductID(void)
{
  return (signed char)ReadRegister(Product_ID);
}

signed char Dx(void)
{
  return (signed char)ReadRegister(DeltaX);
}

signed char Dy(void)
{
  return (signed char)ReadRegister(DeltaY);
}

byte ReadRegister(byte address)
{
  int i = 0;
  byte result = 0b11111111;    // Initilize the byte with a dummy value
  pinMode (SDIO, OUTPUT);

  digitalWrite(NCS, LOW);

  // Bitbang SPI read operation

  // Write the address of the register:
  for(i = 7; i > -1; i--)
  {
    digitalWrite(SCLK, LOW);
    if(bitRead(address, i) == 1)
      digitalWrite(SDIO, HIGH);
    else
      digitalWrite(SDIO, LOW);
    digitalWrite(SCLK, HIGH);
  }

  pinMode (SDIO, INPUT);    // Switch data line, SDIO from OUTPUT to INPUT (SDO -> SDI)
  delayMicroseconds(5);    // Time between Write and Read Commands, tSRAD >= 4uS
  
  // Retrive the data from the register:
  for(i = 7; i > -1; i--)    
  {                            
    digitalWrite (SCLK, LOW);
    if(digitalRead(SDIO) == HIGH)
      bitSet(result, i);
    else
      bitClear(result, i);
    digitalWrite (SCLK, HIGH);
  }
  digitalWrite(NCS, HIGH);

  return result;
}

void WriteRegister(byte address, byte data)
{
  int i;
  bitSet(address, 7);   // Set MSB high, to indicate write operation
  pinMode (SDIO, OUTPUT);

  digitalWrite(NCS, LOW);

  // Bitbang SPI write operation
  // Write the address of the register:
  for(i = 7; i > -1; i--)
  {
    digitalWrite(SCLK, LOW);
    if(bitRead(address, i) == 1)
      digitalWrite(SDIO, HIGH);
    else
      digitalWrite(SDIO, LOW);
    digitalWrite(SCLK, HIGH);
  }
  
  delayMicroseconds(35);  // Time between Write Commands, tSWR >= 30uS
  
  // Write the data to the register:
  for(i = 7; i > -1; i--)
  {
    digitalWrite(SCLK, LOW);
    if(bitRead(data, i) == 1)
      digitalWrite(SDIO, HIGH);
    else
      digitalWrite(SDIO, LOW);
    digitalWrite(SCLK, HIGH);
  }
  digitalWrite(NCS, HIGH);
}

This sensor has SDIO line and so no MISO /MOSI line hence maybe I can't use SPI protocol.

I checked another sensor has MISO/MOSI lines and result was indeed interesting.
For 1000 register readout in your test codes by using bit-bang mode, the total time was 243148 usec but in SPI mode using Arduino SPI library it was just 21108 usec!

so, Bit-Bang mode transfer rate : 4.112Kbps and SPI Mode transfer rate: 47.375Kbps!

which is 12 times and make sense...rs 232 max transfer rate is 1 Mbps while SPI has 12 Mbps.

@dc42: Interesting. I am interested in Teensy but I have no idea how it will fit with Arduino Uno. Do you have any idea how to connect and transfer data between the two?
« Last Edit: August 29, 2011, 04:28:06 pm by nitin29 » Logged

 -- Nitin

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

The testcode has some overhead for calling  ProductID();  .

you might strip off a few micros per call if you write out the function in the loop. -  no function call overhead -

A call to ProductId will result in at least 2 function calls ProductId() and readRegister()
signed char ProductID(void)
{
  return (signed char)ReadRegister(Product_ID);
}

Can you do the test again but then with a call to ReadRegister(Product_ID);  ? then you can calculate the overhead of the additional function call!


Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

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

Today, I could test the sensor again. The time improved with a reason.

Now, with function calls (as you said) : 258.680 usec per register call.

With your suggestion: 258.172 usec per register call.

By removing Arduino's bitwise functions (bitSet, bitClear and so on) and using instead the bitwise operators like data |= (1 << i) in the ReadRegister & WriteRegister loops : 253.648 usec per register call.

More changes: Removing Arduino's "byte" macro result in same as  the time : 253.648 usec per register call.

What else could be done? Still it is slow at 3.94Kbps. smiley-sad
« Last Edit: August 30, 2011, 01:31:28 pm by nitin29 » Logged

 -- Nitin

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

fiddled with readregister a bit, maybe 2-3 micros again

Code:
byte ReadRegister(byte address)
{
  int i = 0;
  byte result = 0b11111111;    // Initilize the byte with a dummy value
  pinMode (SDIO, OUTPUT);

  digitalWrite(NCS, LOW);

  // Bitbang SPI read operation

  // Write the address of the register:
  for(i = 7; i > -1; i--)
  {
    digitalWrite(SCLK, LOW);
digitalWrite(SDIO, bitRead(address, i));
    digitalWrite(SCLK, HIGH);
  }

  pinMode (SDIO, INPUT);    // Switch data line, SDIO from OUTPUT to INPUT (SDO -> SDI)
  delayMicroseconds(4);    // Time between Write and Read Commands, tSRAD >= 4uS
 
  // Retrive the data from the register:
  for(i = 7; i > -1; i--)     
  {                           
    digitalWrite (SCLK, LOW);
bitWrite(result, i, digitalRead(SDIO));
    digitalWrite (SCLK, HIGH);
  }
  digitalWrite(NCS, HIGH);

  return result;
}

You may want to use directPort manipulation - http://www.arduino.cc/en/Reference/PortManipulation - to speed up more ...
Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Here a first version of direct port manipulation, compiles but must be tested and verified if all right pins are used.

It should be much faster give it a try
Code:
byte ReadRegisterX(byte address)
{
  int i = 0;
  byte result = 0b11111111;    // Initilize the byte with a dummy value
  // pinMode (SDIO, OUTPUT);
  DDRB |= (1<<3);   //datadirection register

  //digitalWrite(NCS, LOW); pin 7
  PORTD &= ~(1<<7);

  // Bitbang SPI read operation

  // Write the address of the register:
  for(i = 7; i > -1; i--)
  {
    //digitalWrite(SCLK, LOW); pin 5
    PORTD &= ~(1<<5);
    // digitalWrite(SDIO, bitRead(address, i));  // SDIO pin 11
    if (bitRead(address, i) == 1) PORTB |= (1<<3);
    else PORTB &= ~(1<<3);
    // digitalWrite(SCLK, HIGH); pin 5
    PORTD |= (1<<5);
  }

  //pinMode (SDIO, INPUT);    // Switch data line, SDIO from OUTPUT to INPUT (SDO -> SDI)
  DDRB &= ~(1<<3);  //datadirection register

  delayMicroseconds(4);    // Time between Write and Read Commands, tSRAD >= 4uS

  // Retrive the data from the register:
  for(i = 7; i > -1; i--)     
  {                           
    //digitalWrite(SCLK, LOW); pin 5
    PORTD &= ~(1<<5);
    // bitWrite(result, i, digitalRead(SDIO));
    bitWrite(result, i, ((PORTB & (1<<3)) >0));

    // digitalWrite(SCLK, HIGH); pin 5
    PORTD |= (1<<5);
  }
  // digitalWrite(NCS, HIGH); pin 7
  PORTD |= (1<<7);

  return result;
}
« Last Edit: August 30, 2011, 02:22:54 pm by robtillaart » Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@dc42: Interesting. I am interested in Teensy but I have no idea how it will fit with Arduino Uno. Do you have any idea how to connect and transfer data between the two?

I have no experience of the Teensy, but essentially it (and the Teensy++) are alternatives to the Arduino Uno, with an add-on to the Arduino IDE to support them. More at http://www.pjrc.com/teensy/.

Alternatively, if you were to add an Ethernet shield to your Uno, you could send the data over Ethernet instead of serial.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

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

@robtillaart
Code Optimization - 2 Bytes from register, a "," and a ";" - total of 4 bytes over serial.
Ist codes (Initial Program - with Arduino's bitwise functions) - min. 4.164 ms, max. 9.364 ms,
2nd (No if and else loops inside ) - min. 4.160, max. 10.4 msec,
3rd Codes (Native - No Arduino function for Port & Pin setting) - min. 4.156 ms, max. 8.320 ms to 10.396  ms

Single register call: 248 usec. Call and printout of that register value: 1048 usec.
// Serial.print is eating 4 times of duration for sending byte over UART!

So, sensor is capable to be retrived by 4 times. But, it is pulled down by Arduino UART librarys!  smiley-sad

Thank you very much, your codes and suggestions have been of great help!

@dc42
Does Teensy support Arduino or coding? I mean, then I don't have to change the coding. And, how could I get the data directly from UController?

Does any body have ethernet shield/breakout and could test that how much it take to sent a byte from Arduino to Computer over Ethernet?
If it take much less then I can think of moving to Maple (only if it support 2 SPI as my some of my sensor have to use SPI so I can put ethernet on one and sensor on other).

Somebody know about this : http://www.watterott.com/de/OLIMEXINO-STM32-MAPLE
No. of serial & support of maple is not mentioned. Only Maple compatible board is shown.

Thank you!
Logged

 -- Nitin

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

@dc42
Does Teensy support Arduino or coding? I mean, then I don't have to change the coding. And, how could I get the data directly from UController?

I don't have any experience of Teensy, however I know there is an add-on for the Arduino IDE to support the Teensy, see http://pjrc.com/teensy/teensyduino.html.

When using either USB or Ethernet, you should send data in blocks, not individual bytes.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

Global Moderator
Dallas
Online Online
Shannon Member
*****
Karma: 207
Posts: 12910
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Does Teensy support Arduino or coding? I mean, then I don't have to change the coding.

Yes.  In my experience, the Teensy is highly compatible.

Quote
And, how could I get the data directly from UController?

The same way you do now.  By default, the Teensy is presented to the host computer as a serial port.  A very very fast serial port.
Logged

United Kingdom
Offline Offline
Tesla Member
***
Karma: 224
Posts: 6614
Hofstadter's Law: It always takes longer than you expect, even when you take into account Hofstadter's Law.
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Single register call: 248 usec. Call and printout of that register value: 1048 usec.
// Serial.print is eating 4 times of duration for sending byte over UART!

My guess is that the uart-over-USB protocol has a lot of overhead and perhaps some hanshaking between the two ends, and that is what is slowing it down, rather than the Serial.print software implementation.
Logged

Formal verification of safety-critical software, software development, and electronic design and prototyping. See http://www.eschertech.com. Please do not ask for unpaid help via PM, use the forum.

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

I have to get around 10 bytes per iteration. Not much, so I don't know how to optimize this packet thing. I have checked with the access rate and if I'm calling same sensor's register say 10 times,  the total time is multiple of single call. So, I don't think I have saving on packet of say 10 bytes/ 10 registers.

Teensy looks really promising. But I don't know how to get it here in Europe (Germany).
Maybe it will take longer to ship as the original seller is in US and then I am short on time.

I just thought about SD Card...If I can directly send the data to SD card and log my result there.

SD card and Ethernet shield are here available in plenty. I thought that maybe I can get some success with them.

Will SD Card logging or Ethernet transmission be faster as compared to this whole USB-Serial conversion?


Logged

 -- Nitin

Global Moderator
Netherlands
Offline Offline
Shannon Member
*****
Karma: 217
Posts: 13705
In theory there is no difference between theory and practice, however in practice there are many...
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset


Single register call: 248 usec.
== > is that the performance of the ReadRegister()  code with the direct port manipulation?  == code from Reply #36  ??
Is that only 10 micros faster than the digitalWrite() version? ????



 
Quote
Will SD Card logging or Ethernet transmission be faster as compared to this whole USB-Serial conversion?
SDCard : check - http://arduino.cc/forum/index.php/topic,64813.0.html -

Logged

Rob Tillaart

Nederlandse sectie - http://arduino.cc/forum/index.php/board,77.0.html -
(Please do not PM for private consultancy)

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

This value was without Direct Port manipulation. With port manipulation, there is difference of 2 usec. So, with just 2 usec when the single call is taking around 248 usec there isn't much difference...plus code looks non-arduinoic.

From Reply #32 and your test codes:
It takes 248 usec when I just call Dx() and 1048 usec if I send print over serial, using Serial.print(Dx()).

Code:
void setup()
{
  Serial.begin(9600);
  Serial.begin("start");

  unsigned long before = micros();
  Dx();  // Takes 248 usec
  // Serial.print(Dx());  // Takes 1048 usec
  unsigned long duration = micros() - before;
  Serial.println(duration);
}

No idea know, what else could be done.

Thought of using Ethernet with Maple because it has 2 SPI but then it has no Ethernet library yet!
There is also CAN bus support and I could get the CAN-USB converter. How would it be with CAN bus, anybody got idea?

Will check the post you attached. Maybe it can change something. I only fear that I have 10 byte of data and if I have to write to SD card then maybe I had to open and close the file on each iteration. That seems a crazy idea to me.


Logged

 -- Nitin

Pages: 1 2 [3] 4 5   Go Up
Jump to: