Fastest method to obtain digital data

Status
Not open for further replies.

rexlcd

New member
Hi!
I have a Teensy 3.5 and multiple digital sensors whose output pins are connected to the Teensy. I want to obtain the data from the sensors as fast as possible. For that, I think I have 3 options:
1) read them with digitalReadFast
2) port manipulation
3) DMA (the data from the pins directly go to the memory, although I don't know if this is possible, and I have no knowledge on how to implement the DMA)
Which method do you think is the fastest? I really need help as I have a contest in a few days and I really need this.

Thank you very much!
Mihai
 
There are quite a few different types of sensors that can be read in a number of different ways. But given your question (lack of details, for one) I'm not sure if you did your homework before posting.

Many digital sensors use the I2C bus, and in that case the limiting factor will be the bus speed and the update speed of the sensors. Normally both are programmable. If you have a sensor that can use either I2C or SPI, the latter will usually result in a faster operation. In both cases, you probably just want to use the appropriate library functions since they work well and are debugged, so no read with digitalReadFast or with port manipulation. DMA refers to a type of data transfer -- you do not normally read sensors with DMA.
 
The Teensy DMA engine can be used to pipline IO without CPU involvement, such as the OctoWS library does for outgoing. There is at least one example around pulling digital data into DMA memory space and then extracting it into user code but my google fu is not finding it at the moment. It would certainly be the optimal way to do this if you have the time to get it right. The more basic solution is ports, if you can fit all your signals into one port worth of IO pins and then read that port into RAM that will work. The actual flow doing it the bit banging way will be interesting, unless this is a situation where you can trigger code, have it run in a fixed loop into an array and then stop knowing you have captured all the data you need and then process it offline. So a question is, using one 32 bit/4 byte word per record, will your data fit into Teensy 3.5 RAM? (target sample rate*sample time).

If it does not then things will get complex quickly
 
There are quite a few different types of sensors that can be read in a number of different ways. But given your question (lack of details, for one) I'm not sure if you did your homework before posting.

Many digital sensors use the I2C bus, and in that case the limiting factor will be the bus speed and the update speed of the sensors. Normally both are programmable. If you have a sensor that can use either I2C or SPI, the latter will usually result in a faster operation. In both cases, you probably just want to use the appropriate library functions since they work well and are debugged, so no read with digitalReadFast or with port manipulation. DMA refers to a type of data transfer -- you do not normally read sensors with DMA.

Sorry for the lack of details. Each sensor represents a distance sensor with only output pin that goes either LOW or HIGH, depending if an obstacle is in front of it or not. What I want is to get the state of a sensor as quickly as possible in the memory (for example in a variable) so I can use it in my code. Hope that's clear of what I'm trying to do.
 
The Teensy DMA engine can be used to pipline IO without CPU involvement, such as the OctoWS library does for outgoing. There is at least one example around pulling digital data into DMA memory space and then extracting it into user code but my google fu is not finding it at the moment. It would certainly be the optimal way to do this if you have the time to get it right. The more basic solution is ports, if you can fit all your signals into one port worth of IO pins and then read that port into RAM that will work. The actual flow doing it the bit banging way will be interesting, unless this is a situation where you can trigger code, have it run in a fixed loop into an array and then stop knowing you have captured all the data you need and then process it offline. So a question is, using one 32 bit/4 byte word per record, will your data fit into Teensy 3.5 RAM? (target sample rate*sample time).

If it does not then things will get complex quickly

That DMA solution you're talking about is exactly the ideal solution for me. If by any chance you come across that example, please post it :) regarding the port manipulation, yes, I think the data will fit into the Teensy's RAM and I can also make the signals fit into one port and do bit banging on that. But, still, the DMA solution is the king.
 
Thank you very much! This is awesome! I took this piece of code from there:
Code:
#include <DMAChannel.h>

const size_t capture_count = 60000;
uint8_t buffer[capture_count] __attribute__ ((aligned (16)));
DMAChannel dma;

void setup() {
    Serial.begin(9600);
    int  pins[] = {9,10,11,12,15};
    for(int i=0;i<5;i++)
      pinMode(pins[i],INPUT);
}


void loop() {
  while(1) {
    dma.TCD->SADDR = &GPIOC_PDIR ;
    dma.TCD->SOFF = 0;
    dma.TCD->ATTR_SRC = 0; // 1 byte/transfer source
    dma.TCD->SLAST = 0;
    dma.TCD->DADDR = buffer;
    dma.TCD->DOFF = 1;     // 1 byte destination increment
    dma.TCD->ATTR_DST = 0; // 1 bytes/transfer dest
    dma.TCD->NBYTES = capture_count;
    dma.TCD->DLASTSGA = 0;
    dma.TCD->BITER = 1;
    dma.TCD->CITER = 1;
    dma.disableOnCompletion();
    dma.enable();
    dma.triggerManual();

    // wait for 'capture_count' samples to be captured
    while(!dma.complete()) ;
    // process buffer
    Serial.write(buffer,capture_count);
  }
}
If I'm not mistaken, now I should have the data from the sensors in buffer, right? But, isn't this approach slow, considering the fact that the DMA is configured every loop?
 
Maybe it is just me, but I find it easier to give a reasonable answer if I know more about the problem.

Example: What sensor are you using for proximity? What I have seen is that many of them do not update more than N times per second. Example, the Sharp IR sensor:
https://www.adafruit.com/product/19...2sW1cLXIHy1G6YJxApX2KIxBlh2U58hBoC71gQAvD_BwE

It is one of Sharp's faster IR sensors at nearly 400hz. So trying to read it at 1mhz speed or faster may not gain you any additional information. If I were using a few of these or like sensors, I would be tempted to first simply try hooking these up and try out using pin change interrupts. Again depending on which sensor or the like, you can simply interrupt when signal goes LOW to HIGH or ...
 
Each sensor represents a distance sensor with only output pin that goes either LOW or HIGH, depending if an obstacle is in front of it or not. What I want is to get the state of a sensor as quickly as possible in the memory (for example in a variable) so I can use it in my code.
How many sensors do you have? Any more detail on them? Up to 8 can be connected to a single 8 bit wide port and could be read with a single read command that way. But whether that's optimal for further processing, that I do no know.

I'm not sure how much processing will be done by the rest of your code, but it could be significant compared to the time it takes to read the sensors. So I would make sure that the rest of the code is as efficient as possible before implementing DMA for the data transfer.

And as per KurtE's post, interrupt driven read may be the most responsive way to read them.
 
Status
Not open for further replies.
Back
Top