Data acquisition/Logic Analyzer

That'll make it hard to get a time from micros(), won't it?

I upload the code , and it shows 1000 samples, time in uS = 1384. it means it takes 1.384milliseonds to acquire 1K samples. isnt it? now what to do.

Thank you

But it'll make sampling more even

Ok, so one method will yield 3000 samples in 4.152mS, hardly close to 2MSPS.Try the next method:

byte dataArray[1000];
unsigned long startTime;
unsigned long endTime;
unsigned long elapsedTime;
unsigned int x;
void setup(){
startTime = micros();

dataArray[0] = PIND; // only 8 bit port on Uno
dataArray[1] = PIND; // only 8 bit port on Uno
dataArray[2] = PIND; // only 8 bit port on Uno
dataArray[3] = PIND; // only 8 bit port on Uno
// repeat until you get 1000 samples:
dataArray[998] = PIND; // only 8 bit port on Uno
dataArray[999] = PIND; // only 8 bit port on Uno
endTime = micros();
elapsedTime = endTime - startTime;
Serial.print("1000 samples, time in uS = ");
void loop(){}

You can improve speed by disabling interrupts prior to starting sampling and then re-enabling then, but you'll need an oscilloscope or some other external tool to measure the time by measuring a pin going high at the start of capturing and low at the end of capturing.

i upload the code and got this "1000 samples, time in uS = 192" , i also pust cli() before start sampling and sei() after sampling.

Did you create the 1000 read lines?
If so, then 3000 byte samples will take 0.576mS
2 million samples/second = 1 million samples/0.5second = 1000/.0005second, so about 1/3 of what you wanted.
1/6 of what you wanted for ints.

Looks like you need a faster processor.

Hello, can you tell me how do i send this data to excel sheet with acquisition time of each sample.

is there any way to do so?? if we cant do with time then atleast tell me how to send out these sampled data into excel sheet.

how to read this data, i want it to excel sheet. is there any way to store actual time for each sample.?? yes it is a 1/3 of what i need.

Sure, Need a faster machine tho. I'm only here for the slower 8-bit stuff.

can you tell me how to send this data out in excel sheet with actual time of each sample like we got 1000 samples 192 microseconds, so for each sample would be 1000/192=5.2083 microsecods means 8 bit or 1 byte data at rate of 5.2083 microseconds. so i want this time too.

Thank you so much for the support.

can i write this same problem on Arduino DUE forum.

thank you

"can i write this same problem on Arduino DUE forum."
Go for it. I'll move this one over for you even.

I want to acquire 16 bit data (initially we can try for 8 bit too) at sampling rate of 2MSPS,

On Due you can read any of the 4 ports (32bit) into a local variable in 3 clock cycles.
That is every 3*(1000/84)=35.7ns or 84/3=28MHz.

Of course if you need to take more samples than CPU has free registers (for the local variables) more time has to be spent for storing the values. But Arduino Due 84MHz clock frequency allows for 41 clock cycles (for 2MSPS) to to so, so I would expect Due definitely able to capture 2MSPS into its (96KB in total) memory.

I investigated whether (5$, 1GHz, 512MB) Raspberry Pi Zero can capture faster than Due 35.7ns, but it was not able to capture in less than 50ns:

I need to find out how to compile kernel modules on my (8$, 1.2GHz A7 quad core, 256MB) NanoPi Neo, then I will see whether captures <50ns are possible with it.

Recently I spent 5$ for a 24MHz logic analyzer, and 24$ for a 100MHz one (waiting for delivery):

Especially the 100MHz one will give me 3 channels(bits) @100MHz or 10ns between measurements which is better than the Due 35.7ns between measurements, and it allows for 10 billion samples to be taken. Will be good to have that and the Due measurements for measuring speed of light (light travels 3.3m in 10ns).

Regarding your 8/16 bit 2MSPS requirements, the second will definitely do:
9CH@32M MAX Sample Rate
16CH@16M MAX Sample Rate

For the 5$ one with 8 channels no detailed data can be found.
But even if only 1 channel could be captured @24MHz, 8 channels @3MHz should be possible meeting your requirement.


Thank you so much Mr. Hermann . i seen all your post i read it. i want to know that . DUE has 32 bit Core.

How do i access it , how much time it will take. is it possible to acquire 32 bits pattern in binary directly to DUE memory..? it is very useful information that you are capturing the speed of light with DUE means it has good power of processing.

i would like to know that howmany machine cycle dUE will take to acquire 32 bit..?

Thank you so much


i would like to know that howmany machine cycle dUE will take to acquire 32 bit…?

Thank you so much that you asked again.

It was 3 Arduino clock cycles (of 11.9ns), that is less than 36ns between measurements. But until today I thought this was only true for capturing a small number of samples, less than the number of free CPU registers. But belo sketch shows that reading into an array via “*a++ =” also does only take 3 clock ticks (7 for only one read, but then 3 clock cycles more for each read added, I compiled and did run the sketch, and then mad the comment show the number of clock ticks measured and reported:

// C.23 = D7
Pio *p = digitalPinToPort(7);

void setup() {
  uint32_t b,a1,a2,a3,a4,a5,a6,a7,A[100];
  uint32_t t0,t1,b7 = digitalPinToBitMask(7);
  uint32_t *a=&A[0];
  pinMode(7, INPUT);
  t0=SysTick->VAL;  // 1
  *a++ = p->PIO_PDSR; // 7 
  *a++ = p->PIO_PDSR; // 10 
  *a++ = p->PIO_PDSR; // 13 
  *a++ = p->PIO_PDSR; // 16 
  *a++ = p->PIO_PDSR; // 19
  *a++ = p->PIO_PDSR; // 22
  *a++ = p->PIO_PDSR; // 25
  *a++ = p->PIO_PDSR; // 28
  *a++ = p->PIO_PDSR; // 31
  *a++ = p->PIO_PDSR; // 34
  *a++ = p->PIO_PDSR; // 37
  *a++ = p->PIO_PDSR; // 40
  *a++ = p->PIO_PDSR; // 43
  *a++ = p->PIO_PDSR; // 46
  *a++ = p->PIO_PDSR; // 49
//  *a++ = p->PIO_PDSR; // 52
  Serial.println( ((t0<t1)?84000+t0:t0)-t1 );

void loop() {}


The quickest dynamic loop I was able to come up with does take 8 clock cycles per read (of 10000 reads!):

// C.23 = D7
Pio *p = digitalPinToPort(7);

void setup() {
  uint32_t i,A[10000],t0,t1;

  pinMode(7, INPUT);

  for(i=0; i<sizeof(A)/sizeof(A[0]); ) {
    A[i++] = p->PIO_PDSR; 
  // 80012 => 8 clock cycles per read
  Serial.println( ((t0<t1)?84000+t0:t0)-t1 );

void loop() {}

Copying in the 10000 statements does take only 3 clock cycles per read (30008 for 10000):

// C.23 = D7
Pio *p = digitalPinToPort(7);

#define T(stmt) stmt; stmt; stmt; stmt; stmt; stmt; stmt; stmt; stmt; stmt;

void setup() {
  uint32_t i,A[10000],t0,t1,*a=&A[0];

  pinMode(7, INPUT);

  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  T(T(T(*a++ = p->PIO_PDSR)))
  // 34(10), 304(100), 3008(1000), 30008(10000) => 3 clock cycles per read
  Serial.println( ((t0<t1)?84000+t0:t0)-t1 );

void loop() {}

The Arduino IDE compiler gave up on compiling single line “T(T(T(T(*a++ = p->PIO_PDSR))))”, so I just copied 10 lines generating 1000 reads.

10000 32bit values is 40000 bytes, so you could read slightly more than double of that into Arduino 96KB memory, eg. 20000 values in 60000 clock cycles (of 11.9ns) or 714μs in total. So Arduino Due can be a short time span (less than a millisecond) 84/3=28MHz, 32 channel logic analyzer. That is even better than the 100MHz logic analyzer mentioned above, that can do 16CH@16M MAX Sample Rate while Due can (for less than a millisecond) 32CH@28M …

This definition

unsigned char *a = (unsigned char *)&A[0];

does need 3 clock cylces per read

*a++ = p->PIO_PDSR

as well, and

a[0] = 0x01234567;
a[1] = 0x89ABCDEF;

results in a[0]=0x67 and a[1]=0xEF. With that change you can read 3ms with 8CH@28M into Arduino Due ram.


Today I got the 24$ 100MHz 16 channel logic analyzer mentioned above after only 12 days (China->Germany, free shipping)!

First I tested against 10KHz Raspberry Pi Zero PWM signal, and the logic analyzer software reported exactly 10.00KHz:
(right click the images in order to see the details)

Then I tried to verify the 26.21MHz that Pi Zero was able to generate maximally without PWM as described in this posting, measured by Arduino Due tc_lib and averaging the results:

The PWM signal is not perfectly even spaced, but hey, its a 26MHz signal generated from 84MHz CPU in software:

I zoomed out to determine the average frequency over a long range and notice a gap of a little bit more than 10us, seems to be some Raspbian OS interruption of normal program flow:

Here is the big picture, 26.26MHz over a range of 0.1849s, with 4854232 complete periods:

26.21MHz versus 26.26MHz, Arduino Due tc_lib and logic analyzer results nearly perfectly match.

Finally I wanted to test the logic analyzer itself against the highest possible Pi Zero hardware PWM frequency (19.2/4=4.8MHz). Something was wrong, I measured 6.273MHz and Pi Zero hardware PWM frequency cannot be that off:

Zooming in the problem can be seen easily , little down spikes while signal should be up:

Then I realized what could be the problem. While the 26MHz measiurement was done on GPIO17 which was not used by the 320x240 TFT display, the hardware PWM was generated on GPIO18 which was used for the TFT display as well. I did use ILI9341_due library before, just learned yesterday and today how to make Raspberry Pi Zero use framebuffer to drive the ILI9341 and even start an X session on the TFT:

The TFT was not "on" as shown on initial photo, but the framebuffer driver seems to do something (the little down spikes). So I just removed the TFT only and did measure again. This time I measured exactly 4.800MHz over 0.12s:

Zooming in now shows a nearly perfectly even spaced 4.8MHz curve:


This posting shows a 14MS/s 8CH logic analyzer sketch for the Arduino Due (32CH possible as well):


In above posting

up to 80KB of 96KB memory made logic analyzer like reading at 28Msps possible, and the only restriction was the size of RAM that could be used for that.

Lately using RAM (disk) in a completely different application scenario on a different microcontroller saved the day again and allowed for stuff otherwise impossible.

On a (5$) Raspberry Pi Zero there is a 188MB ("only") /dev/shm ramdisk. I used that to capture video frames at much higher framerates than Raspberry "raspivid" allows for (90fps). The higher framerates became possible by reducing framesize and thus increasing framerate. The 188MB allowed to capture up to 8s of high framerate video regardless of resolution.

Here is a sample (640x128 stretched) video, captured at 665fps(!).
The animated .gif plays at 25fps, 26.6 slower than real:

Here are the framerates that can be a achieved with 5$ camera:

Two completely different problems, solved by making (extreme) use of (limited) RAM.