Nano 33 BLE Direct Memory access

Good morning,

I am working on a data logger using arduino 33 ble. I would like to log different sensors:

  • 2 analog sensor at 100 Hz
  • Internal imu at 50-100 Hz
  • GPS at 10 Hz (with nav_pvt message, so possibility to log it directly as binary)

My problem is to sincronyze the measurements. My idea was to log the highest frequency sensor and flush all together once gps is available. I got from gps a PPS at 10 Hz that i can use as trigger to flush data. A guy that works with nordic processor suggested to me to use DMA since it is available in nrf processor, but i have no idea how to do it.
Someone can give a suggestion or an example.
Thanks in advance

alek91:

  • 2 analog sensor at 100 Hz
  • Internal imu at 50-100 Hz
  • GPS at 10 Hz (with nav_pvt message, so possibility to log it directly as binary)

You do not need DMA for that amount of data. You can easily handle that by the processor. Do you have any processing needs that would require most of the processor time?

alek91:
My problem is to sincronyze the measurements.

What do you mean by that? (I do not mean the spelling.) Please describe what you would like to achieve and why.

alek91:

  • 2 analog sensor at 100 Hz

What are those signals? Do you just need the values or do you want to reconstruct a signal? e.g. do you really mean 100Hz or ~100 times a second.

Hello Klaus,
Thanks for your answer. The two sensor are linear analog potentiometer so i don't need to reconstruct the signal, since i do it in post processing, so 100 Hz means i want equally spaced sampled signal.
I saw some example with arudino mega were they are using NeoHWSerial and some other libraries that are not compatible with arduino 33.

From your answer i understand that arduino 33 should not have big limitation if I store the two signals on the ram and then write all together when GPS writing occurs, is it correct?
How can i manage this on 33 in a clena way? create a buffer as a struct, then add gps and write after that? During writing the arduino will keep logging or it will stop until writing is finished?

Thanks

alek91:
The two sensor are linear analog potentiometer so i don't need to reconstruct the signal, since i do it in post processing, so 100 Hz means i want equally spaced sampled signal.

So, you are interested in the signal and you want equidistant samples?
Then you will need to write the ADC code yourself. As far as I know the Arduino library is designed for manual call of the analogRead() function which you will not be able to start equidistant. The datasheet describes how to use timers to start the ADC automatically. However, it’s not all in one place because it involves multiple blocks of the microcontroller.

alek91:
From your answer i understand that arduino 33 should not have big limitation if I store the two signals on the ram and then write all together when GPS writing occurs, is it correct?
How can i manage this on 33 in a clena way?

Where do you want the data to go?
How do you want to transmit the data?

alek91:
During writing the arduino will keep logging or it will stop until writing is finished?

That is mostly up to you. The Arduino Nano 33 BLE can handle a lot of things at the same time. Beware many examples use delay() which is the worst enemy good sketches.

Data will be stored on a SD card.
So i wrote my adc code already and i store the data in a structure

void acquireData(data_t* data) {
  data->time = micros();
  data->xSuspF =  analogRead(5);
  data->xSuspR =  analogRead(4);
}

Similar code is used to store the GPS coordinates. From another example I copied this part of code :

 if ( processGPS() ) {
                
                  logfile.print(millis()); //point at which message parsing has finished
                  logfile.print(",");
                  logfile.print(pvt.lat); //latitude
                  logfile.print(",");
                  logfile.print(pvt.lon); //longitude
                  logfile.print(",");
                  logfile.print(pvt.hMSL); //altitude at sea level
                  logfile.print(",");
                  logfile.print(pvt.gSpeed); //ground Speed mm/s
                  logfile.print(",");

                  ADCsamples    = 0;                       //reset the ADC samples couter to 0
                  lastADCsample = millis() - ADC_INTERVAL; // force the 1st ADC sample

                   if ( (millis() - millisAtEpoch) > 200 and (noGpsFlag == false)) {     //asumes no gps fix when no epoch recieved within 200ms.
                noGpsFlag = true;
                }

                if ((ADCsamples < MAX_ADC_SAMPLES) and
                ((millis() - lastADCsample) >= ADC_INTERVAL) or ((noGpsFlag == true)   //when GPS outage, operates indefinitly at set sample rate
                and ((millis() - lastADCsample) >= ADC_INTERVAL)) )
                {
                     acquireData(&data);
                     printData(&logfile, &data);
                     ADCsamples++
                     lastADCsample  += ADC_INTERVAL;
                }

                }

So the first part is checking for the GPS that write his data on the log file without checking the time when it happens, the second part print the ADC for the rest of the time.
Anyway i do not like too much this way. I would like to flush a packet of data just when gps occurs. So store the ADC data until gps pulse occurs.
Anyway for AVR arduino no one is using this way cause ram is too small. I would like to do it on the nano but in a clean way.
Any suggest or example?

alek91:
So i wrote my adc code already and i store the data in a structure

That code will not get you equidistant samples. As I said before you will need to use a timer to automatically trigger the AD conversion.
Maybe using a software trigger is good enough in your case. I do not know what you want to do with the data.

alek91:
Anyway i do not like too much this way. I would like to flush a packet of data just when gps occurs. So store the ADC data until gps pulse occurs.

How do you know that this is what your sketch is doing?
Just a little while ago I had a look into a SDcard issue somebody had in the forum. What I discovered was that the library was collecting writes to the SD card and wrote the data when it had collected enough data.

Here is a link to that post. See reply #3.

https://forum.arduino.cc/index.php?topic=725049.0

This would suggest, you should write to your SD card whenever you have a set of data and your sketch is not in a timing critical part. If the SD library writes to the SD card itself the write will take ~20ms. I would not mix data with different sampling rates but create records for each type. Each record starts in a new line with an identifier e.g. A0, IMU, GPS and then a number of comma separated values depending the buffer size for each.

Thanks Klaus for your tips.
From what i understood the problem you're poinitng to "equally spaced data" is the missing of a timer.
I looked on the web i found out the possibility to have a timer on mbed nrf processor with a library. Do you suggest to use different timers for different loops?
I am able to create the buffers than but still not sure how to send then together to my SD.

alek91:
From what i understood the problem you're poinitng to "equally spaced data" is the missing of a timer.

Yes.

alek91:
I looked on the web i found out the possibility to have a timer on mbed nrf processor with a library.

Do you have a link to the library?

alek91:
Do you suggest to use different timers for different loops?

You need a hardware timer to trigger the ADC. This will ensure accurate sampling within the accuracy of the clock source. There is no variable delay trough software.

Other things that can live with delays and are fairly slow, can be controlled trough software timers (multiple timers derived from a hardware timer e.g. using millis()).

alek91:
I am able to create the buffers than but still not sure how to send then together to my SD.

I would start thinking about the data structure you want in your file. Then create the buffers, you might need double buffers. Then write a state machine that will write the data to the SD card. The state machine will be called whenever you have time. It will check whether a buffer needs to be sent, send the data and then return. For multiple buffers it needs to be called multiple times.
Do not worry about sending the data together. I suspect the SD library needs to take the underlying flash memory structure and/or RAM buffer size into account. If you try to match your data to that the code will be complicated and hard to extend.
You need to focus on data collection e.g., when the SD card is written the write will take ~20ms. During that time, the data from the ADC still needs to be collected every 10ms (100Hz). This suggests ether ADC interrupt handling or DMA.

Now is more clear... Still have some doubt about how to store the data on the buffer together or separately but i will try to figure out.
here the link to the library for the timer. I tried the examples and they are working. Still not try to put them on my code actually.

This topic was automatically closed 120 days after the last reply. New replies are no longer allowed.