Digital data acquisition speed?

I have a project in mind where it would be necessary to acquire bytes of data (perhaps 1k) from the digital I/O pins as fast as possible.

If the data is saved into an array on the Arduino it could then be sent to a PC at a slower rate compatible with the serial library.

Does anyone know what is the highest rate of byte reads that a Uno can do, and how to program it for that?

Thanks

...R

You can read 8 input pins in one instruction cycle using direct register access:

PIND = D7/D6/D5/D4/D3/D2/D1/D0
PINB = //D13/D12/D11/D10/D9/D8
PINC= //A5/A4/A3/A2/A1/A0

byte buffer[1024];

noInterrupts();  // Prevent interruptions.
for (int i=0; i<1024; i++)
   buffer[i] = PIND;  // Read pins 0-7
interrupts();

Thanks John,

I'm guessing from your example that reading a byte and storing it in the array would take several CPU cycles. Even if it was only 10 cycles the reads would be relatively slow - say 1.6m per second.

I was/am hoping there might be a special way to do it that would be able to read, say, 5m/s.

The data would be coming from a high speed ADC chip.

...R

johnwasser:
You can read 8 input pins in one instruction cycle using direct register access:

PIND = D7/D6/D5/D4/D3/D2/D1/D0
PINB = //D13/D12/D11/D10/D9/D8
PINC= //A5/A4/A3/A2/A1/A0

byte buffer[1024];

noInterrupts();  // Prevent interruptions.
for (int i=0; i<1024; i++)
   buffer[i] = PIND;  // Read pins 0-7
interrupts();

The data would be coming from a high speed ADC chip.

Which one?

I don't immediately see that it matters - it's just 8-bit data.

Its a TDA8703 which can do 40msps iirc.

...R

You could lose the overhead of the loop, at the expense of longer, more boring code.
Four lots of 256 acquisitions would maybe allow byte indices, which could be faster than into.
5Msps is still quick for a 16MHz processor.

Five million 8-bit samples per second is probably beyond the range of the ATmega processor running at 16 MHz.

This paper has a lot of references that might help:
http://stephan.walter.name/files/publications/walter-dso-project.pdf

All of the devices that use a Philips TDA8703 and aren't FPGA-based seem to include a high speed buffer such as the Micron MT 5C2568 or the IDT7202.

Thanks John,

I can read the device with an FTDI UM245R module - I was just wondering if there is a way to use my new Arduino Uno as an alternative.

...R

johnwasser:
Five million 8-bit samples per second is probably beyond the range of the ATmega processor running at 16 MHz.

This paper has a lot of references that might help:
http://stephan.walter.name/files/publications/walter-dso-project.pdf

All of the devices that use a Philips TDA8703 and aren't FPGA-based seem to include a high speed buffer such as the Micron MT 5C2568 or the IDT7202.

A quick hack based on johnwasser's suggestion took about 500 usec per 1024 samples in a for loop, and about 200 usec in linear code (i.e. 1024 separate assignment statements).

That's slower than I expected, and also didn't seem to be affected by enabling/disabling interrupts, so I'm not sure I trust the results, but that's what I saw

DigitalReadSpeed.ino (22.3 KB)

Is there any (slight) advantage in:

void capture()
{
  byte* buffer1 = &buffer[256];
  byte* buffer2 = &buffer[512];
  byte* buffer3 = &buffer[768];  // these don't have to be here, they're just for illustration
  buffer[0] = PIND;
...
...
  buffer[255] = PIND;
  buffer1[0] = PIND;

...etc

?
(Just curious, but I'm on a train and don't have an Arduino with me.)

This is very interesting. I think the faster timing implies about 3 CPU steps per byte read.

It will be worth having a look at AVR assembler code to see how it can be done. It's unlikely to be better than 3 steps/per but I hadn't expected anything as good as that. I would also need to look at the timing diagram to see whether data could be validly read at that rate.

Of course in a practical situation there also needs to be a clock signal which may consume more cycles.

Thanks.

And any more ideas will be very welcome.

...R

PeterH:
A quick hack based on johnwasser's suggestion took about 500 usec per 1024 samples in a for loop, and about 200 usec in linear code (i.e. 1024 separate assignment statements).

That's slower than I expected, and also didn't seem to be affected by enabling/disabling interrupts, so I'm not sure I trust the results, but that's what I saw

Update ... in case anyone is interested ...

Its some time since I played around with my program to read data with the UM245R module. I have just been trying it again and I have remembered that I can read data more-or-less continuously at high speed with the UM245R module whereas the most I could read with an Arduino Uno would be 2k, even if the speed was fast enough. So I won't be exploring this aspect of the Arduino any further.

By the way the data-acquisition is from a home-made oscilloscope which I will be using to check that some of my Arduino output is correct for a radio control project.

...R