Go Down

Topic: Seeking ideas to append time stamps to Due ADC results. (Read 289 times) previous topic - next topic

Microzod

Hello.

I am using the Due's ADC with a DMA(or PDC to be accurate) to store the results in buffers that is then transferred to Matlab on a PC with SerialUSB, however I want time stamps with each result.
I don't know if this is possible to do without slowing down the readings but I am thinking that since each result is 12-bits there are 4bits left over that are transferred as 0's for each value and them 4bits could be used for timestamps. If nothing else they could allow one to keep relative timestamps(I don't really know anything about how timestamps is usually done)

I would appreciate any ideas or comments on this.

Regards
David

Collin80

Unfortunately I don't see your idea working. Once you set up DMA you don't have any involvement any longer. The ADC hardware starts to store data into RAM without you ever seeing it happen so there's no way to use those extra 4 bits since the storage happens "behind your back" via the DMA mechanism.

However, if you have the ADC hardware in free running mode with DMA then you are getting a sample at regular intervals. If you know all of the settings you used for the setup of this mode then you should be able to determine how long each reading takes and average the timestamp as the "middle" of the reading. As such, if you use something like the micros() function to grab the current system time when you start then you can use the ADC capturing interval to time stamp every reading by adding the number of microseconds each reading takes for each subsequent reading. Does that make sense?

TheRevva

I'm going to take a 'wild guess' and assume that you've configured the ADC such that the values are irregularly spaced throughout time.  (eg: If you've made use of the window comparator such that it only generates a transfer when the value is outside your window).
If that assumption (ugh, what a HORRIBLE word) is correct, and you truly need a 'time-of-occurence', then I'd suggest you might find it more suitable to use a traditional interrupt driven approach and place the pertinent time-stamping code inside the ADC ISR.
I doubt this can be achieved while still using DMA / PDC driven readings (but I'm often wrong... LOL)
In simple terms, you'd setup one of the 9 counter timers as a 32-bit free running time-stamp counter.  Every time you enter the ADC ISR to get the latest reading, you'd simply read the CURRENT value of that timestamp counter to save in a separate memory space.
As for trying to use the 4 superfluous bits, you'd only have 16 possible timestamp values to choose from (which is rather limitting?)

Before you take this any further, I'd suggest you look deeply at the host end (MatLab?) and see what's possible there.  I'm betting it can be made to accept a 2-dimensional array where each 'reading' is passed back as two discrete values (One for the timestamp and the other for the corresponding ADC value).

If your ADC readings are regularly spaced (as Colin suggests above), then it might suffice to pass a back a SINGLE timestamp right at the outset since the effective timestamp of all following values can be easily calculated.

And lastly, the 'all important' question...
What is YOUR definition of a timestamp?
Is "7" a suitable timestamp?
How about "16:30:25.123412"?
Or does it need to include day / month / year too?
It's hard for us to give specific answers without knowing the pertinent constraints.

Microzod

Hello.
I'm sorry for the long delay of responding the the answers you took the time to write.

Let me start of by saying that I am very novice in the area of DSP and I am after reading your answers begiining to think that I am way of base in my persuit.

What a timestamp should look like?... well it's suppose to be a value representing when the sample was read(duhh)... But I have perhaps overstated the importance of achiving this, I usually learn by doing and when I had set up a DMA assisted ADC transfer into Matlab I thought that timestamps is something that you always need to be accurate and from the begining I was simply exploring if the Due can be made to do this properly.
I don't want to disable or delay the DMA transfer since I like the speed of samples but I had thought that maybe I can use as suddgested some interrupt, the DMA is triggered from a Interrupt and as such why could I not take the time by that same interrupt... But I'm not sure the interrupt might be End of RX buffer which could still work.

Even if you both havent aid it straight out I gather from your posts that timestamping might be pointless if I know that every second approximatly this many samples is generated and that I might be better of trusting that the samples is more ore less uniformly spaced over a lets say one second time period.

I know nothing of any implementation of timestamps so my request has been defined by my many assumptions which I am begining to realize that I had.

In any case the code I use is from the friendliness of a member here on the forum, its this:
Code: [Select]
#undef HID_ENABLED

// Arduino Due ADC->DMA->USB 1MSPS
// by stimmer
// from http://forum.arduino.cc/index.php?topic=137635.msg1136315#msg1136315
// Input: Analog in A0
// Output: Raw stream of uint16_t in range 0-4095 on Native USB Serial/ACM

// on linux, to stop the OS cooking your data:
// stty -F /dev/ttyACM0 raw -iexten -echo -echoe -echok -echoctl -echoke -onlcr

// Edited by David
#include <LiquidCrystal.h>

#define n 256 // Buffer size
ยจ
// LCD pin definitions:(though the LCD is not in use as it stands now)
#define RS 41
#define RW 43
#define E 45
#define D4 47
#define D5 49
#define D6 51
#define D7 53

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(RS, E, D4, D5, D6, D7);

volatile int bufn, obufn;
uint16_t buf[4][n];   // 4 buffers of 256 readings

void ADC_Handler()  // move DMA pointers to next buffer
{     
  int f = ADC->ADC_ISR;
 
  if (f & (1 << 27)) //f = ADC_ISR register, (1 << 27) = // ADC_ISR_ENDRX MASK
  {
      bufn = (bufn + 1) & 3;
      ADC->ADC_RNPR = (uint32_t)buf[bufn];
      ADC->ADC_RNCR = 256;
  }
}


void setup()
{
  // Set LCD to Write mode(R/W pin to GND).
  pinMode(RW, OUTPUT);
  digitalWrite(RW, LOW);
 
  // set up the LCD's number of columns and rows:
  lcd.begin(20, 4);
  lcd.clear();
 
  // Enable external reference voltage ICs supply voltage.
  // I have a REF2030 on a tiny PCB that sits in D13, GND , Vref(after resoldering the Vref jumper resistor).
  pinMode(13, OUTPUT);
  digitalWrite(13, HIGH);
 
  SerialUSB.begin(0);
  while(!SerialUSB);
  pmc_enable_periph_clk(ID_ADC);    // Enable ADC peripheral clock
  adc_init(ADC, SystemCoreClock, ADC_FREQ_MAX, ADC_STARTUP_FAST);  // Initilize ADC
  ADC->ADC_MR |= 0x80;              // free running
  ADC->ADC_CHER = 0x40;             //CH7 = A0
 

  NVIC_EnableIRQ(ADC_IRQn);         // Enable ADC Interrupt Vector
  ADC->ADC_IDR = 0xFFFFFFFF;        //Disable all ADC interrupts  alt. use ADC->ADC_IDR=~(1<<27);
  ADC->ADC_IER = (1 << 27);         // 27 = ADC_IER_ENDRX
  ADC->ADC_RPR = (uint32_t)buf[0];  // DMA Receive Pointer Register... Buffer
  ADC->ADC_RCR = n;                 // DMA Receive counter Register... Buffer Size
  ADC->ADC_RNPR = (uint32_t)buf[1]; // DMA Receive Next Pointer Register... Buffer
  ADC->ADC_RNCR = n;                // DMA Receive Next counter Register... Buffer Size
  bufn = obufn = 1;
  ADC->ADC_PTCR = 1;
  ADC->ADC_CR = 2;
}

 

void loop()
{
  while(obufn == bufn); // wait for buffer to be full
  SerialUSB.write((uint8_t *)buf[obufn],512); // send it - 512 bytes = 256 uint16_t
  obufn = (obufn + 1) & 3;
}


I have to get into how SAM3x's timers work, about time but I am not comfortable with counters for some reason, ADD and programming is not o particularly good mix.

I might have missed to answer some of your posts but my mind is in a very volatile state but I will return to check you post again later today.

Untill the, have a nice day.

eestudent2016

Hi,

i want to set my arduino DUE to free running mode, according to the tutorial, http://frenki.net/2013/10/fast-analogread-with-arduino-due/

I should comment the //adc_disable_channel(ADC, ulChannel);

However, I couldnt find the line in my wiring_analog.c.

Anyone facing the same problem with me?

Please help!

Go Up
 


Please enter a valid email to subscribe

Confirm your email address

We need to confirm your email address.
To complete the subscription, please click the link in the email we just sent you.

Thank you for subscribing!

Arduino
via Egeo 16
Torino, 10131
Italy