Hello,
I'm using BL654 module (nrf52840 inside); SDK15; softdevice s140; IAR.
In my projects I'm using peripherals: I2C(TWI), SPI. Project based on ble_app_uart example (most of sdk_config.h are default, exept TWI/SPI instances and timer3)
My goal is to add sampling data from 4 analog input channels:
Channel 1 - input 0;
Channel 2 - input 5;
Channel 3 - input 4;
Channel 4 - input 7;
My code for SAADC:
#define SAMPLES_IN_BUFFER 4 #define BUFFERS_IN_CH 2 #define SAADC_SAMPLE_PERIOR_MS 1000 volatile uint8_t state = 1; static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(3); static nrf_saadc_value_t m_buffer_pool[BUFFERS_IN_CH][SAMPLES_IN_BUFFER]; static nrf_ppi_channel_t m_ppi_channel; static uint32_t m_adc_evt_counter; void timer_handler(nrf_timer_event_t event_type, void * p_context) { // } void saadc_sampling_event_init(void) { ret_code_t err_code; err_code = nrf_drv_ppi_init(); APP_ERROR_CHECK(err_code); nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG; timer_cfg.bit_width = NRF_TIMER_BIT_WIDTH_32; err_code = nrf_drv_timer_init(&m_timer, &timer_cfg, timer_handler); APP_ERROR_CHECK(err_code); // setup m_timer for compare event every X ms uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, SAADC_SAMPLE_PERIOR_MS); nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL3, ticks, NRF_TIMER_SHORT_COMPARE3_CLEAR_MASK, false); nrf_drv_timer_enable(&m_timer); uint32_t timer_compare_event_addr = nrf_drv_timer_compare_event_address_get(&m_timer, NRF_TIMER_CC_CHANNEL3); uint32_t saadc_sample_task_addr = nrf_drv_saadc_sample_task_get(); // setup ppi channel so that timer compare event is triggering sample task in SAADC err_code = nrf_drv_ppi_channel_alloc(&m_ppi_channel); APP_ERROR_CHECK(err_code); err_code = nrf_drv_ppi_channel_assign(m_ppi_channel, timer_compare_event_addr, saadc_sample_task_addr); APP_ERROR_CHECK(err_code); } void saadc_sampling_event_enable(void) { ret_code_t err_code = nrf_drv_ppi_channel_enable(m_ppi_channel); APP_ERROR_CHECK(err_code); } void saadc_callback(nrf_drv_saadc_evt_t const * p_event) { if (p_event->type == NRF_DRV_SAADC_EVT_DONE) { ret_code_t err_code; // set buffers err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); // print samples on hardware UART and parse data for BLE transmission NRF_LOG_INFO("ADC event number: %d\r\n",(int)m_adc_evt_counter); for (int i = 0; i < SAMPLES_IN_BUFFER; i++) { NRF_LOG_INFO("CH_[%d] adc_value: %d\r\n", i, p_event->data.done.p_buffer[i]); } m_adc_evt_counter++; } } void saadc_init(void) { ret_code_t err_code; nrf_drv_saadc_config_t saadc_config = NRF_DRV_SAADC_DEFAULT_CONFIG; saadc_config.resolution = NRF_SAADC_RESOLUTION_12BIT; nrf_saadc_channel_config_t channel_1_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0); nrf_saadc_channel_config_t channel_2_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN5); nrf_saadc_channel_config_t channel_3_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4); nrf_saadc_channel_config_t channel_4_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7); err_code = nrf_drv_saadc_init(&saadc_config, saadc_callback); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(0, &channel_1_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(5, &channel_2_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(4, &channel_3_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(7, &channel_4_config); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[0],SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_buffer_convert(m_buffer_pool[1],SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); } void SAADC_Init(void) { saadc_sampling_event_init(); saadc_init(); saadc_sampling_event_enable(); }
Main(removed stuff with TWI and SPI):
int main(void) { uart_init(); log_init(); timers_init(); power_management_init(); ble_stack_init(); //printf("ble_stack started...\r\n"); gap_params_init(); gatt_init(); services_init(); advertising_init(); conn_params_init(); SAADC_Init(); // Start execution. advertising_start(); // Enter main loop. for (;;) { idle_state_handle(); } }
Problem:
Channel's position numbers doest match their positions in output. And sometimes hopping in arrays...
For example, I'm shorting AIN0 (channel #1) to GND and thats what I see under debug:
AIN5 (channel #2):
AIN4 (channel #3):
AIN7 (channel #4):
And one more things I would like to ask:
Since TIMER0 is used by softdevice, I'm using TIMER3 for SAADC. Am I correct that in saadc_sampling_event_init() I shoud compare events/adresses for TIMER3?
Regards