Hello, i am making a "simple" project, the goal being changing the duty cycle of the pwm depending on saadc sample value. My goal is to sample audio, process it ( low pass filter), and then output with PWM + hardware filtering.
My code works with the BSP_LEDS outputs ( i can control the light trhough a potentiometer).
The thing is:
- When i plug an external led to the BSP_LED1 pin (p0.13), it kind of work but some strange things appears ( like the external led is still on when the duty cycle is 0, but the internal led still works properly).
- I told myself that it should be an hardware problem due to the actual internal LED, so i will use an other GPIO to output pwm and put my led on a breadboard.
- Here is my code :
#include <stdbool.h> #include <stdint.h> #include <stdio.h> #include <string.h> #include "nrf.h" #include "nrf_drv_saadc.h" #include "nrf_drv_ppi.h" #include "nrf_drv_timer.h" #include "boards.h" #include "app_error.h" #include "nrf_delay.h" #include "app_util_platform.h" #include "nrf_pwr_mgmt.h" #include "app_pwm.h" #include "nrf_log.h" #include "nrf_log_ctrl.h" #include "nrf_log_default_backends.h" #define SAMPLES_IN_BUFFER 1 volatile uint8_t state = 1; static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(0); static nrf_saadc_value_t m_buffer_pool[2][SAMPLES_IN_BUFFER]; static nrf_ppi_channel_t m_ppi_channel; static uint32_t m_adc_evt_counter; uint32_t value=50; APP_PWM_INSTANCE(PWM1, 4); // Create the instance "PWM1" using TIMER1. void timer_handler(nrf_timer_event_t event_type, void * p_context) { } static volatile bool ready_flag; // A flag indicating PWM status. void pwm_ready_callback(uint32_t pwm_id) // PWM callback function { ready_flag = true; } 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 400ms */ uint32_t ticks = nrf_drv_timer_ms_to_ticks(&m_timer, 400); nrf_drv_timer_extended_compare(&m_timer, NRF_TIMER_CC_CHANNEL0, ticks, NRF_TIMER_SHORT_COMPARE0_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_CHANNEL0); 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; err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, SAMPLES_IN_BUFFER); APP_ERROR_CHECK(err_code); int i; NRF_LOG_INFO("ADC event number: %d", (int)m_adc_evt_counter); for (i = 0; i < SAMPLES_IN_BUFFER; i++) { NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]); value= p_event->data.done.p_buffer[i]/10; if(value>1000) value=1000; if(value<0) value=0; } m_adc_evt_counter++; } } void saadc_init(void) { ret_code_t err_code; nrf_saadc_channel_config_t channel_config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN0); err_code = nrf_drv_saadc_init(NULL, saadc_callback); APP_ERROR_CHECK(err_code); err_code = nrf_drv_saadc_channel_init(0, &channel_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); } /** * @brief Function for main application entry. */ int main(void) { uint32_t err_code = NRF_LOG_INIT(NULL); APP_ERROR_CHECK(err_code); NRF_LOG_DEFAULT_BACKENDS_INIT(); ret_code_t ret_code = nrf_pwr_mgmt_init(); APP_ERROR_CHECK(ret_code); saadc_init(); saadc_sampling_event_init(); saadc_sampling_event_enable(); nrf_gpio_cfg_output(38); /* 2-channel PWM, 200Hz, output on DK LED pins. */ app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(5000L, 38); /* Switch the polarity of the second channel. */ pwm1_cfg.pin_polarity[1] = APP_PWM_POLARITY_ACTIVE_HIGH; /* Initialize and enable PWM. */ err_code = app_pwm_init(&PWM1, &pwm1_cfg, pwm_ready_callback); APP_ERROR_CHECK(err_code); app_pwm_enable(&PWM1); NRF_LOG_INFO("SAADC HAL simple example started."); while (1) { while (app_pwm_channel_duty_set(&PWM1, 0, value) == NRF_ERROR_BUSY); nrf_delay_ms(25); nrf_pwr_mgmt_run(); NRF_LOG_FLUSH(); } }
To explain shortly, the saadc_callback function update a variable "value", and i update the pwm duty cycle in the while(1) with this value.
Here, line 159, i put pin n°38 wich is supposed to be pin P0.26 , but i have no output on this pin.
If i change this value with BSP_LED_0/1/2, it works .
How could i get my pwm signal outside of the NRF52DK ?
If you have any ideas, i'll be glad to hear them.
Thanks