This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

Problem getting pwm output on other PIN than BSP_LED_X

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

Parents
  • OK, to debug, i'll try with the simple project PWM library in the SDK15 .

    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf.h"
    #include "app_error.h"
    #include "bsp.h"
    #include "nrf_delay.h"
    #include "app_pwm.h"
    #include "nrf_drv_saadc.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "app_util_platform.h"
    #define SAMPLES_IN_BUFFER 1
    
    APP_PWM_INSTANCE(PWM1, 1); // Create the instance "PWM1" using TIMER1.
    
    static volatile bool ready_flag; // A flag indicating PWM status.
    
    void pwm_ready_callback(uint32_t pwm_id) // PWM callback function
    {
        ready_flag = true;
    }
    
    int main(void)
    {
    
        ret_code_t err_code;
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    
        /* 2-channel PWM, 200Hz, output on DK LED pins. */
        app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(5000L, BSP_LED_0);
    
        /* 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.");
    
        uint32_t value;
        while (true)
        {
            for (uint8_t i = 0; i < 40; ++i)
            {
                value = (i < 20) ? (i * 5) : (100 - (i - 20) * 5);
    
                ready_flag = false;
                /* Set the duty cycle - keep trying until PWM is ready... */
                while (app_pwm_channel_duty_set(&PWM1, 0, value) == NRF_ERROR_BUSY)
                    ;
    
                /* ... or wait for callback. */
                while (!ready_flag)
                    ;
                APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, value));
                nrf_delay_ms(25);
            }
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */
    


    So i got the LED blinking.
    If i put a external led on the P0.17 pin, it also blink but in the opposite way :

    With this example, i still got no output if i change to PIN to a GPIO.

Reply
  • OK, to debug, i'll try with the simple project PWM library in the SDK15 .

    #include <stdbool.h>
    #include <stdint.h>
    #include "nrf.h"
    #include "app_error.h"
    #include "bsp.h"
    #include "nrf_delay.h"
    #include "app_pwm.h"
    #include "nrf_drv_saadc.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "app_util_platform.h"
    #define SAMPLES_IN_BUFFER 1
    
    APP_PWM_INSTANCE(PWM1, 1); // Create the instance "PWM1" using TIMER1.
    
    static volatile bool ready_flag; // A flag indicating PWM status.
    
    void pwm_ready_callback(uint32_t pwm_id) // PWM callback function
    {
        ready_flag = true;
    }
    
    int main(void)
    {
    
        ret_code_t err_code;
    
        err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    
    
        /* 2-channel PWM, 200Hz, output on DK LED pins. */
        app_pwm_config_t pwm1_cfg = APP_PWM_DEFAULT_CONFIG_1CH(5000L, BSP_LED_0);
    
        /* 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.");
    
        uint32_t value;
        while (true)
        {
            for (uint8_t i = 0; i < 40; ++i)
            {
                value = (i < 20) ? (i * 5) : (100 - (i - 20) * 5);
    
                ready_flag = false;
                /* Set the duty cycle - keep trying until PWM is ready... */
                while (app_pwm_channel_duty_set(&PWM1, 0, value) == NRF_ERROR_BUSY)
                    ;
    
                /* ... or wait for callback. */
                while (!ready_flag)
                    ;
                APP_ERROR_CHECK(app_pwm_channel_duty_set(&PWM1, 1, value));
                nrf_delay_ms(25);
            }
            NRF_LOG_FLUSH();
        }
    }
    
    /** @} */
    


    So i got the LED blinking.
    If i put a external led on the P0.17 pin, it also blink but in the opposite way :

    With this example, i still got no output if i change to PIN to a GPIO.

Children
Related