# SparkFun Forums

### Hi speed analog acquisition?

Topics pertaining to the Arduino Core & software used with the Artemis module and Artemis development boards.

### Hi speed analog acquisition?#209379

By dlp
#209379
I've used the following sketch (modified from a handy site about Teensy FFT) to time the acquisition of 512 ADC values, but it tops out at about 65kS/s. How are we to acquire at or near the very impressive Artemis MS/s rates?

/*dlp - Using an Artemis Redboard, found for the original 512 samples at 50khz, the measured freq is 38.1khz
if you specify 14 or 16-bit resolution it stays the same
200khz = 65.1
100khz = 65.1
90khz = 65.1
80khz = 52.5
70khz = 52.5
60khz = 43.8
50khz = 38.1 (23.8% low)
40khz = 33.5 (16.2% low)
30khz = 26.6 (11.3% low)
20khz = 17.9 (10.5% low)
*/

#define SAMPLES 512 //Must be a power of 2
#define SAMPLING_FREQUENCY 50000 //Hz
#define REFRESH_RATE 10 //Hz

unsigned long sampling_period_us;
unsigned long useconds_sampling;

unsigned long refresh_period_us;
unsigned long useconds_refresh;
float SamplesAcqFreq;

double vReal[SAMPLES];
double vImag[SAMPLES];

uint8_t analogpin = A0;

void setup() {
Serial.begin(115200);
//analogReadResolution(14); //Set resolution to 14 bit
sampling_period_us = round(1000000*(1.0/SAMPLING_FREQUENCY));
refresh_period_us = round(1000000*(1.0/REFRESH_RATE));
pinMode(analogpin, INPUT);
}

void loop() {
useconds_refresh = micros();
/*SAMPLING*/
for(int i=0; i<SAMPLES; i++)
{
useconds_sampling = micros();

vImag = 0;

while(micros() < (useconds_sampling + sampling_period_us)){
//wait...
}
}
SamplesAcqFreq = SAMPLES/((float(micros())-useconds_refresh)/1000000);
Serial.println(SamplesAcqFreq); //print sample freq
while(micros() < (useconds_refresh + refresh_period_us)){ //wait for refresh time
//wait...
}
}

https://www.norwegiancreations.com/2019 ... -analysis/

### Re: Hi speed analog acquisition?#209629

By Valen
#209629
You are doing calculations on sample time in your code. But those are just make-believe results or after-the-fact rates. You probably need to change some register settings to change the ADC clock prescaler to affect the real sample rate. I am unaware of where to find the datasheet of the processor because I am too unfamiliar with the board/chip architecture. But that would be where the solution lies.

### Re: Hi speed analog acquisition? - Working#210010

By dlp
#210010
I modified a C-code example found in the Ambiq-Micro SDK (adc_lpmode0_dma.c ) and it now works on the Artemis Redboard & Arduino IDE.
Single-channel, single-ended, 14bit acquisition, choosing frequencies that will include one complete wave in the 512-point buffer I measure the following S/s:
500Hz with AVG_8 = 140kS/s.
3kHz with AVG_1 = 1.11MS/s.

Here's the sketch:

Edited by moderator to add code tags. Please use the code tag button above when posting code.
Code: Select all
``````//*****************************************************************************
//
//!
//! @brief This example takes samples with the ADC at high-speed using DMA.
//!
//! Purpose: This example shows the CTIMER-A3 triggering repeated samples of an external
//! input at 1.2Msps in LPMODE0.  The example uses the CTIMER-A3 to trigger
//! ADC sampling.  Each data point is 8 sample average and is transferred
//! from the ADC FIFO into an SRAM buffer using DMA.

#include "am_bsp.h"

// Define a circular buffer to hold the ADC samples
//*****************************************************************************
#define ResolutionBits 14

unsigned long useconds_refresh;

// Define the ADC SE0 pin to be used. (A4)
{
};

// Interrupt handler for the ADC.
//*****************************************************************************
extern "C" void am_adc_isr()  //must use 'extern "C" ' for the Artemis
{

{
}

{
}

// If we got a DMA complete, set the flag.
{
}

// If we got a DMA error, set the flag.
{
}
}

// Set up the core for sleeping, and then go to sleep.
//*****************************************************************************
void sleep()
{
// Disable things that can't run in sleep mode.
//    am_bsp_debug_printf_disable();
//#endif

// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);

// Re-enable peripherals for run mode.
//    am_bsp_debug_printf_enable();
//#endif

}

//*****************************************************************************
{

// Configure the ADC to use DMA for the sample transfer.
{
//am_util_stdio_printf("Error - configuring ADC DMA failed.\n");
Serial.println("Error - configuring ADC DMA failed.");
}
// Reset the ADC DMA flags.

}

//*****************************************************************************
{

// Initialize the ADC and get the handle.
{
//am_util_stdio_printf("Error - reservation of the ADC instance failed.\n");
Serial.println("Error - reservation of the ADC instance failed.");
}

AM_HAL_SYSCTRL_WAKE,
false) )
{
//am_util_stdio_printf("Error - ADC power on failed.\n");
Serial.println("Error - ADC power on failed.");
}

// Set up the ADC configuration parameters. These settings are reasonable
// for accurate measurements at a low sample rate.
/*
*/
{
}

// Set up an ADC slot
/*

// Single-ended channels
// Differential channels.
// Miscellaneous other signals.

*/
{
//am_util_stdio_printf("Error - configuring ADC Slot 0 failed.\n");
Serial.println("Error - configuring ADC Slot 0 failed.");
}

// Configure the ADC to use DMA for the sample transfer.
// For this example, the samples will be coming in slowly. This means we
// can afford to wake up for every conversion.
//

//
{
}
}

// Initialize the ADC repetitive sample timer A3.
//*****************************************************************************
{
// Start a timer to trigger the ADC periodically (1 second).?? Must be a hold-over from another version
am_hal_ctimer_config_single(3, AM_HAL_CTIMER_TIMERA,
AM_HAL_CTIMER_HFRC_12MHZ    |
AM_HAL_CTIMER_FN_REPEAT     |
AM_HAL_CTIMER_INT_ENABLE);

am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA3);

am_hal_ctimer_period_set(3, AM_HAL_CTIMER_TIMERA, 10, 5); //10 tick period, 5 ticks wide

// Enable the timer A3 to trigger the ADC directly

// Start the timer.
am_hal_ctimer_start(3, AM_HAL_CTIMER_TIMERA);
}

void setup() {
Serial.begin(115200);
while (!Serial) {}
// Set the clock frequency.
if (AM_HAL_STATUS_SUCCESS != am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0))
{
//am_util_stdio_printf("Error - configuring the system clock failed.\n");
Serial.println("Error - configuring the system clock failed.");
}

// Set the default cache configuration and enable it.
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_config(&am_hal_cachectrl_defaults))
{
//am_util_stdio_printf("Error - configuring the system cache failed.\n");
Serial.println("Error - configuring the system cache failed.");
}
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_enable())
{
//am_util_stdio_printf("Error - enabling the system cache failed.\n");
Serial.println("Error - enabling the system cache failed.");
}

// Configure the board for low power operation.
am_bsp_low_power_init();

// Enable only the first 512KB bank of Flash (0).  Disable Flash(1)
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_MIN))
{
//am_util_stdio_printf("Error - configuring the flash memory failed.\n");
Serial.println("Error - configuring the flash memory failed.");
}

// Enable the first 32K of TCM SRAM.
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_SRAM_32K_DTCM))
{
//am_util_stdio_printf("Error - configuring the SRAM failed.\n");
Serial.println("Error - configuring the SRAM failed.");
}

// Start the ITM interface.
am_bsp_itm_printf_enable();

// Start the CTIMER A3 for timer-based ADC measurements.

// Enable interrupts.
am_hal_interrupt_master_enable();

// Set a pin to act as our ADC input

// Trigger the ADC sampling for the first time manually.
{
//am_util_stdio_printf("Error - triggering the ADC failed.\n");
Serial.println("Error - triggering the ADC failed.");
}

// Print the banner.
am_util_stdio_terminal_clear();
//am_util_stdio_printf("ADC Example with 1.2Msps and LPMODE=0\n");
Serial.println("ADC Example with 1.2Msps and LPMODE=0");

// Allow time for all printing to finish.
am_util_delay_ms(10);

// We are done printing. Disable debug printf messages on ITM.
//    am_bsp_debug_printf_disable();
//#endif

}

void loop() {
// Go to Deep Sleep.
useconds_refresh = micros();
{
sleep();
}

// Check for DMA errors.
{
//am_util_stdio_printf("DMA Error occured\n");
Serial.println("DMA Error occured");
while(1);
}

// Check if the ADC DMA completion interrupt occurred.
{
//14 bit is 0-16383 on a range of 0-2V
//Shift result depending on resolution, averaging
result = result >> (6);
// Serial.println(result);
Serial.println(result*(2.0 /16383.0),3);
}
while(1){}
{
uint32_t        ui32SampleCount;
am_util_stdio_printf("DMA Complete\n");
&ui32SampleCount,
SampleBuffer))
{
//am_util_stdio_printf("Error - failed to process samples.\n");
Serial.println("Error - failed to process samples.");
}
}
#endif

// Reset the DMA completion and error flags.

{
//am_util_stdio_printf("Error - clearing the ADC interrupts failed.\n");
Serial.println("Error - clearing the ADC interrupts failed.");
}

// Trigger the ADC sampling for the first time manually.
{
//am_util_stdio_printf("Error - triggering the ADC failed.\n");
Serial.println("Error - triggering the ADC failed.");
}
} // if ()

}``````

### Re: Hi speed analog acquisition?#210099

By dlp
#210099
There was a typo in the last working sketch for this so I'll re-post it.
Now that I've got 1 channel working, I'm going for 2 channels, but it's eluding me so far. Any thoughts?

Edited by moderator to add code tags.
Code: Select all
``````//*****************************************************************************
//
//!
//! @brief This example takes samples with the ADC at high-speed using DMA.
//!
//! Purpose: This example shows the CTIMER-A3 triggering repeated samples of an external
//! input at 1.2Msps in LPMODE0.  The example uses the CTIMER-A3 to trigger
//! ADC sampling.  Each data point is 8 sample average and is transferred
//! from the ADC FIFO into an SRAM buffer using DMA.

#include "am_bsp.h"

// Define a circular buffer to hold the ADC samples
//*****************************************************************************
#define ResolutionBits 14

unsigned long useconds_refresh;

// Define the ADC SE0 pin to be used. (A4)
{
};

// Interrupt handler for the ADC.
//*****************************************************************************
extern "C" void am_adc_isr()  //must use 'extern "C" ' for the Artemis
{

{
}

{
}

// If we got a DMA complete, set the flag.
{
}

// If we got a DMA error, set the flag.
{
}
}

// Set up the core for sleeping, and then go to sleep.
//*****************************************************************************
void sleep()
{
// Disable things that can't run in sleep mode.
//    am_bsp_debug_printf_disable();
//#endif

// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);

// Re-enable peripherals for run mode.
//    am_bsp_debug_printf_enable();
//#endif

}

//*****************************************************************************
{

// Configure the ADC to use DMA for the sample transfer.
{
//am_util_stdio_printf("Error - configuring ADC DMA failed.\n");
Serial.println("Error - configuring ADC DMA failed.");
}
// Reset the ADC DMA flags.

}

//*****************************************************************************
{

// Initialize the ADC and get the handle.
{
//am_util_stdio_printf("Error - reservation of the ADC instance failed.\n");
Serial.println("Error - reservation of the ADC instance failed.");
}

AM_HAL_SYSCTRL_WAKE,
false) )
{
//am_util_stdio_printf("Error - ADC power on failed.\n");
Serial.println("Error - ADC power on failed.");
}

// Set up the ADC configuration parameters. These settings are reasonable
// for accurate measurements at a low sample rate.
/*
*/
{
}

// Set up an ADC slot
/*

// Single-ended channels
// Differential channels.
// Miscellaneous other signals.

*/
{
//am_util_stdio_printf("Error - configuring ADC Slot 0 failed.\n");
Serial.println("Error - configuring ADC Slot 0 failed.");
}

// Configure the ADC to use DMA for the sample transfer.
// For this example, the samples will be coming in slowly. This means we
// can afford to wake up for every conversion.
//

//
{
}
}

// Initialize the ADC repetitive sample timer A3.
//*****************************************************************************
{
// Start a timer to trigger the ADC periodically (1 second).?? Must be a hold-over from another version
am_hal_ctimer_config_single(3, AM_HAL_CTIMER_TIMERA,
AM_HAL_CTIMER_HFRC_12MHZ    |
AM_HAL_CTIMER_FN_REPEAT     |
AM_HAL_CTIMER_INT_ENABLE);

am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA3);

am_hal_ctimer_period_set(3, AM_HAL_CTIMER_TIMERA, 10, 5); //10 tick period, 5 ticks wide

// Enable the timer A3 to trigger the ADC directly

// Start the timer.
am_hal_ctimer_start(3, AM_HAL_CTIMER_TIMERA);
}

void setup() {
Serial.begin(115200);
while (!Serial) {}
// Set the clock frequency.
if (AM_HAL_STATUS_SUCCESS != am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0))
{
//am_util_stdio_printf("Error - configuring the system clock failed.\n");
Serial.println("Error - configuring the system clock failed.");
}

// Set the default cache configuration and enable it.
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_config(&am_hal_cachectrl_defaults))
{
//am_util_stdio_printf("Error - configuring the system cache failed.\n");
Serial.println("Error - configuring the system cache failed.");
}
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_enable())
{
//am_util_stdio_printf("Error - enabling the system cache failed.\n");
Serial.println("Error - enabling the system cache failed.");
}

// Configure the board for low power operation.
am_bsp_low_power_init();

// Enable only the first 512KB bank of Flash (0).  Disable Flash(1)
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_MIN))
{
//am_util_stdio_printf("Error - configuring the flash memory failed.\n");
Serial.println("Error - configuring the flash memory failed.");
}

// Enable the first 32K of TCM SRAM.
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_SRAM_32K_DTCM))
{
//am_util_stdio_printf("Error - configuring the SRAM failed.\n");
Serial.println("Error - configuring the SRAM failed.");
}

// Start the ITM interface.
am_bsp_itm_printf_enable();

// Start the CTIMER A3 for timer-based ADC measurements.

// Enable interrupts.
am_hal_interrupt_master_enable();

// Set a pin to act as our ADC input

// Trigger the ADC sampling for the first time manually.
{
//am_util_stdio_printf("Error - triggering the ADC failed.\n");
Serial.println("Error - triggering the ADC failed.");
}

// Print the banner.
am_util_stdio_terminal_clear();
//am_util_stdio_printf("ADC Example with 1.2Msps and LPMODE=0\n");
Serial.println("ADC Example with 1.2Msps and LPMODE=0");

// Allow time for all printing to finish.
am_util_delay_ms(10);

// We are done printing. Disable debug printf messages on ITM.
//    am_bsp_debug_printf_disable();
//#endif

}

void loop() {
// Go to Deep Sleep.
useconds_refresh = micros();
{
sleep();
}

// Check for DMA errors.
{
//am_util_stdio_printf("DMA Error occured\n");
Serial.println("DMA Error occured");
while(1);
}

// Check if the ADC DMA completion interrupt occurred.
{
//14 bit is 0-16383 on a range of 0-2V
//Shift result depending on resolution, averaging
result = result >> (6);
// Serial.println(result);
Serial.println(result*(2.0 /16383.0),3);
}
while(1){}   //pause execution

// Reset the DMA completion and error flags.

{
//am_util_stdio_printf("Error - clearing the ADC interrupts failed.\n");
Serial.println("Error - clearing the ADC interrupts failed.");
}

// Trigger the ADC sampling for the first time manually.
{
//am_util_stdio_printf("Error - triggering the ADC failed.\n");
Serial.println("Error - triggering the ADC failed.");
}
} // if ()

}``````

### Re: Hi speed analog acquisition? - 2 Channel#210296

By dlp
#210296
Here's a mod to the sketch that will do 2 Channels at high speed. A 2kHz signal will put 2 completes waves in the buffer and I measure a sample frequency of 552kS/s per channel. As expected half the frequency of a single channel.

MODERATOR NOTE: PLEASE USE CODE TAGS WHEN INCLUDING CODE.
Code: Select all
``````//*****************************************************************************
//
//!
//! @brief This example takes samples with the ADC at high-speed using DMA.
//!
//! Purpose: This example shows the CTIMER-A3 triggering repeated samples of an external
//! input at 1.2Msps in LPMODE0. The example uses the CTIMER-A3 to trigger
//! ADC sampling. Each data point is 8 sample average and is transferred
//! from the ADC FIFO into an SRAM buffer using DMA.

// uses bit-masking to parse out the data

#include "am_bsp.h"

#define ADC_SAMPLE_BUF_SIZE (1024) //2channels at 512 samples.  Ch1 and Ch2 alternate in the buffer

unsigned long useconds_refresh;

// Define the ADC SE0 pin to be used. (A4)
{
};

// Define the ADC SE3 pin to be used. (A5)
{
};

// Interrupt handler for the ADC.
//*****************************************************************************
extern "C" void am_adc_isr() //must use 'extern "C" ' for the Artemis
{

{
}

{
}

// If we got a DMA complete, set the flag.
{
}

// If we got a DMA error, set the flag.
{
}
}

// Set up the core for sleeping, and then go to sleep.
//*****************************************************************************
void sleep()
{
// Disable things that can't run in sleep mode.
// am_bsp_debug_printf_disable();
//#endif

// Go to Deep Sleep.
am_hal_sysctrl_sleep(AM_HAL_SYSCTRL_SLEEP_DEEP);

// Re-enable peripherals for run mode.
// am_bsp_debug_printf_enable();
//#endif

}

//*****************************************************************************
{

// Configure the ADC to use DMA for the sample transfer.
{
Serial.println("Error - configuring ADC DMA failed.");
}
// Reset the ADC DMA flags.

}

//*****************************************************************************
{

// Initialize the ADC and get the handle.
{
Serial.println("Error - reservation of the ADC instance failed.");
}

AM_HAL_SYSCTRL_WAKE,
false) )
{
//am_util_stdio_printf("Error - ADC power on failed.\n");
Serial.println("Error - ADC power on failed.");
}

// Set up the ADC configuration parameters. These settings are reasonable
// for accurate measurements at a low sample rate.
/*
*/
{
}

// Set up an ADC slot 0
/*

// Single-ended channels
// Differential channels.
// Miscellaneous other signals.
*/

{
//am_util_stdio_printf("Error - configuring ADC Slot 0 failed.\n");
Serial.println("Error - configuring ADC Slot 0 failed.");
}

// Set up an ADC slot 1
{
Serial.println("Error - configuring ADC Slot 0 failed.");
}

// Configure the ADC to use DMA for the sample transfer.

//

{
}
}

// Initialize the ADC repetitive sample timer A3.
//*****************************************************************************
{
// Start a timer to trigger the ADC periodically
am_hal_ctimer_config_single(3, AM_HAL_CTIMER_TIMERA,
AM_HAL_CTIMER_HFRC_12MHZ |
AM_HAL_CTIMER_FN_REPEAT |
AM_HAL_CTIMER_INT_ENABLE);

am_hal_ctimer_int_enable(AM_HAL_CTIMER_INT_TIMERA3);

am_hal_ctimer_period_set(3, AM_HAL_CTIMER_TIMERA, 10, 5); //10 tick period, 5 ticks wide

// Enable the timer A3 to trigger the ADC directly

// Start the timer.
am_hal_ctimer_start(3, AM_HAL_CTIMER_TIMERA);
}

void setup() {
Serial.begin(115200);
while (!Serial) {}
// Set the clock frequency.
if (AM_HAL_STATUS_SUCCESS != am_hal_clkgen_control(AM_HAL_CLKGEN_CONTROL_SYSCLK_MAX, 0))
{
Serial.println("Error - configuring the system clock failed.");
}

// Set the default cache configuration and enable it.
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_config(&am_hal_cachectrl_defaults))
{
Serial.println("Error - configuring the system cache failed.");
}
if (AM_HAL_STATUS_SUCCESS != am_hal_cachectrl_enable())
{
Serial.println("Error - enabling the system cache failed.");
}

// Configure the board for low power operation.
am_bsp_low_power_init();

// Enable only the first 512KB bank of Flash (0). Disable Flash(1)
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_FLASH_MIN))
{
Serial.println("Error - configuring the flash memory failed.");
}

// Enable the first 32K of TCM SRAM.
if (AM_HAL_STATUS_SUCCESS != am_hal_pwrctrl_memory_enable(AM_HAL_PWRCTRL_MEM_SRAM_32K_DTCM))
{
Serial.println("Error - configuring the SRAM failed.");
}

// Start the ITM interface.
//am_bsp_itm_printf_enable();

// Start the CTIMER A3 for timer-based ADC measurements.

// Enable interrupts.
am_hal_interrupt_master_enable();

// Set a pin to act as our ADC input

// Trigger the ADC sampling for the first time manually.
{
Serial.println("Error - triggering the ADC failed.");
}

// Print the banner.
am_util_stdio_terminal_clear();
Serial.println("ADC Example with 1.2Msps and LPMODE=0");

// Allow time for all printing to finish.
am_util_delay_ms(10);

}

void loop() {
// Go to Deep Sleep.
useconds_refresh = micros();
{
sleep();
}

// Check for DMA errors.
{
//am_util_stdio_printf("DMA Error occured\n");
Serial.println("DMA Error occured");
while (1);
}

// Check if the ADC DMA completion interrupt occurred.
{
bool toggle = 0;
for (int i = 0; i < ADC_SAMPLE_BUF_SIZE; i++) {
//14 bit is 0-16383 on a range of 0-2V
uint32_t mask = 0xFFFC0;  // all ones for bits 6-19, other bits zeroed
//Shift result depending on resolution, averaging
result = result & mask; //get bits 6-19 data only
result = result >> (6); //remove the fractional values

// Serial.println(result);
if (!toggle){
Serial.print(result * (2.0 / 16383.0), 3);
Serial.print(",");
}
else{
Serial.println(result * (2.0 / 16383.0), 3);
}
toggle = !toggle;
}

while (1) {}  // stop to view data

// Reset the DMA completion and error flags.

{
//am_util_stdio_printf("Error - clearing the ADC interrupts failed.\n");
Serial.println("Error - clearing the ADC interrupts failed.");
}

// Trigger the ADC sampling for the first time manually.
{
//am_util_stdio_printf("Error - triggering the ADC failed.\n");
Serial.println("Error - triggering the ADC failed.");
}
}

}``````
Topic permissions

You can post new topics in this forum
You can reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

###### long long title how many chars? lets see 123 ok more? yes 60

We have created lots of YouTube videos just so you can achieve [...]

###### Another post test yes yes yes or no, maybe ni? :-/

The best flat phpBB theme around. Period. Fine craftmanship and [...]

###### Do you need a super MOD? Well here it is. chew on this

All you need is right here. Content tag, SEO, listing, Pizza and spaghetti [...]

###### Lasagna on me this time ok? I got plenty of cash

this should be fantastic. but what about links,images, bbcodes etc etc? [...]