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

Power sequence issue SAADC read

Hello Everyone,

I am developing a Zigbee-based device using nRF52840.

So far all functionalities are working without any problem. Now for device load detection, we are developing an initial sequence that reads ADC and depending on that procced for the next action.

Below are the steps which should be carried out for the initial sequence.

  • Initial Sequence

An initial sequence is required at the start of the program (power-up or reset).

This is to determine the maximum duty cycle under the various operating conditions.

The reason for this is the power supply of the control circuit is no longer guaranteed with an increasing duty cycle in the 2 wire configuration.

The dimmer would toggle between a power down and the subsequent program start. To avoid this, the following steps are carried out:

_ Reset

_Gradually increase the duty cycle in small steps

_Voltage measurement after every increase

_ Shutdown of the load when a voltage at the input capacitor of

<100V with 2-wire operation

or 100% control of the load in 3-wire operation.

_Save this determined duty cycle value and declare it as 100%

_Turn off the bulb.

_ Turn ON the bulb till 30% brightness of the measured 100% and continue with normal program sequence.

Attached is the schematic for reference.

Attached is my main.c file where incorporated the above initial sequence steps.

1258.main_20210218.c

The problem here is if I do the power-on sequence of Dev-kit and Custom hardware with custom code then I am not able to execute the initial sequence steps. For Dev-kit (USB power down power-up) and custom hardware (mains supply power down power-up). To execute the steps I have to press the RESET button present on Dev-kit as well as Custom hardware. But it should work first instant with power down power up steps.

I tried to check but in debug mode, it works but flashing the code doesn't work well.

One more method I tried to execute for the initial sequence, below is the attached code. Here I am able to do the power-on sequence without any problem but not able to read ADC values so I tried to add delay_ms() (ex 50msc) but after adding delay my other functionality got affected means LED while brightness incrementing or turning ON it starts flickering. Which not acceptable it should be the smooth end-user point. But without delay not able to read ADC. Let me know what is the problem. Attached is the code.

/**
 * Copyright (c) 2018 - 2019, 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 zigbee_examples_light_bulb main.c
 * @{
 * @ingroup zigbee_examples
 * @brief Dimmable light sample (HA profile)
 */

#include "sdk_config.h"
#include "zboss_api.h"
#include "zb_mem_config_med.h"
#include "zb_ha_dimmable_light.h"
#include "zb_error_handler.h"
#include "zb_nrf52840_internal.h"
#include "zigbee_helpers.h"

#include "bsp.h"
#include "boards.h"
#include "app_pwm.h"
#include "app_timer.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "nrf_drv_gpiote.h"
#include "nrf_drv_timer.h"
#include "nrf_drv_saadc.h"
#include "nrf_delay.h"

#define MAX_CHILDREN                      10                                    /**< The maximum amount of connected devices. Setting this value to 0 disables association to this device.  */
//              /**< Scan only one, predefined channel to find the coordinator. */
#define IEEE_CHANNEL_MASK                  (ZB_TRANSCEIVER_ALL_CHANNELS_MASK)
#define HA_DIMMABLE_LIGHT_ENDPOINT        10                                    /**< Device endpoint, used to receive light controlling commands. */
#define ERASE_PERSISTENT_CONFIG           ZB_FALSE                              /**< Do not erase NVRAM to save the network parameters after device reboot or power-off. */


/* Basic cluster attributes initial values. */
#define BULB_INIT_BASIC_APP_VERSION       01                                    /**< Version of the application software (1 byte). */
#define BULB_INIT_BASIC_STACK_VERSION     10                                    /**< Version of the implementation of the ZigBee stack (1 byte). */
#define BULB_INIT_BASIC_HW_VERSION        11                                    /**< Version of the hardware of the device (1 byte). */
#define BULB_INIT_BASIC_MANUF_NAME        "Nordic"                              /**< Manufacturer name (32 bytes). */
#define BULB_INIT_BASIC_MODEL_ID          "Dimable_Light_v0.1"                  /**< Model number assigned by manufacturer (32-bytes long string). */
#define BULB_INIT_BASIC_DATE_CODE         "20180416"                            /**< First 8 bytes specify the date of manufacturer of the device in ISO 8601 format (YYYYMMDD). The rest (8 bytes) are manufacturer specific. */
#define BULB_INIT_BASIC_POWER_SOURCE      ZB_ZCL_BASIC_POWER_SOURCE_DC_SOURCE   /**< Type of power sources available for the device. For possible values see section 3.2.2.2.8 of ZCL specification. */
#define BULB_INIT_BASIC_LOCATION_DESC     "Office desk"                         /**< Describes the physical location of the device (16 bytes). May be modified during commisioning process. */
#define BULB_INIT_BASIC_PH_ENV            ZB_ZCL_BASIC_ENV_UNSPECIFIED          /**< Describes the type of physical environment. For possible values see section 3.2.2.2.10 of ZCL specification. */

#define IDENTIFY_MODE_ENTER_BUTTON        BSP_BOARD_BUTTON_0                    /**< Enter the Bulb into the Identify mode. */
#ifdef  BOARD_PCA10059                                                          /**< If it is Dongle */
#define ZIGBEE_NETWORK_STATE_LED          BSP_BOARD_LED_0                       /**< LED indicating that light switch successfully joind ZigBee network. */
#else
#define ZIGBEE_NETWORK_STATE_LED          BSP_BOARD_LED_3                       /**< LED indicating that light switch successfully joind ZigBee network. */
#endif


/* Declare endpoint for Dimmable Light device with scenes. */
#define ZB_HA_DECLARE_LIGHT_EP(ep_name, ep_id, cluster_list)                         \
  ZB_ZCL_DECLARE_HA_DIMMABLE_LIGHT_SIMPLE_DESC(ep_name, ep_id,                       \
    ZB_HA_DIMMABLE_LIGHT_IN_CLUSTER_NUM, ZB_HA_DIMMABLE_LIGHT_OUT_CLUSTER_NUM);      \
  ZBOSS_DEVICE_DECLARE_REPORTING_CTX(reporting_info## device_ctx_name,               \
                                     ZB_HA_DIMMABLE_LIGHT_REPORT_ATTR_COUNT);        \
  ZBOSS_DEVICE_DECLARE_LEVEL_CONTROL_CTX(cvc_alarm_info## device_ctx_name,           \
                                         ZB_HA_DIMMABLE_LIGHT_CVC_ATTR_COUNT);       \
  ZB_AF_DECLARE_ENDPOINT_DESC(ep_name, ep_id, ZB_AF_HA_PROFILE_ID,                   \
                              0,     \
                              NULL,                 \
                              ZB_ZCL_ARRAY_SIZE(cluster_list, zb_zcl_cluster_desc_t),\
                              cluster_list,                                          \
                              (zb_af_simple_desc_1_1_t*)&simple_desc_##ep_name,      \
                              ZB_HA_DIMMABLE_LIGHT_REPORT_ATTR_COUNT,                \
                              reporting_info## device_ctx_name,                      \
                              ZB_HA_DIMMABLE_LIGHT_CVC_ATTR_COUNT,                   \
                              cvc_alarm_info## device_ctx_name)

#if !defined ZB_ROUTER_ROLE
#error Define ZB_ROUTER_ROLE to compile light bulb (Router) source code.
#endif

/********************Custom MACRO Pin Mapping*******************************/
#define ZERO_CROSS_DETECTION       NRF_GPIO_PIN_MAP(0,6)      //ZCD pin 
#define DIMMER_TRIGGER             NRF_GPIO_PIN_MAP(0,8)      //Trigger pin
#define EXTSW1_CONTROL             BSP_BUTTON_1         //ExtSW1 pin

//#define EXTSW2_CONTROL             NRF_GPIO_PIN_MAP(0,26)     //EXtSW2 pin

#define KEY_UP                     NRF_GPIO_PIN_MAP(1,10)     //Up pin
#define KEY_DOWN                   NRF_GPIO_PIN_MAP(1,13)     //Down pin

//#define KEY_LEARN                  NRF_GPIO_PIN_MAP(0,24)     //Learn pin
//#define OPTIONAL1_KEY              NRF_GPIO_PIN_MAP(1,15)     //Optional1 pin
//#define OPTIONAL2_KEY              NRF_GPIO_PIN_MAP(0,2)      //Optional2 pin
 
#define HALFCYCLE_10MSTIME          10000       //10msec for half cycle time 
#define MAX_DUTYCYCLE               9000       //max duty cycle 9msec

#define MIN_ADC_VAL                 78         //minimum adc value with repsective capacitor minimum voltage 

void timer2_Configuration (void);       //timer 2 configured as duty cycle timer 
void timer2_DimmingControlling_tme(uint32_t ui32Timer2Dutycycle); 

void timer1_Configuration (void);       //timer 1 configured as fixed timer for negative cycle 
void timer1_fixedtimeOperation (uint32_t ui32fixedtime);


/* Basic cluster attributes. */
typedef struct
{
    zb_uint8_t zcl_version;
    zb_uint8_t app_version;
    zb_uint8_t stack_version;
    zb_uint8_t hw_version;
    zb_char_t  mf_name[32];
    zb_char_t  model_id[32];
    zb_char_t  date_code[16];
    zb_uint8_t power_source;
    zb_char_t  location_id[17];
    zb_uint8_t ph_env;
    zb_char_t  sw_ver[17];
} bulb_device_basic_attr_t;

/* Identify cluster attributes. */
typedef struct
{
    zb_uint16_t identify_time;
} bulb_device_identify_attr_t;

/* ON/Off cluster attributes. */
typedef struct
{
    zb_bool_t   on_off;
    zb_bool_t   global_scene_ctrl;
    zb_uint16_t on_time;
    zb_uint16_t off_wait_time;
} bulb_device_on_off_attr_t;

/* Level Control cluster attributes. */
typedef struct
{
    zb_uint8_t  current_level;
    zb_uint16_t remaining_time;
} bulb_device_level_control_attr_t;

/* Scenes cluster attributes. */
typedef struct
{
    zb_uint8_t  scene_count;
    zb_uint8_t  current_scene;
    zb_uint8_t  scene_valid;
    zb_uint8_t  name_support;
    zb_uint16_t current_group;
} bulb_device_scenes_attr_t;

/* Groups cluster attributes. */
typedef struct
{
    zb_uint8_t name_support;
} bulb_device_groups_attr_t;

/* Main application customizable context. Stores all settings and static values. */
typedef struct
{
    bulb_device_basic_attr_t         basic_attr;
    bulb_device_identify_attr_t      identify_attr;
    bulb_device_scenes_attr_t        scenes_attr;
    bulb_device_groups_attr_t        groups_attr;
    bulb_device_on_off_attr_t        on_off_attr;
    bulb_device_level_control_attr_t level_control_attr;
} bulb_device_ctx_t;

/* constant declaration -----------------------------------------------*/
const nrf_drv_timer_t TIMER_1 = NRF_DRV_TIMER_INSTANCE(2);  // Created instance as timer 1
const nrf_drv_timer_t TIMER_2 = NRF_DRV_TIMER_INSTANCE(4);  // Created instance as timer 2

/*************GLOBAL VATIABLES***************************************/
uint32_t time2_ticks;
uint32_t ui32DimmerONTime = 0;
uint32_t CurrentDutyCycle = 0;
uint32_t ui32fixedtime = 0;
uint32_t ui32Brightness = 0; 
uint32_t ui32PrevDutyCycle = 0;

bool boolIgnorelongpress = false;

//push button config variables
uint16_t ui8PushbuttonStatusCount = 0;
uint8_t ui8Pushbuttonstatus = 0;

bool boolpushbuttonStatus = false;
bool boolpushbuttonContinue = false;
bool boolBrightnesslevelcontrol = false;
bool boolNextZCDProcess = false;

//button_2 global variables
uint16_t ui16PushButton2Count = 0;
uint8_t ui8PushButton2status = 0;
bool boolPushButton2Status = false;
bool boolPushButton2Continue = false;
bool boolPushButton2BrightnessControl = false;

//button_3 global variables
uint16_t ui16PushButton3Count = 0;
uint8_t ui8PushButton3status = 0;
bool boolPushButton3Status = false;
bool boolPushButton3Continue = false;
bool boolPushButton3BrightnessControl = false;

//SAADC/ADC variables
uint16_t ui16CurrentADCValue = 255; 
uint32_t ui32DutyCycle100 = MAX_DUTYCYCLE;

////Flag to monitor ADC value comparision with w. r. t. 0.7V while initial sequence implmentation
//bool boolADCComparisonComplete = true;
////Monitors ADC Reading while initial sequence implmentation
//bool boolADCReadingComplete = false;
////Flag indicating initial sequence operation or normal operation
bool boolInitialSequenceMeasurement = false;

bool boolSetInit30 = false;
float Val = 0, Val2=0;
uint32_t Result =0;


static nrf_saadc_value_t adc_buf[1];

/*************************END****************************************/


static bulb_device_ctx_t m_dev_ctx;

ZB_ZCL_DECLARE_IDENTIFY_ATTRIB_LIST(identify_attr_list, &m_dev_ctx.identify_attr.identify_time);


ZB_ZCL_DECLARE_GROUPS_ATTRIB_LIST(groups_attr_list, &m_dev_ctx.groups_attr.name_support);

ZB_ZCL_DECLARE_SCENES_ATTRIB_LIST(scenes_attr_list,
                                  &m_dev_ctx.scenes_attr.scene_count,
                                  &m_dev_ctx.scenes_attr.current_scene,
                                  &m_dev_ctx.scenes_attr.current_group,
                                  &m_dev_ctx.scenes_attr.scene_valid,
                                  &m_dev_ctx.scenes_attr.name_support);

ZB_ZCL_DECLARE_BASIC_ATTRIB_LIST_EXT(basic_attr_list,
                                     &m_dev_ctx.basic_attr.zcl_version,
                                     &m_dev_ctx.basic_attr.app_version,
                                     &m_dev_ctx.basic_attr.stack_version,
                                     &m_dev_ctx.basic_attr.hw_version,
                                     m_dev_ctx.basic_attr.mf_name,
                                     m_dev_ctx.basic_attr.model_id,
                                     m_dev_ctx.basic_attr.date_code,
                                     &m_dev_ctx.basic_attr.power_source,
                                     m_dev_ctx.basic_attr.location_id,
                                     &m_dev_ctx.basic_attr.ph_env,
                                     m_dev_ctx.basic_attr.sw_ver);

/* On/Off cluster attributes additions data */
ZB_ZCL_DECLARE_ON_OFF_ATTRIB_LIST_EXT(on_off_attr_list,
                                      &m_dev_ctx.on_off_attr.on_off,
                                      &m_dev_ctx.on_off_attr.global_scene_ctrl,
                                      &m_dev_ctx.on_off_attr.on_time,
                                      &m_dev_ctx.on_off_attr.off_wait_time);

ZB_ZCL_DECLARE_LEVEL_CONTROL_ATTRIB_LIST(level_control_attr_list,
                                         &m_dev_ctx.level_control_attr.current_level,
                                         &m_dev_ctx.level_control_attr.remaining_time);

ZB_HA_DECLARE_DIMMABLE_LIGHT_CLUSTER_LIST(dimmable_light_clusters,
                                          basic_attr_list,
                                          identify_attr_list,
                                          groups_attr_list,
                                          scenes_attr_list,
                                          on_off_attr_list,
                                          level_control_attr_list);

ZB_HA_DECLARE_LIGHT_EP(dimmable_light_ep,
                       HA_DIMMABLE_LIGHT_ENDPOINT,
                       dimmable_light_clusters);

ZB_HA_DECLARE_DIMMABLE_LIGHT_CTX(dimmable_light_ctx,
                                 dimmable_light_ep);



/**@brief Function for initializing the nrf log module.
 */
static void log_init(void)
{
    ret_code_t err_code = NRF_LOG_INIT(NULL);
    APP_ERROR_CHECK(err_code);

    NRF_LOG_DEFAULT_BACKENDS_INIT();
}

/*********Brightness set command from Alexa or App*******************************************/
/**@brief Sets brightness of LED
 *
 * @param[in] brightness_level Brightness level, allowed values 0 ... 255, 0 - turn off, 255 - full brightness
 */
static void light_bulb_onboard_set_brightness(zb_uint8_t brightness_level)
{
    
    /* ZigBee level control cluster uses values from 0 up to 255. */
     //Convert brigthness level values as per 0 to 100 range 
     ui32DimmerONTime = ((brightness_level * 100)/ 255);
     //set brightness level to 100% Max 
    // CurrentDutyCycle = (((ui32DimmerONTime * 0.75) + 25) * 100); 

     CurrentDutyCycle = (ui32DimmerONTime * ui32DutyCycle100)/100;   
}


/**@brief Sets brightness of bulb luminous executive element
 *
 * @param[in] brightness_level Brightness level, allowed values 0 ... 255, 0 - turn off, 255 - full brightness
 */
static void light_bulb_set_brightness(zb_uint8_t brightness_level)
{
    light_bulb_onboard_set_brightness(brightness_level);
}

/**@brief Function for setting the light bulb brightness.
  *
  * @param[in]   new_level   Light bulb brightness value.
 */
static void level_control_set_value(zb_uint16_t new_level)
{
    NRF_LOG_INFO("Set level value: %i", new_level);

    ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT,                                       
                         ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL,            
                         ZB_ZCL_CLUSTER_SERVER_ROLE,                 
                         ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, 
                         (zb_uint8_t *)&new_level,                                       
                         ZB_FALSE);                                  

    /* According to the table 7.3 of Home Automation Profile Specification v 1.2 rev 29, chapter 7.1.3. */
    if (new_level == 0)
    {
        zb_uint8_t value = ZB_FALSE;
        ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT, 
                             ZB_ZCL_CLUSTER_ID_ON_OFF,    
                             ZB_ZCL_CLUSTER_SERVER_ROLE,  
                             ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
                             &value,                        
                             ZB_FALSE);                   
    }
    else
    {
        zb_uint8_t value = ZB_TRUE;
        ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT, 
                             ZB_ZCL_CLUSTER_ID_ON_OFF,    
                             ZB_ZCL_CLUSTER_SERVER_ROLE,  
                             ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
                             &value,                        
                             ZB_FALSE);
    }

    light_bulb_set_brightness(new_level);
}


/**@brief Function for turning ON/OFF the light bulb.
 *
 * @param[in]   on   Boolean light bulb state.
 */
static void on_off_set_value(zb_bool_t on)
{
    NRF_LOG_INFO("Set ON/OFF value: %i", on);

    ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT, 
                         ZB_ZCL_CLUSTER_ID_ON_OFF,    
                         ZB_ZCL_CLUSTER_SERVER_ROLE,  
                         ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
                         (zb_uint8_t *)&on,                        
                         ZB_FALSE);

    if (on)
    {
        level_control_set_value(m_dev_ctx.level_control_attr.current_level);  
        boolIgnorelongpress = false;    
    }
    else
    {
        light_bulb_set_brightness(0U);  
        CurrentDutyCycle = 0;
        boolIgnorelongpress = true; 
    }
}



/**@brief Function for initializing LEDs and a single PWM channel.
 */
static void leds_buttons_init(void)
{
    /* Initialize all LEDs*/
    /* Configure board. */
    bsp_board_init(BSP_INIT_LEDS);

    
}

/**@brief Function for initializing all clusters attributes.
 */
static void bulb_clusters_attr_init(void)
{
    /* Basic cluster attributes data */
    m_dev_ctx.basic_attr.zcl_version   = ZB_ZCL_VERSION;
    m_dev_ctx.basic_attr.app_version   = BULB_INIT_BASIC_APP_VERSION;
    m_dev_ctx.basic_attr.stack_version = BULB_INIT_BASIC_STACK_VERSION;
    m_dev_ctx.basic_attr.hw_version    = BULB_INIT_BASIC_HW_VERSION;

    /* Use ZB_ZCL_SET_STRING_VAL to set strings, because the first byte should
     * contain string length without trailing zero.
     *
     * For example "test" string wil be encoded as:
     *   [(0x4), 't', 'e', 's', 't']
     */
    ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.mf_name,
                          BULB_INIT_BASIC_MANUF_NAME,
                          ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MANUF_NAME));

    ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.model_id,
                          BULB_INIT_BASIC_MODEL_ID,
                          ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_MODEL_ID));

    ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.date_code,
                          BULB_INIT_BASIC_DATE_CODE,
                          ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_DATE_CODE));

    m_dev_ctx.basic_attr.power_source = BULB_INIT_BASIC_POWER_SOURCE;

    ZB_ZCL_SET_STRING_VAL(m_dev_ctx.basic_attr.location_id,
                          BULB_INIT_BASIC_LOCATION_DESC,
                          ZB_ZCL_STRING_CONST_SIZE(BULB_INIT_BASIC_LOCATION_DESC));


    m_dev_ctx.basic_attr.ph_env = BULB_INIT_BASIC_PH_ENV;

    /* Identify cluster attributes data */
    m_dev_ctx.identify_attr.identify_time = ZB_ZCL_IDENTIFY_IDENTIFY_TIME_DEFAULT_VALUE;

    /* On/Off cluster attributes data */
    m_dev_ctx.on_off_attr.on_off = (zb_bool_t)ZB_ZCL_ON_OFF_IS_ON;

    m_dev_ctx.level_control_attr.current_level  = ZB_ZCL_LEVEL_CONTROL_LEVEL_MAX_VALUE;
    m_dev_ctx.level_control_attr.remaining_time = ZB_ZCL_LEVEL_CONTROL_REMAINING_TIME_DEFAULT_VALUE;

    ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT, 
                         ZB_ZCL_CLUSTER_ID_ON_OFF,    
                         ZB_ZCL_CLUSTER_SERVER_ROLE,  
                         ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID,
                         (zb_uint8_t *)&m_dev_ctx.on_off_attr.on_off,                        
                         ZB_FALSE);                   

    ZB_ZCL_SET_ATTRIBUTE(HA_DIMMABLE_LIGHT_ENDPOINT,                                       
                         ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL,            
                         ZB_ZCL_CLUSTER_SERVER_ROLE,                 
                         ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID, 
                         (zb_uint8_t *)&m_dev_ctx.level_control_attr.current_level,                                       
                         ZB_FALSE);                                  
}

/**@brief Function which tries to sleep down the MCU 
 *
 * Function which sleeps the MCU on the non-sleepy End Devices to optimize the power saving.
 * The weak definition inside the OSIF layer provides some minimal working template
 */
zb_void_t zb_osif_go_idle(zb_void_t)
{
    //TODO: implement your own logic if needed
    zb_osif_wait_for_event();
}

/**@brief Callback function for handling ZCL commands.
 *
 * @param[in]   param   Reference to ZigBee stack buffer used to pass received data.
 */
static zb_void_t zcl_device_cb(zb_uint8_t param)
{
    zb_uint8_t                       cluster_id;
    zb_uint8_t                       attr_id;
    zb_buf_t                       * p_buffer = ZB_BUF_FROM_REF(param);
    zb_zcl_device_callback_param_t * p_device_cb_param =
                     ZB_GET_BUF_PARAM(p_buffer, zb_zcl_device_callback_param_t);

    NRF_LOG_INFO("zcl_device_cb id %hd", p_device_cb_param->device_cb_id);

    /* Set default response value. */
    p_device_cb_param->status = RET_OK;

    switch (p_device_cb_param->device_cb_id)
    {
        case ZB_ZCL_LEVEL_CONTROL_SET_VALUE_CB_ID:
            NRF_LOG_INFO("Level control setting to %d", p_device_cb_param->cb_param.level_control_set_value_param.new_value);
            level_control_set_value(p_device_cb_param->cb_param.level_control_set_value_param.new_value);
            break;

        case ZB_ZCL_SET_ATTR_VALUE_CB_ID:
            cluster_id = p_device_cb_param->cb_param.set_attr_value_param.cluster_id;
            attr_id    = p_device_cb_param->cb_param.set_attr_value_param.attr_id;

            if (cluster_id == ZB_ZCL_CLUSTER_ID_ON_OFF)
            {
                uint8_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data8;

                NRF_LOG_INFO("on/off attribute setting to %hd", value);
                if (attr_id == ZB_ZCL_ATTR_ON_OFF_ON_OFF_ID)
                {
                    on_off_set_value((zb_bool_t) value);
                }
            }
            else if (cluster_id == ZB_ZCL_CLUSTER_ID_LEVEL_CONTROL)
            {
                uint16_t value = p_device_cb_param->cb_param.set_attr_value_param.values.data16;

                NRF_LOG_INFO("level control attribute setting to %hd", value);
                if (attr_id == ZB_ZCL_ATTR_LEVEL_CONTROL_CURRENT_LEVEL_ID)
                {
                    level_control_set_value(value);
                }
            }
            else
            {
                /* Other clusters can be processed here */
                NRF_LOG_INFO("Unhandled cluster attribute id: %d", cluster_id);
            }
            break;

        default:
            p_device_cb_param->status = RET_ERROR;
            break;
    }

    NRF_LOG_INFO("zcl_device_cb status: %hd", p_device_cb_param->status);
}

/**@brief ZigBee stack event handler.
 *
 * @param[in]   param   Reference to ZigBee stack buffer used to pass arguments (signal).
 */
void zboss_signal_handler(zb_uint8_t param)
{
    zb_zdo_app_signal_hdr_t  * p_sg_p = NULL;
    zb_zdo_app_signal_type_t   sig    = zb_get_app_signal(param, &p_sg_p);
    zb_ret_t                   status = ZB_GET_APP_SIGNAL_STATUS(param);
    zb_bool_t                  comm_status;

    switch (sig)
    {
        case ZB_BDB_SIGNAL_DEVICE_FIRST_START:
        case ZB_BDB_SIGNAL_DEVICE_REBOOT:
            if (status == RET_OK)
            {
                NRF_LOG_INFO("Joined network successfully");
                bsp_board_led_on(ZIGBEE_NETWORK_STATE_LED);
            }
            else
            {
                NRF_LOG_ERROR("Failed to join network. Status: %d", status);
                bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED);
                comm_status = bdb_start_top_level_commissioning(ZB_BDB_NETWORK_STEERING);
                ZB_COMM_STATUS_CHECK(comm_status);
            }
            break;

        case ZB_ZDO_SIGNAL_PRODUCTION_CONFIG_READY:
            if (status != RET_OK)
            {
                NRF_LOG_WARNING("Production config is not present or invalid");
            }
            break;

        case ZB_ZDO_SIGNAL_LEAVE:
            if (status == RET_OK)
            {
                bsp_board_led_off(ZIGBEE_NETWORK_STATE_LED);

                zb_zdo_signal_leave_params_t * p_leave_params = ZB_ZDO_SIGNAL_GET_PARAMS(p_sg_p, zb_zdo_signal_leave_params_t);
                NRF_LOG_INFO("Network left. Leave type: %d", p_leave_params->leave_type);
            }
            else
            {
                NRF_LOG_ERROR("Unable to leave network. Status: %d", status);
            }
            break;

        default:
            /* Unhandled signal. For more information see: zb_zdo_app_signal_type_e and zb_ret_e */
            NRF_LOG_INFO("Unhandled signal %d. Status: %d", sig, status);
            break;
    }

    if (param)
    {
        ZB_FREE_BUF_BY_REF(param);
    }
}

/* This Initial sequence to carried out to measure the intensity level for light controlling 
*  with respect to voltage level at input capacitor.
*
*/



static void InitialSequence(void)
{
  ret_code_t err_code;
  boolInitialSequenceMeasurement = true;
  
  ui32Brightness = 0;
  //read ADC value of capacitor
  err_code = nrf_drv_saadc_sample();
  APP_ERROR_CHECK(err_code);

  while((ui16CurrentADCValue >= MIN_ADC_VAL) && (ui32Brightness <= ui32DutyCycle100))
  {
      ui32PrevDutyCycle = ui32Brightness;
      ui32Brightness += 100;

      nrf_drv_gpiote_in_event_enable(ZERO_CROSS_DETECTION,true); //enable ZCD

      err_code = nrf_drv_saadc_sample();//trigger ADC
      APP_ERROR_CHECK(err_code);

      nrf_delay_ms(50); //adding delay able to read adc values 

  }
  ui32DutyCycle100 = ui32PrevDutyCycle;

  on_off_set_value(0U);
  ui32DimmerONTime = 0;
  boolSetInit30 = true;
  boolInitialSequenceMeasurement = false;  
}
/***************************SAADC Configuration Start*********************************************/

/**@brief Function for handling the ADC interrupt.
 *
 * @details  This function will fetch the conversion result from the ADC, convert the value into
 *           percentage and send it to peer.
 */
void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
    if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
    {
        
        uint32_t          err_code;

        ui16CurrentADCValue = p_event->data.done.p_buffer[0];  

        err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
        APP_ERROR_CHECK(err_code);
      
    }
}

/**@brief Function for configuring ADC to do capacitor voltage conversion.
 */
static void adc_configure(void)
{
    ret_code_t err_code;
    nrf_drv_saadc_config_t saadc_config;
    saadc_config.resolution = NRF_SAADC_RESOLUTION_8BIT;   //8 bit resolution
    saadc_config.interrupt_priority = APP_IRQ_PRIORITY_LOW;
    
    err_code = nrf_drv_saadc_init(&saadc_config, saadc_event_handler);
    APP_ERROR_CHECK(err_code);
    
   //singale shot and channel config 
   //If input range is 0 to 2.26V then set reference as VDD/4 and gain as 1/3
   nrf_saadc_channel_config_t channel_config;
   channel_config.reference = NRF_SAADC_REFERENCE_VDD4;
   channel_config.gain = NRF_SAADC_GAIN1_4;
   channel_config.acq_time = NRF_SAADC_ACQTIME_10US;
   channel_config.mode = NRF_SAADC_MODE_SINGLE_ENDED;
   channel_config.pin_n = NRF_SAADC_INPUT_DISABLED; 
   channel_config.pin_p = NRF_SAADC_INPUT_AIN2;
   channel_config.resistor_n = NRF_SAADC_RESISTOR_DISABLED;
   channel_config.resistor_p = NRF_SAADC_RESISTOR_DISABLED;

    err_code = nrf_drv_saadc_channel_init(2, &channel_config);
    APP_ERROR_CHECK(err_code);

    err_code = nrf_drv_saadc_buffer_convert(&adc_buf[0], 1);
    APP_ERROR_CHECK(err_code);
}

/***************************SAADC Configuration End*********************************************/

/***************************ZCD pin handler functions Start*********************************************/
void zcd_in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action) //ZCD Interrupt Handler Routine
{
     if(CurrentDutyCycle == 0)  //if the duty cycle is zero then enable ZCD do not disable it 
     {
        nrf_drv_gpiote_in_event_enable(ZERO_CROSS_DETECTION, true);
     }
     else
     {
       //disable ZCD event 
       nrf_drv_gpiote_in_event_disable(ZERO_CROSS_DETECTION);
     }

    if(!boolInitialSequenceMeasurement)
    {
       //Positive cycle operation
       //Computation of Ramp up and Ramp down during brightness change
        if(CurrentDutyCycle != ui32Brightness)
        {
          if(ui32Brightness < CurrentDutyCycle)         //ui32Brightness is the current brightness value that is compared with user set value
          {
              ui32Brightness += 50;	 	//increment brightness
              if(ui32Brightness >= ui32DutyCycle100)        //the maximum duty cycle is 10msec
              {
                ui32Brightness = ui32DutyCycle100;	
              }
          }
          if(ui32Brightness > CurrentDutyCycle)
          {
              ui32Brightness -= 50;	 	 //decrement brightness
              if(ui32Brightness <= 0)
              {
                 ui32Brightness = 0;
              }

          }
        } 
    }
             
       //start timer1 for 10msec timer to estimate negative cycle start
       timer1_fixedtimeOperation(HALFCYCLE_10MSTIME);      //timer 1 start for 10msec

       if(ui32Brightness != 0) //User has turned off the light
       {         
          if(ui32Brightness >= MAX_DUTYCYCLE) //duty cycle is more than 9ms
           {
             timer2_DimmingControlling_tme(MAX_DUTYCYCLE);  //timer 2 started for brightness control 
             nrf_gpio_pin_write(DIMMER_TRIGGER,1);     //when duty cycle is greater than 0 set trigger pin HIGH 
           }
           else
           {
             timer2_DimmingControlling_tme(ui32Brightness);  //timer 2 started for brightness control
             nrf_gpio_pin_write(DIMMER_TRIGGER,1);     //when duty cycle is greater than 0 set trigger pin HIGH
           }
       }
       else
       {
          nrf_gpio_pin_write(DIMMER_TRIGGER,0);    //when duty cycle is 0 set trigger pin LOW 
          
           if(boolSetInit30)
           {
              Val = (ui32DutyCycle100*100)/MAX_DUTYCYCLE;
              Val2 = ((Val*255)/100);
              Result = (uint32_t)((Val2*30)/100);
              boolSetInit30 = false;
              m_dev_ctx.level_control_attr.current_level = Result;
              level_control_set_value(m_dev_ctx.level_control_attr.current_level);
           }
       }
         
}
/***************************ZCD pin handler functions End*********************************************/

/***************************Button1 pin handler functions Start*********************************************/
void button_in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    //controlling logic using button press interrupt
     boolpushbuttonStatus = true; // if the push button press detect then set flag true
     boolBrightnesslevelcontrol = !boolBrightnesslevelcontrol;   //toggle brightness control flag to increment/decrement level accordingly.
     ui8PushbuttonStatusCount = 0;
}
/***************************Button1 pin handler functions End*********************************************/

/***************************Button2 pin handler functions Start*********************************************/
void button2_in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    //button_2 pressed turn ON the LED and Increment the brightness
      boolPushButton2Status = true; //if the push button_2 press detect then set flag
      boolPushButton2BrightnessControl = true;
}
/***************************Button2 pin handler functions End*********************************************/

/***************************Button3 pin handler functions Start*********************************************/
void button3_in_pin_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
{
    //button_3 pressed turn OFF the LED and Decrement the brightness
      boolPushButton3Status = true; //if the push button_2 press detect then set flag
      boolPushButton3BrightnessControl = true;
}     
/***************************Button3 pin handler functions End*********************************************/

/********** timer 1 Configuration Start *************************************************/
/**
* @brief Handler for timer events.
* 
* timer1_event_handler function to turn OFF the bulb and disable the timer 
*   
*/
void timer1_event_handler(nrf_timer_event_t event_type, void* p_context)
{   
      nrf_drv_timer_disable(&TIMER_1);        //disable timer 1
      
      //Negative cycle operation       
       if(ui32Brightness != 0) //User has turned off the light
       {
           if(ui32Brightness >= MAX_DUTYCYCLE) //duty cycle is more than 9ms
           {
             timer2_DimmingControlling_tme(MAX_DUTYCYCLE);  //timer 2 started for brightness control 
             nrf_gpio_pin_write(DIMMER_TRIGGER,1);     //when duty cycle is greater than 0 set trigger pin HIGH 
           }
           else
           {
             timer2_DimmingControlling_tme(ui32Brightness);  //timer 2 started for brightness control
             nrf_gpio_pin_write(DIMMER_TRIGGER,1);     //when duty cycle is greater than 0 set trigger pin HIGH
           }
       }
       else
       {
          nrf_gpio_pin_write(DIMMER_TRIGGER,0);    //when duty cycle is 0 set trigger pin LOW
       }
       
       boolNextZCDProcess = true; //set this flag for next zcd detection 

        //pushutton status check, below statements are executed when button_1 pressed
        if(boolpushbuttonStatus)   //check push button ststus flag is set or not 
        {
           ui8Pushbuttonstatus = nrf_gpio_pin_read(EXTSW1_CONTROL);  // if the button flag is set then read the push button pin status 
           if(ui8Pushbuttonstatus == 1) //if the push button pin is high then enter to check button press count 
           {
              ui8PushbuttonStatusCount+=2;    // increment the button press count 
              if(ui8PushbuttonStatusCount > 100)  // if the button the press count is 100(1sec) then it is long press action 
              {
                  /*function to brightness control
                  * on long press, increment and decrement the light intensity with the level of 10% 
                  */
                  if(boolBrightnesslevelcontrol)   // if the brightness level flag flase then start incrementing till maximun brightness 100%
                  {
                      if(m_dev_ctx.level_control_attr.current_level < 230)  
                      {
                          m_dev_ctx.level_control_attr.current_level = m_dev_ctx.level_control_attr.current_level + 13;                                                 
                      }
                      else 
                      {
                          m_dev_ctx.level_control_attr.current_level = 230;
                      }
                      level_control_set_value(m_dev_ctx.level_control_attr.current_level);
                  }
                  else
                  {
                      if(m_dev_ctx.level_control_attr.current_level >= 13)  
                      {
                          m_dev_ctx.level_control_attr.current_level = m_dev_ctx.level_control_attr.current_level - 13;                                                 
                      }
                      else 
                      {
                          m_dev_ctx.level_control_attr.current_level = 3;
                      }
                      level_control_set_value(m_dev_ctx.level_control_attr.current_level); 
                  }
                  ui8PushbuttonStatusCount = 0;
                  boolpushbuttonContinue = true;   
              }
           }
           else if(ui8Pushbuttonstatus == 0)  // if the push button oinb status is not set the enter loop to toggle the light status 
           {
              boolpushbuttonStatus = false;
              if((ui8PushbuttonStatusCount >=15) && (ui8PushbuttonStatusCount <= 100) && (boolpushbuttonContinue == false))  // if the button press is single (between 400msec to 1sec) then toggle the light 
              {
                  boolBrightnesslevelcontrol = !boolBrightnesslevelcontrol;
                  //function to toggle the LED current state
                  if(CurrentDutyCycle == 0)
                  {         
                      level_control_set_value(m_dev_ctx.level_control_attr.current_level);
                      boolIgnorelongpress = false;
                  }
                  else
                  {
                     //Off the LED
                     on_off_set_value(0U);
                     CurrentDutyCycle = 0; 
                     boolIgnorelongpress = true;                     
                  }
              }
              boolpushbuttonContinue = false; //set long press button flag false
              ui8PushbuttonStatusCount = 0;   //button press count zero 
           }
    
        }
        
        /***************Below statements are executed when button_2 pressed*****************************************/
        if(boolPushButton2Status)
        {
            ui8PushButton2status = nrf_gpio_pin_read(KEY_UP);
            if(ui8PushButton2status == 0)
            {   
               ui16PushButton2Count +=2; 
               if(!boolIgnorelongpress)  //ignore long press from up/down key when OFF 
               {
                  if(ui16PushButton2Count > 100)  //Increment brightness when button_2 long press
                  {
                      if(boolPushButton2BrightnessControl)
                      {
                        if(m_dev_ctx.level_control_attr.current_level < 230)  
                        {
                            m_dev_ctx.level_control_attr.current_level = m_dev_ctx.level_control_attr.current_level + 13;                                                 
                        }
                        else 
                        {
                            m_dev_ctx.level_control_attr.current_level = 230;
                        }
                        level_control_set_value(m_dev_ctx.level_control_attr.current_level);
    
                      }
                    ui16PushButton2Count = 0;
                    boolPushButton2Continue = true;
                  } 
               }
            }
            else if(ui8PushButton2status == 1)
            {
                boolPushButton2Status = false;
                boolPushButton2BrightnessControl = false;
                if((ui16PushButton2Count >=15) && (ui16PushButton2Count <= 100) && (boolPushButton2Continue == false))
                {
                     level_control_set_value(m_dev_ctx.level_control_attr.current_level); //Turn On when button_2 short press
                     boolIgnorelongpress = false;
                }
                ui16PushButton2Count = 0;
                boolPushButton2Continue = false;
            }
        }
        /***************Above statements are executed when button_2 pressed*****************************************/

        /***************Below statements are executed when button_3 pressed*****************************************/
        if(boolPushButton3Status)
        {
            ui8PushButton3status = nrf_gpio_pin_read(KEY_DOWN);
            if(ui8PushButton3status == 0)
            {
                ui16PushButton3Count +=2;
                if(!boolIgnorelongpress)    //ignore long press from up/down key when OFF 
                {                    
                    if(ui16PushButton3Count > 100)  //Decrement brightness when button_3 long press
                    {
                        if(boolPushButton3BrightnessControl)
                        {
                          if(m_dev_ctx.level_control_attr.current_level >= 13)  
                          {
                              m_dev_ctx.level_control_attr.current_level = m_dev_ctx.level_control_attr.current_level - 13;                                                 
                          }
                          else 
                          {
                              m_dev_ctx.level_control_attr.current_level = 3;
                          }
                          level_control_set_value(m_dev_ctx.level_control_attr.current_level); 

                        }
                      ui16PushButton3Count = 0;
                      boolPushButton3Continue = true;
                    }
                }
            }
            else if(ui8PushButton3status == 1)
            {
                boolPushButton3Status = false;
                boolPushButton3BrightnessControl = false;
                if((ui16PushButton3Count >=15) && (ui16PushButton3Count <= 100) && (boolPushButton3Continue == false))
                {
                    //Turn Off when button_3 short press
                    CurrentDutyCycle = 0; 
                    on_off_set_value(0U);
                    boolIgnorelongpress = true;
                }
                ui16PushButton3Count = 0;
                boolPushButton3Continue = false;
            }
        }
        /***************Above statements are executed when button_3 pressed*****************************************/
       
}

/**
* @brief function for timer1 configurarion
* 
* configure timer 1 with the frequency parameter set 1MHz
* Intialise the timer event handler and enable 10msec timer for Negative cycle  
*   
*/
void timer1_Configuration (void)
{  
    uint32_t err_code = NRF_SUCCESS;
    //Configure TIMER_1 as 10msec timer
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.frequency = 4; //set frequency 1MHz  
    err_code = nrf_drv_timer_init(&TIMER_1, &timer_cfg, timer1_event_handler);
    if (err_code != NRF_SUCCESS)
    {
        // handle error condition
    }
}

//fixed timer 1
void timer1_fixedtimeOperation (uint32_t ui32fixedtime)
{
  uint32_t time1_ticks;

  time1_ticks = nrf_drv_timer_us_to_ticks(&TIMER_1, ui32fixedtime); 
  nrf_drv_timer_extended_compare(
        &TIMER_1, NRF_TIMER_CC_CHANNEL0, time1_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);    //timer 1 configured as continous timer  
  nrf_drv_timer_clear(&TIMER_1);
  nrf_drv_timer_enable(&TIMER_1);
}
/**********Negative Cycle timer Configuration End *************************************************/


/**********************Duty Cycle timer Configuration Start ********************************************/
/**
* @brief Handler for timer events.
* 
* timer2_event_handler function to turn OFF the bulb and disable the timer 
*   
*/
void timer2_event_handler(nrf_timer_event_t event_type, void* p_context) //Timer 2 interrupt handler
{
     nrf_drv_timer_disable(&TIMER_2);    //disable timer 2
     nrf_gpio_pin_write(DIMMER_TRIGGER,0);  //set trigger pin LOW 
     if(boolNextZCDProcess)     //if negative cycle complete enable the ZCD event again for next interrupt
     {
      // enable ZCD event 
       nrf_drv_gpiote_in_event_enable(ZERO_CROSS_DETECTION,true);
       boolNextZCDProcess = false;
     }
     
}

/**
* @brief function for timer2 configurarion
* 
* configure timer 2 with the frequency parameter set 1MHz
* Intialise the timer event handler and enable 10msec to control the dimming effect 
*   
*/
void timer2_Configuration (void)
{  
    uint32_t err_code = NRF_SUCCESS;
    //Configure TIMER_2 as 0 to 10msec duty cycle timer
    nrf_drv_timer_config_t timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
    timer_cfg.frequency = 4; //set frequency 1MHz  
    err_code = nrf_drv_timer_init(&TIMER_2, &timer_cfg, timer2_event_handler);
    if (err_code != NRF_SUCCESS)
    {
        // handle error condition
    }
}
//timer2 dimming control time function 
void timer2_DimmingControlling_tme(uint32_t ui32Timer2Dutycycle)
{
    time2_ticks = nrf_drv_timer_us_to_ticks(&TIMER_2, ui32Timer2Dutycycle); //ui32Timer2Dutycycle is passed as duty cycle value 0 to 100%

     nrf_drv_timer_extended_compare(
         &TIMER_2, NRF_TIMER_CC_CHANNEL0, time2_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);       //timer 2 configured as continous timer

    nrf_drv_timer_clear(&TIMER_2); 
    nrf_drv_timer_enable(&TIMER_2);
}
/**********************Duty Cycle timer Configuration End *************************************************/

/*************GPIO Configuration*******************************/
/* ************************************************************
*function to configure ZCD, Tigger and Button pin 
*  Configure ZCD as Digital input pin (P0_6)
*  Configure Trigger as Digital output pin (P0_8)
*  Configure Button as Digital input pin (P1_9)
*
*  Function : GPIO_pin_configuration(void);
***************************************************************/
static void GPIO_pin_configuration (void)
{
   uint32_t err_code;

     //Set ZCD pin as input pin and Configure ZCD handler
    if(!nrf_drv_gpiote_is_init())
    {
      err_code = nrf_drv_gpiote_init();
    }

    /**********Trigger pin Configuration Start *************************************************/
    //Set Trigger pin as output pin
     nrf_gpio_cfg_output(DIMMER_TRIGGER);
     /**********Trigger pin Configuration End *************************************************/
     
    /**********ZCD pin Configuration Start *************************************************/
    //Set ZCD pin as input pin and Configure ZCD handler
    nrf_drv_gpiote_in_config_t zcd_in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);   //raising edge detection
    zcd_in_config.pull = NRF_GPIO_PIN_PULLUP;   //configure ZCD pin as pull_up
    err_code = nrf_drv_gpiote_in_init(ZERO_CROSS_DETECTION, &zcd_in_config, zcd_in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(ZERO_CROSS_DETECTION, true);
    /**********ZCD pin Configuration End *************************************************/

   /**********Button1 pin Configuration Start *************************************************/
   //Set Button1 pin as input pin and Configure Button handler 
    nrf_drv_gpiote_in_config_t button_in_config = GPIOTE_CONFIG_IN_SENSE_LOTOHI(true);
    button_in_config.pull = NRF_GPIO_PIN_PULLDOWN; //configure button pin as pull_down

    err_code = nrf_drv_gpiote_in_init(EXTSW1_CONTROL, &button_in_config, button_in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(EXTSW1_CONTROL, true);
    /**********Button1 pin Configuration End *************************************************/

    /**********Button2 pin Configuration Start *************************************************/
   //Set Button2 pin as input pin and Configure Button handler 
    nrf_drv_gpiote_in_config_t button2_in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    button2_in_config.pull = NRF_GPIO_PIN_PULLUP; //configure button pin as pull_up

    err_code = nrf_drv_gpiote_in_init(KEY_UP, &button2_in_config, button2_in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(KEY_UP, true);
    /**********Button2 pin Configuration End *************************************************/

       /**********Button3 pin Configuration Start *************************************************/
   //Set Button3 pin as input pin and Configure Button handler 
    nrf_drv_gpiote_in_config_t button3_in_config = GPIOTE_CONFIG_IN_SENSE_HITOLO(true);
    button3_in_config.pull = NRF_GPIO_PIN_PULLUP; //configure button pin as pull_up

    err_code = nrf_drv_gpiote_in_init(KEY_DOWN, &button3_in_config, button3_in_pin_handler);
    APP_ERROR_CHECK(err_code);

    nrf_drv_gpiote_in_event_enable(KEY_DOWN, true);
    /**********Button3 pin Configuration End *************************************************/
}

/**@brief Function for application main entry.
 */
int main(void)
{
    zb_ret_t       zb_err_code;
    zb_ieee_addr_t ieee_addr;

    /* Initialize timer, logging system and GPIOs. */
    log_init();
    leds_buttons_init();

    GPIO_pin_configuration();   //GPIO initialization and configuration
    timer2_Configuration();     //Timer 2 as duty cycle time configured 
    timer1_Configuration();     //Timer 1 as negative cycle timer 
    adc_configure();            //ADC intialization and configuration as channal 2, 8 bit resolution

    /* Set ZigBee stack logging level and traffic dump subsystem. */
    ZB_SET_TRACE_LEVEL(ZIGBEE_TRACE_LEVEL);
    ZB_SET_TRACE_MASK(ZIGBEE_TRACE_MASK);
    ZB_SET_TRAF_DUMP_OFF();

    /* Initialize ZigBee stack. */
    ZB_INIT("led_bulb");

    /* Set device address to the value read from FICR registers. */
    zb_osif_get_ieee_eui64(ieee_addr);
    zb_set_long_address(ieee_addr);

    /* Set static long IEEE address. */
    zb_set_network_router_role(IEEE_CHANNEL_MASK);
    zb_set_max_children(MAX_CHILDREN);
    zigbee_erase_persistent_storage(ERASE_PERSISTENT_CONFIG);
    zb_set_keepalive_timeout(ZB_MILLISECONDS_TO_BEACON_INTERVAL(3000));

    /* Initialize application context structure. */
    UNUSED_RETURN_VALUE(ZB_MEMSET(&m_dev_ctx, 0, sizeof(m_dev_ctx)));

    /* Register callback for handling ZCL commands. */
    ZB_ZCL_REGISTER_DEVICE_CB(zcl_device_cb);

    /* Register dimmer switch device context (endpoints). */
    ZB_AF_REGISTER_DEVICE_CTX(&dimmable_light_ctx);

    bulb_clusters_attr_init();   
   // m_dev_ctx.level_control_attr.current_level = 77;
    level_control_set_value(m_dev_ctx.level_control_attr.current_level);

    InitialSequence(); 

    /** Start Zigbee Stack. */
    zb_err_code = zboss_start();
    ZB_ERROR_CHECK(zb_err_code);
      

    while(1)
    {

        zboss_main_loop_iteration();
        UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());

    }
}


/**
 * @}
 */

Can anyone help me where I am doing wrong.

Thanks in advance. 

Regards,

Rohit R

Parents
  • Hi,

    I'm not sure I understand exactly what is not working with your power-on sequence, do you get an error code or similar?

    The SAADC works asynchronously, meaning that the call to the sample-function will only trigger a sample, and you will get a callback in the event handler when the sampling is done.

    the delay-method should work, and with a single channel and 10 us acquisition-time, you should be able to reduce it to around 15 us. However, to be sure to get long enough, but shortest possible wait, you should set a flag and do a blocking wait for this flag to be set:

    uint8_t saadc_done_flag = false;
    
    static void InitialSequence(void)
    {
      ...
      
      //read ADC value of capacitor
      err_code = nrf_drv_saadc_sample();
      APP_ERROR_CHECK(err_code);
      
      while(saadc_done_flag == false);
      saadc_done_flag = false;
      
    
      while((ui16CurrentADCValue >= MIN_ADC_VAL) && (ui32Brightness <= ui32DutyCycle100))
      {
          ...
    
          err_code = nrf_drv_saadc_sample();//trigger ADC
          APP_ERROR_CHECK(err_code);
    	  
    	  while(saadc_done_flag == false);
    	  saadc_done_flag = false;	  
      }
     
    }
    
    void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            uint32_t          err_code;
    
            ui16CurrentADCValue = p_event->data.done.p_buffer[0];
    		saadc_done_flag = true;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
            APP_ERROR_CHECK(err_code);
          
        }
    }

    Best regards,
    Jørgen

Reply
  • Hi,

    I'm not sure I understand exactly what is not working with your power-on sequence, do you get an error code or similar?

    The SAADC works asynchronously, meaning that the call to the sample-function will only trigger a sample, and you will get a callback in the event handler when the sampling is done.

    the delay-method should work, and with a single channel and 10 us acquisition-time, you should be able to reduce it to around 15 us. However, to be sure to get long enough, but shortest possible wait, you should set a flag and do a blocking wait for this flag to be set:

    uint8_t saadc_done_flag = false;
    
    static void InitialSequence(void)
    {
      ...
      
      //read ADC value of capacitor
      err_code = nrf_drv_saadc_sample();
      APP_ERROR_CHECK(err_code);
      
      while(saadc_done_flag == false);
      saadc_done_flag = false;
      
    
      while((ui16CurrentADCValue >= MIN_ADC_VAL) && (ui32Brightness <= ui32DutyCycle100))
      {
          ...
    
          err_code = nrf_drv_saadc_sample();//trigger ADC
          APP_ERROR_CHECK(err_code);
    	  
    	  while(saadc_done_flag == false);
    	  saadc_done_flag = false;	  
      }
     
    }
    
    void saadc_event_handler(nrf_drv_saadc_evt_t const * p_event)
    {
        if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
        {
            uint32_t          err_code;
    
            ui16CurrentADCValue = p_event->data.done.p_buffer[0];
    		saadc_done_flag = true;
    
            err_code = nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 1);
            APP_ERROR_CHECK(err_code);
          
        }
    }

    Best regards,
    Jørgen

Children
  • Hi Jørgen,

    Thank you for the feedback.

    yes, I tried setting a flag and block but a different way and it did not work.

    I refer to your code and check the result.

    I'm not sure I understand exactly what is not working with your power-on sequence, do you get an error code or similar?

    - No, I do not get any error but unable to read ADC values. with my 2nd code attached in the previous post. But it works without hard RESET.

    I tried your wait for a suggestion as shared in the snippet but after the flag gets to set it did not enter into the below while condition statement because of that brightness not incrementing as well as no further execution.

      while((ui16CurrentADCValue >= MIN_ADC_VAL) && (ui32Brightness <= ui32DutyCycle100))
      {
          ui32PrevDutyCycle = ui32Brightness;
          ui32Brightness += 10;
    
          nrf_drv_gpiote_in_event_enable(ZERO_CROSS_DETECTION,true); //enable ZCD
    
          err_code = nrf_drv_saadc_sample();//trigger ADC
          APP_ERROR_CHECK(err_code);
    
          while(ui8Saadc_done_flag == false);
          ui8Saadc_done_flag = false;
    
    //      nrf_delay_ms(50); //adding delay able to read adc values 
    
      }
      
      

    Let me know what is the cause.

    I can not use delay because while incrementing brightness it is flickering so end-user point it is not acceptable.

    Thanks and Regards

    Rohit R

  • Rohit Rajapure said:
    I tried your wait for a suggestion as shared in the snippet but after the flag gets to set it did not enter into the below while condition statement because of that brightness not incrementing as well as no further execution.

    Did you set the flag to false initially, and set the flag to true in saadc_event_handler when you receive the NRF_DRV_SAADC_EVT_DONE event?

    Rohit Rajapure said:
    I can not use delay because while incrementing brightness it is flickering so end-user point it is not acceptable.

    My suggestion was to reduce the delay to around 15 microseconds (us). I do not see how that could give visible flickering.

  • Hi Jørgen,

    Thanks for the feedback,

    One update from my end. I have resolved the RESET issue in the power-on sequence. I had made some changes in my first approach 1258.main_20210218.c. Files are attached in my query post. Now I am able to make power-on sequence and SAADC working.

    Yes, SAADC reading needs some configuration fine-tuning. We are testing the same.

    Thank you for your constant support Slight smile. I will get back to you in case of any queries.

    Thanks and Regards

    Rohit R

Related