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. */
}
}
/** @} */