You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Hi, I want to use two ADC (ADS8864) and esp32 to sample analog waveform and send them to PC using WIFI. The data are sampled in a fixed sample rate, for example 100ksps for ADS8864, and I want to use SPI to read them into a buffer. When the data are ready, for example, 256 samples have been collected. I memcpy them out and send them to PC.
I config a timer of 200kHz (5us), and at the interrupt of the timer, I toggle a GPIO (which is connected to the CONV port of ADC), and at every two timer interrupt, I send a semaphore to notice a task to read the ADC using the SPI peripheral of esp32.
However, 1. we found that the CONV signal is not stable, which is not precisely 100khz with sharp edges. the duty cycle is approximately 0.4 and the period is changing. 2. How could I read the samples out using a SPI DMA? so that SPI can quietly sample the data and put them in a list or a cyclic buffer. 3. Can I run SPI sample in another core and notify current core when samples are ready?
Is it right in this way (for esp32) to use SPI as a ADC sampler reader and periodically (100KHz) sample an analog waveform? If not, what is the right way to do so?
The corresponding codes are
#defineTIMER_INTR_SEL TIMER_INTR_LEVEL /*!< Timer level interrupt */
#defineTIMER_GROUP TIMER_GROUP_0 /*!< Test on timer group 0 */
#defineTIMER_DIVIDER 16 /*!< Hardware timer clock divider, 80 to get 1MHz clock to timer */
#defineTIMER_SCALE (TIMER_BASE_CLK / TIMER_DIVIDER) /*!< used to calculate counter value */
#defineTIMER_FINE_ADJ (1.4*(TIMER_BASE_CLK / TIMER_DIVIDER)/1000000) /*!< used to compensate alarm value */
#defineTIMER_INTERVAL0_SEC (0.000005) /*!< test interval for timer 0 */
xSemaphoreHandlesemaphore;
volatileintcnt=0;
staticspi_device_handle_tspi1,spi2;
voidIRAM_ATTRtimer_group0_isr(void*para)
{
inttimer_idx= (int) para;
intled_val;
uint32_tintr_status=TIMERG0.int_st_timers.val;
if((intr_status&BIT(timer_idx)) &&timer_idx==TIMER_0) {
TIMERG0.hw_timer[timer_idx].update=1;
TIMERG0.int_clr_timers.t0=1;
led_val= (cnt+1)%2;
gpio_set_level(GPIO_CONV, led_val);
cnt++;
if (led_val==0){
// if CONVST falling down, tell SPI to read!xSemaphoreGiveFromISR(semaphore, NULL);
}
TIMERG0.hw_timer[timer_idx].config.alarm_en=1;
}
}
// config and start timerstaticvoidtg0_timer0_init()
{
inttimer_group=TIMER_GROUP_0;
inttimer_idx=TIMER_0;
timer_config_tconfig;
config.alarm_en=1;
config.auto_reload=1;
config.counter_dir=TIMER_COUNT_UP;
config.divider=TIMER_DIVIDER;
config.intr_type=TIMER_INTR_SEL;
config.counter_en=TIMER_PAUSE;
/*Configure timer*/timer_init(timer_group, timer_idx, &config);
/*Stop timer counter*/timer_pause(timer_group, timer_idx);
/*Load counter value */timer_set_counter_value(timer_group, timer_idx, 0x00000000ULL);
/*Set alarm value*/timer_set_alarm_value(timer_group, timer_idx, (TIMER_INTERVAL0_SEC*TIMER_SCALE) -TIMER_FINE_ADJ);
/*Enable timer interrupt*/timer_enable_intr(timer_group, timer_idx);
/*Set ISR handler*/timer_isr_register(timer_group, timer_idx, timer_group0_isr, (void*) timer_idx, ESP_INTR_FLAG_IRAM, NULL);
/*Start timer counter*/timer_start(timer_group, timer_idx);
}
voidtimer0_task()
{
spi_transaction_tt;
memset(&t, 0, sizeof(t));
t.length=16;
t.flags=SPI_TRANS_USE_RXDATA;
while(1){
xSemaphoreTake(semaphore, portMAX_DELAY);
spi_device_transmit(spi1, &t);
// sample ADC1spi_device_transmit(spi2, &t);
// sample ADC2
}
//taskdelete
}
in main_task
esp_err_tret;
spi_bus_config_tbuscfg1={
.miso_io_num=PIN_NUM_MISO1,
.mosi_io_num=PIN_NUM_MOSI1,
.sclk_io_num=PIN_NUM_CLK1,
.quadwp_io_num=-1,
.quadhd_io_num=-1
};
spi_device_interface_config_tdevcfg1={
.clock_speed_hz=16*1000*1000, //Clock out at 16MHz
.mode=3, //SPI mode 3
.queue_size=1, //We want to be able to queue 1 transactions at a time
};
spi_bus_config_tbuscfg2={
.miso_io_num=PIN_NUM_MISO2,
.mosi_io_num=PIN_NUM_MOSI2,
.sclk_io_num=PIN_NUM_CLK2,
.quadwp_io_num=-1,
.quadhd_io_num=-1
};
spi_device_interface_config_tdevcfg2={
.clock_speed_hz=16*1000*1000, //Clock out at 16MHz
.mode=3, //SPI mode 3
.queue_size=1, //We want to be able to queue 1 transactions at a time
};
ret=spi_bus_initialize(HSPI_HOST, &buscfg1, 1);
ret=spi_bus_initialize(VSPI_HOST, &buscfg2, 2);
//assert(ret==ESP_OK);ret=spi_bus_add_device(HSPI_HOST, &devcfg1, &spi1);
ret=spi_bus_add_device(VSPI_HOST, &devcfg2, &spi2);
//assert(ret==ESP_OK);
The text was updated successfully, but these errors were encountered:
FayeY
changed the title
How to use SPI of esp32 to read ADC samples periodically with fixed sample rate?
[TW#16070] How to use SPI of esp32 to read ADC samples periodically with fixed sample rate?
Oct 28, 2017
projectgus
changed the title
[TW#16070] How to use SPI of esp32 to read ADC samples periodically with fixed sample rate?
How to use SPI of esp32 to read ADC samples periodically with fixed sample rate? (IDFGH-101)
Mar 12, 2019
For what it's worth, you have a RMT or LEDC for precise GPIO control. You should not use a timer that requires work from the RTOS if you don't want any jitter.
Hi, I want to use two ADC (ADS8864) and esp32 to sample analog waveform and send them to PC using WIFI. The data are sampled in a fixed sample rate, for example 100ksps for ADS8864, and I want to use SPI to read them into a buffer. When the data are ready, for example, 256 samples have been collected. I
memcpy
them out and send them to PC.I config a timer of 200kHz (5us), and at the interrupt of the timer, I toggle a GPIO (which is connected to the CONV port of ADC), and at every two timer interrupt, I send a semaphore to notice a task to read the ADC using the SPI peripheral of esp32.
However, 1. we found that the CONV signal is not stable, which is not precisely 100khz with sharp edges. the duty cycle is approximately 0.4 and the period is changing. 2. How could I read the samples out using a SPI DMA? so that SPI can quietly sample the data and put them in a list or a cyclic buffer. 3. Can I run SPI sample in another core and notify current core when samples are ready?
Is it right in this way (for esp32) to use SPI as a ADC sampler reader and periodically (100KHz) sample an analog waveform? If not, what is the right way to do so?
The corresponding codes are
in
main_task
The text was updated successfully, but these errors were encountered: