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

How to control nrf_drv_pwm_simple_playback min max brightness and interval delay playback

Hi,

I notice the brightness playback level cannot be reduced/control by reducing nrf_pwm_sequence_t -> .values.p_common during playback , may I know how to adjust the duty cycle(which will affect the brightness)? Please help me.

 1) If I want to set the led fading using PWM on from 0-50% brightness range only , and I did by calling nrfx_pwm_sequence_values_update(&m_pwm0, 1, seq1) which is not effective at all.

2) How can I control the interval between the 2s Brightness softblink and 18s of quiet period and repeat again?

HW: PCA10056

SW: nRF5_SDK_15.2.0_9412b96

 

/**
 * Copyright (c) 2015 - 2018, Nordic Semiconductor ASA
 *
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without modification,
 * are permitted provided that the following conditions are met:
 *
 * 1. Redistributions of source code must retain the above copyright notice, this
 *    list of conditions and the following disclaimer.
 *
 * 2. Redistributions in binary form, except as embedded into a Nordic
 *    Semiconductor ASA integrated circuit in a product or a software update for
 *    such product, must reproduce the above copyright notice, this list of
 *    conditions and the following disclaimer in the documentation and/or other
 *    materials provided with the distribution.
 *
 * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
 *    contributors may be used to endorse or promote products derived from this
 *    software without specific prior written permission.
 *
 * 4. This software, with or without modification, must only be used with a
 *    Nordic Semiconductor ASA integrated circuit.
 *
 * 5. Any software provided in binary form under this license must not be reverse
 *    engineered, decompiled, modified and/or disassembled.
 *
 * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
 * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
 * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
 * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 *
 */
/** @file
 *
 * @defgroup led_softblink_example_main main.c
 * @{
 * @ingroup led_softblink_example
 * @brief LED Soft Blink Example Application main file.
 *
 */

#include <stdbool.h>
#include <stdint.h>
#include "nrf_delay.h"
#include "nrf_gpio.h"
#include "boards.h"
#include "led_softblink.h"
#include "app_error.h"
#include "sdk_errors.h"
#include "app_timer.h"
#include "nrf_drv_clock.h"
#include "app_util_platform.h"
#include "nrf_drv_pwm.h"
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
#include "bsp.h"

TaskHandle_t  demo1_task_handle;
TaskHandle_t  demo2_task_handle;

static nrf_drv_pwm_t m_pwm0 = NRF_DRV_PWM_INSTANCE(0);
static nrf_drv_pwm_t m_pwm1 = NRF_DRV_PWM_INSTANCE(1);
static nrf_drv_pwm_t m_pwm2 = NRF_DRV_PWM_INSTANCE(2);

// This is for tracking PWM instances being used, so we can unintialize only
// the relevant ones when switching from one demo to another.
#define USED_PWM(idx) (1UL << idx)
static uint8_t m_used = 0;
#define LED_BLINK_TIME_SEC (2)
#define DEMO1_TOP ((LED_BLINK_TIME_SEC*5000)+(10000))
#define DEMO1_STEP (200)
#define COUNTER_DELAY_SEC ((18*25 + 50)*2)
#define COUNTER_TICK ((LED_BLINK_TIME_SEC*25 + 50)*2)
#define RED_LED_CTR ((0xFF*0xB)/(DEMO1_TOP/DEMO1_STEP))
#define GRN_LED_CTR ((0x7F*0xB)/(DEMO1_TOP/DEMO1_STEP))
#define BLU_LED_CTR ((0x20*0xB)/(DEMO1_TOP/DEMO1_STEP))
static uint16_t const              m_demo1_top  = DEMO1_TOP;
static uint16_t const              m_demo1_step = DEMO1_STEP;
static uint16_t counter[3];
static uint32_t timer_tick;
static uint8_t                     m_demo1_phase;
static uint8_t idle_led;
//static nrf_pwm_values_common_t m_demo1_seq_values;
static nrf_pwm_values_individual_t m_demo1_seq_values;

static nrf_pwm_sequence_t const    m_demo1_seq =
{
    .values.p_individual = &m_demo1_seq_values,
    .length              = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),
    .repeats             = 0,
    .end_delay           = 0
};

//static nrf_pwm_sequence_t const    m_demo1_seq =
//{
//    .values.p_common = &m_demo1_seq_values,
//    .length              = NRF_PWM_VALUES_LENGTH(m_demo1_seq_values),
//    .repeats             = 0,
//    .end_delay           = 0
//};

static void demo1_handler(nrf_drv_pwm_evt_type_t event_type)
{
    if (event_type == NRF_DRV_PWM_EVT_FINISHED)
    {
//        uint8_t channel    = m_demo1_phase >> 1;
        bool    down       = m_demo1_phase & 1;
        bool    next_phase = false;

        uint16_t * p_channels = (uint16_t *)&m_demo1_seq_values;
        uint16_t value = p_channels[0];

//  if(idle_led)
//  {
//    --timer_tick;
//  }
//  else
//  {
        if (down)
        {
           counter[0]-= RED_LED_CTR;
           counter[1]-= GRN_LED_CTR;
           counter[2]-= BLU_LED_CTR;

           value -= m_demo1_step;
           if(value == 0)
            {
                next_phase = true;
            }
        }
        else
        {
            counter[0]+= RED_LED_CTR;
            counter[1]+= GRN_LED_CTR;
            counter[2]+= BLU_LED_CTR;

            value += m_demo1_step;
            if (value >= m_demo1_top)
            {
                next_phase = true;
            }
        }

          nrf_pwm_values_t seq1 =
          {
              seq1.p_individual = &counter
          };

            nrfx_pwm_sequence_values_update(&m_pwm0, 1, seq1);
       p_channels[0] = value;
              p_channels[1] = value;
                     p_channels[2] = value;

        if (next_phase)
        {
            if (++m_demo1_phase >= 2 * 3)
            {
                m_demo1_phase = 0;
            }
        }
        ++timer_tick;
//    }
        if((timer_tick >= COUNTER_TICK)&&(idle_led == 0))
        {
 //         idle_led = 1;
//          timer_tick = COUNTER_DELAY_SEC;
nrf_delay_ms(18000);
 //       }else if((idle_led == 1)&&(timer_tick==0))
 //       {
 //                 idle_led = 0;
 timer_tick=0;
        }
    }
}

static void demo1 (void * pvParameter)
{
    UNUSED_PARAMETER(pvParameter);


    /*
     * This demo plays back a sequence with different values for individual
     * channels (LED 1 - LED 4). Only four values are used (one per channel).
     * Every time the values are loaded into the compare registers, they are
     * updated in the provided event handler. The values are updated in such
     * a way that increase and decrease of the light intensity can be observed
     * continuously on succeeding channels (one second per channel).
     */

    nrf_drv_pwm_config_t const config0 =
    {
        .output_pins =
        {
            BSP_LED_0 | NRF_DRV_PWM_PIN_INVERTED, // channel 0
            BSP_LED_1 | NRF_DRV_PWM_PIN_INVERTED, // channel 1
            BSP_LED_2 | NRF_DRV_PWM_PIN_INVERTED, // channel 2
            NRF_DRV_PWM_PIN_NOT_USED
        },
        .irq_priority = APP_IRQ_PRIORITY_LOWEST,
        .base_clock   = NRF_PWM_CLK_2MHz,
        .count_mode   = NRF_PWM_MODE_UP,
        .top_value    = m_demo1_top,
        .load_mode    = NRF_PWM_LOAD_INDIVIDUAL,
        .step_mode    = NRF_PWM_STEP_AUTO
    };
    APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, demo1_handler));
  //APP_ERROR_CHECK(nrf_drv_pwm_init(&m_pwm0, &config0, NULL));
    m_used |= USED_PWM(0);

    static uint16_t /*const*/ seq_values[] =
    {
        0x2800,
        0x1400,
        0x400,
        0x0,
    };
    nrf_pwm_sequence_t const seq =
    {
//        .values.p_common = seq_values,
        .values.p_individual = seq_values,
        .length          = NRF_PWM_VALUES_LENGTH(seq_values),
        .repeats         = 0,
        .end_delay       = 0
    };

    m_demo1_phase                = 0;
    counter[0] = 0;
    counter[1] = 0;
    counter[2] = 0;
    timer_tick = 0;
    idle_led = 0;
    (void)nrf_drv_pwm_simple_playback(&m_pwm0, &m_demo1_seq, 1,
                                      NRF_DRV_PWM_FLAG_LOOP);
// (void)nrf_drv_pwm_simple_playback(&m_pwm0, &seq, 1,
//                                    NRF_DRV_PWM_FLAG_LOOP);
    while(1);
}

static void demo2 (void * pvParameter)
{
  uint8_t test;

    while(1)
    {
      test = 0;
    };

}

static void bsp_evt_handler(bsp_event_t evt)
{
    void (* const demos[])(void *) =
    {
        demo1,
    };
    uint8_t const  demo_idx_max = (sizeof(demos) / sizeof(demos[0])) - 1;
    static uint8_t demo_idx     = 0;

    switch (evt)
    {
        // Button 1 - switch to the previous demo.
        case BSP_EVENT_KEY_0:
            if (demo_idx > 0)
            {
                --demo_idx;
            }
            else
            {
                demo_idx = demo_idx_max;
            }
            break;

        // Button 2 - switch to the next demo.
        case BSP_EVENT_KEY_1:
            if (demo_idx < demo_idx_max)
            {
                ++demo_idx;
            }
            else
            {
                demo_idx = 0;
            }
            break;

        default:
            return;
    }

    if (m_used & USED_PWM(0))
    {
        nrf_drv_pwm_uninit(&m_pwm0);
    }
    if (m_used & USED_PWM(1))
    {
        nrf_drv_pwm_uninit(&m_pwm1);
    }
    if (m_used & USED_PWM(2))
    {
        nrf_drv_pwm_uninit(&m_pwm2);
    }
    m_used = 0;

    demos[demo_idx](NULL);
}


static void init_bsp()
{
    APP_ERROR_CHECK(nrf_drv_clock_init());
    nrf_drv_clock_lfclk_request(NULL);

    APP_ERROR_CHECK(app_timer_init());
    APP_ERROR_CHECK(bsp_init(BSP_INIT_BUTTONS, bsp_evt_handler));
    APP_ERROR_CHECK(bsp_buttons_enable());
}

/**
 * @brief Function for application main entry.
 */
int main(void)
{


    init_bsp();

        /* Create task for LED0 blinking with priority set to 2 */
    UNUSED_VARIABLE(xTaskCreate(demo1, "SOFT_BLINK", configMINIMAL_STACK_SIZE + 400, NULL, 2, &demo1_task_handle));
        /* Create task for LED0 blinking with priority set to 2 */
 //   UNUSED_VARIABLE(xTaskCreate(demo2, "TEST", configMINIMAL_STACK_SIZE + 400, NULL, 3, &demo2_task_handle));
     
    /* Activate deep sleep mode */
    SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk;

   
    /* Start FreeRTOS scheduler. */
    vTaskStartScheduler();

    //soft_blink_function(NULL);
    while (true)
    {
        /* FreeRTOS should not be here... FreeRTOS goes back to the start of stack
         * in vTaskStartScheduler function. */
    }
}

/** @} */

Related