TX power has strange relationship with overall power of chip

I designed a PCB with only the nRF52833 chip and antenna. I want to learn about the relationship between different TX power levels and the overall power consumption of the chip.

I am using a power profiler with a 1.8V supply and reading the average current via software.

During the tests, the TX RX position remains fixed. I obtained the following results:

Why is the received signal strength higher when TX power is 0 dBm compared to when TX power is 4 dBm? Why does the overall power consumption increase when the TX power is reduced to negative values? I look forward to your response.:)

Parents
  • Hi

    Please upload an image of how you've powered the board on your end. As the current consumption here looks too low (nano amps) to be set up correctly of a running nRF52833. The maximum current also is just 0.12µA which is not high enough to be the radio running. So if the PPK is indeed supplying the nRF52833 here it shouldn't be able to transmit anything.

    Also, after stopping the Power Profiler app, you should get the option to export the PPK trace as a .ppk file that you can upload here so we can review it.

    Best regards,

    Simon

  • I have re-conducted the experiment and uploaded the PPK files (powered at 1.8V) for the following TX settings: 8, 4, 3, 0, -4, and -8. This time, it seems the chip did not work when TX was set to -4, and when TX was set to -8, the chip's power consumption was significantly higher than when TX was set to 8. Additionally, the device could not connect to the central device when the TX value was negative. I have also uploaded my main function code in the files. Thank you very much for your assistance.

    #include <stdint.h>
    #include <string.h>
    #include <stdio.h>
    #include <stdlib.h>
    #include "nordic_common.h"
    #include "nrf.h"
    #include <nrfx.h>
    
    #include "nrf_drv_saadc.h"
    #include "nrf_drv_ppi.h"
    #include "ble_hci.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    //#include <nrfx_saadc.h>
    #include "nrf_drv_timer.h"
    #include "nrf_drv_clock.h"
    #include "app_timer.h"
    #include "app_util_platform.h"
    #include "bsp_btn_ble.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_delay.h"
    #include "ble_profile.h"
    #include "alcohol_sensor_config.h"
    #include "alcohol_ext_sensor_controller.h"
    #include "encryption.h"
    #include "nrf_drv_wdt.h"
    
    
    
    
    #include <math.h>
    
    
    
    #define APP_BLE_CONN_CFG_TAG            1                                           /**< A tag identifying the SoftDevice BLE configuration. */
    
    #define DEVICE_NAME                     "DARE"                               /**< Name of device. Will be included in the advertising data. */
    #define MANUFACTURER_NAME               "NTU"                								 /**< Manufacturer. Will be passed to Device Information Service. */
    
    #define APP_BLE_OBSERVER_PRIO           3                                           /**< Application's BLE observer priority. You shouldn't need to modify this value. */
    
    #define APP_ADV_INTERVAL                960  //960                                  /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
    
    #if (CONNECTION_MODE == 1)
       #define APP_ADV_DURATION             18000                                       /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    #else 
       #define APP_ADV_DURATION             1000                                        /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
    #endif
    
    #define MIN_CONN_INTERVAL               MSEC_TO_UNITS(7.5, UNIT_1_25_MS)            /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
    #define MAX_CONN_INTERVAL                MSEC_TO_UNITS(100, UNIT_1_25_MS)            /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
    #define SLAVE_LATENCY                   0                                           /**< Slave latency. */
    #define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(400, UNIT_10_MS)    //4000    /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
    #define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(1000)                       /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)                      /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT    3                                           /**< Number of attempts before giving up the connection parameter negotiation. */
    
    #define DEAD_BEEF                       0xDEADBEEF                                  /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
    
    
    #define SAADC_CHANNEL_COUNT   1
    
    BLE_ALCO_DEF(m_alco);                                                               /**< BLE ALCO service instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                                           /**< GATT module instance. */
    NRF_BLE_QWR_DEF(m_qwr);                                                             /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */
    
    APP_TIMER_DEF(m_read_sensor_timer_id);
    //APP_TIMER_DEF(m_generate_random_data_timer_id);
    //APP_TIMER_DEF(start_advertising_timer_id);
    //APP_TIMER_DEF(alcohol_sensor_init_timer_id);
    //APP_TIMER_DEF(sgp40_heater_off_timer_id);
    APP_TIMER_DEF(radiation_timer_id);   
    APP_TIMER_DEF(rtc_timer_id);     
    //APP_TIMER_DEF(m_send_data_timer_id);// 添加了一个新的定时器
    
    
    //============================ [ADDED] 新增:30秒后休眠的定时器 ============================//
    /** 定义休眠定时器句柄 */
    APP_TIMER_DEF(m_sleep_timer_id);
    
    /** 定义休眠超时时间(30秒) */
    #define SLEEP_AFTER_30S_INTERVAL   APP_TIMER_TICKS(30000)
    //=====================================================================================//
    
    
    static nrf_drv_wdt_channel_id m_wdt_channel_id;//添加看门狗
    
    
    // Type holding the two advertising selection modes.
    typedef enum
    {
        SELECTION_CONNECTABLE = 0, 
        SELECTION_NON_CONNECTABLE
    } adv_scan_type_seclection_t;
    
    
    // Type holding the two possible phy options.
    typedef enum
    {
        SELECTION_1M_PHY = 0, 
        SELECTION_CODED_PHY
    } adv_scan_phy_seclection_t;
    
    static adv_scan_type_seclection_t   m_adv_scan_type_selected = SELECTION_CONNECTABLE;   /**< Global variable holding the current scan selection mode. */
    static adv_scan_phy_seclection_t    m_adv_scan_phy_selected  = SELECTION_CODED_PHY;      /**< Global variable holding the current phy selection. */
    
    
    
    
    
    static uint8_t ble_status = 0;	   //0: disconnecting 1: advertising 2:connection 	
    uint8_t SI4455 = 1 ;  //0 disable 1 enable
    
    
    
    
    
    
    
    bool notification_enabled = false;
    static int data_ptr = 0; 
    
    bool data_sent = false;
    
    bool sleep_timeout = false;
    
    volatile uint32_t milliseconds = 0; 
    
    static int cnt = 0;
    uint8_t ack = 0x0;
    
    double_t  rssi_sum_linear = 0;
    uint16_t rssi_count = 0;
    double_t  rssi_average_linear = 0;
    double_t  rssi_average_dBm = 0;
    uint16_t available_sensors = 0;																					/** <0x0:Off , 0x1:Advertising , 0x2:Connected. */		
    
     alcohol_sensors_data_t alcohol_sensors_data[10]; //后面可以多次数据整合处理
    
    volatile float radiation_adc_max_value = 0;
    volatile uint16_t radiation_data_count = 0;
    
    //static  uint8_t encryption_key[16] = {0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f};
    
    int peripheral_tx_power_levels[] = {0,-40, -20, -16, -12, -8, -4, 0, 3, 4, 8};
    
    static int peripheral_tx_level_index = -8;	
    static int peripheral_tx_level_index_conn = 10;
    
    //static volatile bool is_ready = false;
    //static nrf_saadc_value_t samples[SAADC_CHANNEL_COUNT];
    //static nrfx_saadc_channel_t channels[SAADC_CHANNEL_COUNT] = {NRFX_SAADC_DEFAULT_CHANNEL_SE(NRF_SAADC_INPUT_AIN3, 0)};
    
    //static uint8_t 
    
    static uint16_t   m_conn_handle = BLE_CONN_HANDLE_INVALID;                            /**< Handle of the current connection. */
    static uint16_t   m_ble_alco_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3;            /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Alco service module. */
    static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
    {
        {BLE_UUID_ALCO_SERVICE, BLE_UUID_TYPE_VENDOR_BEGIN}
    };
    
    static void advertising_start();
    static void advertising_timeout_handler(void);
    
    
    
    
    
    #define SAMPLES_IN_BUFFER 10000
    volatile uint8_t state = 1;
    
    static const nrf_drv_timer_t m_timer = NRF_DRV_TIMER_INSTANCE(4);
    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;
    #define HW_TIMEOUT 10000
    
    
    
    
    
    
    
    
    
    
    
    
    //--------------------------------------------------------------
    
    
    static void set_tx_power(void)
    {
        #if (ENABLED_PRINTF)
    			NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
        ret_code_t err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_ADV, m_advertising.adv_handle, peripheral_tx_power_levels[peripheral_tx_level_index]);
        APP_ERROR_CHECK(err_code);
    }
    
    
    //--------------------------------------------------------------
    
    /*static void send_sensor_data(void)
    {
      ret_code_t err_code;
    
      #if (DEVICE_MODE != DEVICE_MODE_NO_SENSOR)
    
         for (int i=0 ; i < data_ptr; i++){
            uint8_t encrypted_data[16];                                 
            //uint16_t data_length = sizeof(alcohol_sensors_data[i].bme688_data);
            uint16_t data_length = sizeof(alcohol_sensors_data[i]);*/
          
                               
            /*	
            alcohol_sensors_data_t decrypted_data;
    
            NRF_LOG_INFO("++++++++++++++++++++++++++++++++++");	
            NRF_LOG_INFO("encrypted data: %u",encrypted_data);		
            NRF_LOG_HEXDUMP_INFO(&encrypted_data, 16)
            decrypt(&decrypted_data, encrypted_data, encryption_key);	
            NRF_LOG_INFO("Dycrypted!")
            NRF_LOG_INFO("Decypted-Time: %s",decrypted_data.time_stamp);
            NRF_LOG_INFO("Decypted-Temperature: " NRF_LOG_FLOAT_MARKER " degrees Celsius.", NRF_LOG_FLOAT((decrypted_data.bme688_data.temperature)));
            NRF_LOG_INFO("Decypted-Humidity: " NRF_LOG_FLOAT_MARKER " Percent.", NRF_LOG_FLOAT((decrypted_data.bme688_data.humidity)));
            NRF_LOG_INFO("Decypted-BME688 Gas resistance: " NRF_LOG_FLOAT_MARKER " bar.", NRF_LOG_FLOAT((decrypted_data.bme688_data.gas_resistance))); 
            NRF_LOG_INFO("Decypted-SGP40 VOC: %u", decrypted_data.sgp40_voc); 	 
            NRF_LOG_INFO("++++++++++++++++++++++++++++++++++");		
            */
    							 
            /*do
            {
                          	
                if (ENABLED_ENCRYPTION)
                {			
                    uint16_t encrypted_data_length = sizeof(encrypted_data);   
                    encrypt(&alcohol_sensors_data[i], encrypted_data, encryption_key);						 
                    err_code = ble_alco_data_send(&m_alco, (uint8_t*)&encrypted_data, &encrypted_data_length, m_conn_handle);
                }
                else
                {
        #if (ENABLED_PRINTF)
    			NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
            // 获取指向 radiation_data 的指针
              float* radiation_adc_max_ptr = &alcohol_sensors_data[i].radiation_data.radiation_adc_max;
    
              // 将指针转换为 uint8_t* 类型
              uint8_t* data_ptr = (uint8_t*)radiation_adc_max_ptr;
    
              // 定义数据长度
              uint16_t data_length = sizeof(float);
    
              // 发送数据
                err_code =ble_alco_data_send(&m_alco, data_ptr, &data_length, m_conn_handle);
    
                     //err_code = ble_alco_data_send(&m_alco, (uint8_t*)&alcohol_sensors_data[i].bme688_data, &data_length, m_conn_handle);              
                     //err_code = ble_alco_data_send(&m_alco, (uint8_t*) &alcohol_sensors_data[i], &data_length, m_conn_handle);              
    
                }
                                          
                if ( (err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_RESOURCES) && (err_code != NRF_ERROR_NOT_FOUND) )
                {
                    APP_ERROR_CHECK(err_code);	
                }
            } while (err_code == NRF_ERROR_BUSY);
    
          } //end of for loop
          										 
      #endif 
    }*/
    static void send_sensor_data_BLE(void)
    {
    
            ret_code_t err_code;
            uint16_t data_length = sizeof(alcohol_sensors_data[data_ptr]);
    
    // 打印即将发送的数据长度
            NRF_LOG_INFO("Sending data length: %d", data_length);
    //      NRF_LOG_HEXDUMP_INFO(&alcohol_sensors_data[0], sizeof(alcohol_sensors_data[0]));
    //          NRF_LOG_INFO("Size of alcohol_sensors_data_t: %d bytes", sizeof(alcohol_sensors_data_t));
    //NRF_LOG_INFO("Offset of radiation_data: %d", offsetof(alcohol_sensors_data_t, radiation_data));
    //NRF_LOG_INFO("Offset of imu_data: %d", offsetof(alcohol_sensors_data_t, imu_data));
    //NRF_LOG_INFO("Offset of ens210_data: %d", offsetof(alcohol_sensors_data_t, ens210_data));
    // 发送数据
            err_code = ble_alco_data_send(&m_alco, (uint8_t*)&alcohol_sensors_data[data_ptr], &data_length, m_conn_handle);
            APP_ERROR_CHECK(err_code);
               										 
    }
    
    
    
    static void send_sensor_data_RF915(void)
    {
    
    comm_RF915_send(&alcohol_sensors_data[data_ptr]);
    
    }
    
    //--------------------------------------------------------------
    
    static void read_sensor_data(void * p_context)
    {
      #if (ENABLED_PRINTF)
            NRF_LOG_INFO("----- %s -----", __FUNCTION__);
      #endif
      ret_code_t err_code;
     UNUSED_PARAMETER(p_context);
      
    	
        if (ble_status == 1 && CONNECTION_MODE == 0 ) //&&SI4455 == 0 测试
      {
         err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
         APP_ERROR_CHECK(err_code);
         if (err_code == NRF_SUCCESS)
         {
            NRF_LOG_INFO("Advertising stopped!");
            NRF_LOG_INFO("-------------------------------------");	
            ble_status = 0;        
         }
    
         //if (data_ptr > 23) data_ptr = 0;
      }
    	
      //if (ble_status != 1 || CONNECTION_MODE == 1)
      //{
        
        //alcohol_sensors_data[data_ptr].bme688_data.humidity = 0x8000;
        //alcohol_sensors_data[data_ptr].bme688_data.temperature = 0x6666; hengming */
    
        switch(DEVICE_MODE) 
        {
          /*case DEVICE_MODE_SINGLE_BME688:
            err_code = get_sensor_data(BME688, &alcohol_sensors_data[data_ptr]);
            break;     
          case DEVICE_MODE_SINGLE_SGP40:
            err_code = get_sensor_data(SGP40, &alcohol_sensors_data[data_ptr]);
            uint32_t err_code;
            err_code = app_timer_start(sgp40_heater_off_timer_id, SGP40_HEATER_OFF_TIME, NULL);
            APP_ERROR_CHECK(err_code);
            break;      
          case DEVICE_MODE_SINGLE_CCS811:
            err_code = get_sensor_data(CCS811, &alcohol_sensors_data[data_ptr]);
            break;     
            
          case DEVICE_MODE_MULT_BME688_SGP40:
            err_code = get_sensor_data(BME688 | SGP40, &alcohol_sensors_data[data_ptr]);                               
            break;      
          case DEVICE_MODE_MULT_SIMULATE:
            err_code = get_sensor_data(SIMULATE, &alcohol_sensors_data[data_ptr]);
            break;     */
    
          case DEVICE_MODE_SINGLE_RADIATION:
            //err_code = app_timer_start(m_send_data_timer_id, APP_TIMER_TICKS(3000), NULL); // 每3秒发送一次数据
            //APP_ERROR_CHECK(err_code);
            alcohol_sensors_data[data_ptr].time_stamp = milliseconds;
            alcohol_sensors_data[data_ptr].radiation_data.radiation_adc_max = radiation_adc_max_value;
            alcohol_sensors_data[data_ptr].radiation_data.data_count = radiation_data_count; //这个函数放置值
            radiation_adc_max_value = 0;
            radiation_data_count = 0;
            break;   
          case DEVICE_MODE_RADIATION_TEST:
            err_code = get_sensor_data(ICM20948 | ENS210, &alcohol_sensors_data[data_ptr]);//新的模式   
            //err_code = app_timer_start(m_send_data_timer_id, APP_TIMER_TICKS(3000), NULL); // 每3秒发送一次数据
            APP_ERROR_CHECK(err_code);
            alcohol_sensors_data[data_ptr].time_stamp = milliseconds;
            alcohol_sensors_data[data_ptr].radiation_data.radiation_adc_max = radiation_adc_max_value;
            alcohol_sensors_data[data_ptr].radiation_data.data_count = radiation_data_count; //这个函数放置值
            radiation_adc_max_value = 0;
            radiation_data_count = 0;
            break; 
           
          default:
            break;
        }
        NRF_LOG_INFO("SI4455 status: %d", SI4455);
        print_sensor_data(&alcohol_sensors_data[data_ptr]);	
        NRF_LOG_INFO("-------------------------------------");
       
    
        if( (ble_status == 0) && (m_conn_handle == BLE_CONN_HANDLE_INVALID) )//&& (SI4455 == 0)为了测试一起发 
            { 
              
              
              advertising_timeout_handler();
              //err_code = app_timer_start(start_advertising_timer_id, START_ADVERTISING_TIME, NULL);
              //APP_ERROR_CHECK(err_code);
    
            } 
        if (ble_status == 2 && notification_enabled) //&& SI4455 == 0)为了测试一起发 
            {
              send_sensor_data_BLE();
    
            }
        if ((SI4455 == 1) || (ble_status == 0))
    
            {
            NRF_LOG_INFO("RF915 start!")
            //send_sensor_data_RF915();
          
            }
            	
        /*if (err_code == NRF_SUCCESS)
        {	
          NRF_LOG_INFO("Ptr:%i", data_ptr);
          print_sensor_data(&alcohol_sensors_data[data_ptr]);	
          NRF_LOG_INFO("-------------------------------------");					
    
          data_ptr += 1; 
    
          if (data_ptr % Num_Samples == 0)
          {                                  
            if( (ble_status == 0) && (m_conn_handle == BLE_CONN_HANDLE_INVALID))
            { 
              err_code = app_timer_start(start_advertising_timer_id, START_ADVERTISING_TIME, NULL);
              APP_ERROR_CHECK(err_code);
    
            } 
            else if (CONNECTION_MODE == 1 && ble_status == 2 && notification_enabled) //我改成0了
            {
              send_sensor_data();
    
            } else data_ptr = 0;                                                
          }
        } //end of err_code == NRF_SUCCESS
      } // end of ble_status != 1*/
      
    } 
    
    //--------------------------------------------------------------
    
    static void advertising_timeout_handler(void)
    {
      advertising_start();
      set_tx_power();			
    }
    
    
    //--------------------------------------------------------------
    
    /**@brief Function for starting timers.
     */
    static void read_sensor_timer_start(void)
    {
      #if (ENABLED_PRINTF)
          NRF_LOG_INFO("----- %s -----", __FUNCTION__);
      #endif
    	
      ret_code_t err_code;
      err_code = app_timer_start(m_read_sensor_timer_id, READ_SENSOR_INTERVAL, NULL);
      APP_ERROR_CHECK(err_code);	
      NRF_LOG_INFO("Read_sensor_data timer started.");
    
      err_code = app_timer_start(rtc_timer_id, RTC_INTERVAL, NULL);
      APP_ERROR_CHECK(err_code);	
      NRF_LOG_INFO("RTC timer started.");
    
      if (DEVICE_MODE == DEVICE_MODE_SINGLE_RADIATION)
      {
    
       // err_code = app_timer_start(m_send_data_timer_id, BLE_RETRY_TIME, NULL);
        err_code = app_timer_start(radiation_timer_id, RADIATION_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_INFO("Radiation timer started.");
      }
    
      if (DEVICE_MODE == DEVICE_MODE_RADIATION_TEST)
      {
    
        //err_code = app_timer_start(m_send_data_timer_id, RADIATION_INTERVAL, NULL);
        err_code = app_timer_start(radiation_timer_id, RADIATION_INTERVAL, NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_INFO("Radiation timer started."); //添加新的时间函数
      }
    }
    
    
    //--------------------------------------------------------------
    
    
    static void alcohol_sensor_init_timeout_handler()
    {
      if (ble_status == 0) //&& (CONNECTION_MODE || DEVICE_MODE == DEVICE_MODE_NO_SENSOR)) //这里
      {
        advertising_timeout_handler();
      }
    
      switch(DEVICE_MODE) 
      {
        /*case DEVICE_MODE_SINGLE_BME688:
          alcohol_sensor_init(BME688);
          //  alcohol_sensor_shutdown(SGP40);
          break;     
        case DEVICE_MODE_SINGLE_SGP40:
          alcohol_sensor_init(SGP40);
          alcohol_sensor_shutdown(BME688);
          break;      
        case DEVICE_MODE_SINGLE_CCS811:
          alcohol_sensor_init(CCS811);
          //  alcohol_sensor_shutdown(BME688 | SGP40);
          break;     
        case DEVICE_MODE_MULT_BME688_SGP40:
          alcohol_sensor_init(BME688 | SGP40);
          break;      
       
        case DEVICE_MODE_MULT_SIMULATE:
          alcohol_sensor_init(SIMULATE);
          break;  */
          
         case DEVICE_MODE_SINGLE_RADIATION:
          alcohol_sensor_init(RADIATION_SENSING);
          break;     
         case DEVICE_MODE_RADIATION_TEST:
          alcohol_sensor_init(ICM20948| ENS210); //新的模式
          break;    
        default:
          break;
      }
    
      read_sensor_timer_start();
      
    }
    
    
    /*--------------------------------------------------------------
    
    
    void alcohol_sensor_init_timer(void)
    {
      uint32_t err_code;
      err_code = app_timer_start(alcohol_sensor_init_timer_id, ALCOHOL_SENSOR_INIT_TIME, NULL);
      APP_ERROR_CHECK(err_code);
    }
    
    
    *///--------------------------------------------------------------
    
    
    /**@brief Function for assert macro callback.
     *
     * @details This function will be called in case of an assert in the SoftDevice.
     *z
     * @warning This handler is an example only and does not fit a final product. You need to analyse
     *          how your product is supposed to react in case of Assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num    Line number of the failing ASSERT call.
     * @param[in] p_file_name File name of the failing ASSERT call.
     */
    void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        #if (ENABLED_PRINTF)
    		NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        app_error_handler(DEAD_BEEF, line_num, p_file_name);
    }
    
    //--------------------------------------------------------------
    
    /*void spg40_heater_off_init_timer(void)
      {
      uint32_t err_code;
      err_code = app_timer_start(sgp40_heater_off_timer_id, SGP40_HEATER_OFF_TIME, NULL);
      APP_ERROR_CHECK(err_code);
      }
    
    //--------------------------------------------------------------
    
    static void sgp40_timeout_handler()
      {
      ret_code_t err_code;
      err_code = get_sensor_data(SGP40, &alcohol_sensors_data[data_ptr]);
      }
    */
    
    
    //--------------------------------------------------------------
    void rtc_timer_handler(void * p_context)
    {
      milliseconds++;
    }
    
    
    
    int max(int a, int b) {
        return (a > b) ? a : b;
    }
    
    
    
    
    
    
    
    
    void calibrate_saadc(void)
    {
        nrfx_err_t nrfx_err_code = NRFX_SUCCESS;
    
        // Stop ADC
        nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
        NRFX_IRQ_DISABLE(SAADC_IRQn);
        nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
    
        // Wait for ADC being stopped.
        bool result;
        NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result);
        NRFX_ASSERT(result);
    
        // Start calibration
        NRFX_IRQ_ENABLE(SAADC_IRQn);
        nrfx_err_code = nrfx_saadc_calibrate_offset();
        APP_ERROR_CHECK(nrfx_err_code);
        while(nrfx_saadc_is_busy()){};
        
        // Stop ADC
        nrf_saadc_int_disable(NRF_SAADC_INT_ALL);
        NRFX_IRQ_DISABLE(SAADC_IRQn);
        nrf_saadc_task_trigger(NRF_SAADC_TASK_STOP);
    
        // Wait for ADC being stopped. 
        NRFX_WAIT_FOR(nrf_saadc_event_check(NRF_SAADC_EVENT_STOPPED), HW_TIMEOUT, 0, result);
        NRFX_ASSERT(result);
        
        // Enable IRQ
        NRFX_IRQ_ENABLE(SAADC_IRQn);
    
    }
    
    
    
    
    
    void timer_handler(nrf_timer_event_t event_type, void * p_context)
    {
    
    }
    
    
    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_us_to_ticks(&m_timer, 100);
        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++)
            {
                radiation_data_count++;
                radiation_adc_max_value = max(radiation_adc_max_value, p_event->data.done.p_buffer[i]);
                //NRF_LOG_INFO("%d", p_event->data.done.p_buffer[i]);
            }
            //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_AIN3);
    
        err_code = nrf_drv_saadc_init(NULL, saadc_callback);
        APP_ERROR_CHECK(err_code);
    
        calibrate_saadc();
    
        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);
    
    }
    
    
    
    
    
    
    
    
    
    
    
    //======================= [ADDED] 新增:30秒后休眠的回调函数 =======================//
    /**
     * @brief sleep_timer_handler:30秒后被调用,使芯片进入休眠
     */
    static void sleep_timer_handler(void * p_context)
    {
        //NRF_LOG_INFO("Going to sleep mode...");
        //NRF_LOG_FLUSH(); // 确保日志输出完毕
    
        // 进入System OFF模式
        //sd_power_system_off();
        // 或 nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }
    //=============================================================================//
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    
    /*ADC封存
    //static void event_handler(nrfx_saadc_evt_t const * p_event)
    //{
    //  if (p_event->type == NRFX_SAADC_EVT_DONE)
    //  {   int i = 0;
    //    for(int i = 0; i < p_event->data.done.size; i++)
    //    {
    //      radiation_data_count++;
    //      radiation_adc_max_value = max(radiation_adc_max_value, p_event->data.done.p_buffer[i]);
    //      //NRF_LOG_INFO("CH%d: %d", i, p_event->data.done.p_buffer[i]);
    //      //NRF_LOG_INFO("shuliang%d", p_event->data.done.size);
    //    }
    //    is_ready = true;
    //  }
    //}//这个函数读取值
    ////--------------------------------------------------------------
      
    
    ///**@brief Timeout handler for the repeated timer.
    // */
    static void radiation_timer_handler(void * p_context)
    {
    //    if(is_ready)
    //    {
    //        ret_code_t err_code;
    
    //        //err_code = nrfx_saadc_simple_mode_set((1<<0),
    //        //                                      NRF_SAADC_RESOLUTION_12BIT, //NRF_SAADC_RESOLUTION_12BIT
    //        //                                      NRF_SAADC_OVERSAMPLE_DISABLED,
    //        //                                      event_handler);
    //        //APP_ERROR_CHECK(err_code);
            
    //        //err_code = nrfx_saadc_buffer_set(samples, SAADC_CHANNEL_COUNT);
    //        //APP_ERROR_CHECK(err_code);
    
    //        err_code = nrfx_saadc_mode_trigger();
    //        APP_ERROR_CHECK(err_code);
    
    //        is_ready = false;
    //    }
    }
    
    //static void adc_init(void)
    //{
    //    uint32_t err_code = nrfx_saadc_init(NRFX_SAADC_CONFIG_IRQ_PRIORITY);
    //    APP_ERROR_CHECK(err_code);
     
    //    err_code = nrfx_saadc_channels_config(channels, SAADC_CHANNEL_COUNT);
    //    APP_ERROR_CHECK(err_code);
    
    
    //        err_code = nrfx_saadc_simple_mode_set((1<<0),
    //                                              NRF_SAADC_RESOLUTION_12BIT, //NRF_SAADC_RESOLUTION_12BIT
    //                                              NRF_SAADC_OVERSAMPLE_DISABLED,
    //                                              event_handler);
    //        APP_ERROR_CHECK(err_code);
            
    //        err_code = nrfx_saadc_buffer_set(samples, SAADC_CHANNEL_COUNT);
    //        APP_ERROR_CHECK(err_code);
    //}
    
    //--------------------------------------------------------------
    static void lfclk_config(void)
    {
        ret_code_t err_code = nrf_drv_clock_init();                        //Initialize the clock source specified in the nrf_drv_config.h file, i.e. the CLOCK_CONFIG_LF_SRC constant
        APP_ERROR_CHECK(err_code);
        nrf_drv_clock_lfclk_request(NULL);
        
        // Wait for the LFCLK to be ready
        while (!nrf_drv_clock_lfclk_is_running()) {
            // Wait for LFCLK to be ready
        }
    }
    
    //--------------------------------------------------------------
    
    
    
    
      //static void send_data_timer_handler(void * p_context)
      //{   
      //    if (SI4455 == 1) 
      //{
              
              
      //        //SI4455= 0;  //重新试试BLE
      //}
    
      //}
    
    
    
    
    void wdt_event_handler(void)
    {
        // This function will be called if the watchdog resets the system.
        // You can log or handle post-reset diagnostics here.
    }
    
    
    
    
    void watchdog_init(void)
    {
        uint32_t err_code = nrf_drv_wdt_init(NULL, wdt_event_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_drv_wdt_channel_alloc(&m_wdt_channel_id);
        APP_ERROR_CHECK(err_code);
    
        nrf_drv_wdt_enable();
    }
    
    void feed_watchdog(void)
    {
        nrf_drv_wdt_channel_feed(m_wdt_channel_id);
    }
    
    
    
    /**@brief Function for initializing the timer module.
     */
    static void timers_init(void)
    {
        #if (ENABLED_PRINTF)
                NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	  
        lfclk_config();                                  //Configure low frequency 32kHz clock
    
    
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    	
        // Create read_sensor_timer.    
        err_code = app_timer_create(&m_read_sensor_timer_id, APP_TIMER_MODE_REPEATED, read_sensor_data);
        APP_ERROR_CHECK(err_code);
    
        // Create start_advertising_timer.    
        //err_code = app_timer_create(&start_advertising_timer_id, APP_TIMER_MODE_SINGLE_SHOT, advertising_timeout_handler);
        //APP_ERROR_CHECK(err_code);
    
        // Create powered_on_timer.    
        //err_code = app_timer_create(&alcohol_sensor_init_timer_id, APP_TIMER_MODE_SINGLE_SHOT, alcohol_sensor_init_timeout_handler);
        //APP_ERROR_CHECK(err_code);
        
        //err_code = app_timer_create(&sgp40_heater_off_timer_id, APP_TIMER_MODE_REPEATED, sgp40_timeout_handler);
        //APP_ERROR_CHECK(err_code);
    
        // Create radiation timer. 
        err_code = app_timer_create(&radiation_timer_id, APP_TIMER_MODE_REPEATED, radiation_timer_handler);
        APP_ERROR_CHECK(err_code);
    
         //Create rtc timer. 
        err_code = app_timer_create(&rtc_timer_id, APP_TIMER_MODE_REPEATED, rtc_timer_handler);
        APP_ERROR_CHECK(err_code);
    
      // Create send data timer.
      //err_code = app_timer_create(&m_send_data_timer_id, APP_TIMER_MODE_REPEATED, send_data_timer_handler);
      //APP_ERROR_CHECK(err_code); //初始化这个发送的定时器
    
    
    // [ADDED]
    err_code = app_timer_create(&m_sleep_timer_id,
                                APP_TIMER_MODE_SINGLE_SHOT,
                                sleep_timer_handler);
    APP_ERROR_CHECK(err_code);
    
    }
    
    
    
    //--------------------------------------------------------------
    
    /**@brief Function for the GAP initialization.
     *
     * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
     *          the device. It also sets the permissions and appearance.
     */
    static void gap_params_init(void)
    {
        #if (ENABLED_PRINTF)
              NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        uint32_t                err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *) DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
        gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
        gap_conn_params.slave_latency     = SLAVE_LATENCY;
        gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for handling Queued Write Module errors.
     *
     * @details A pointer to this function will be passed to each service which may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
      APP_ERROR_HANDLER(nrf_error);
    
    }
    
    static void trigger_controlled_disassebly()
    {
      NRF_LOG_INFO("----- %s -----", __FUNCTION__);
      alcohol_sensor_controlled_disassembly();
      //nrf_delay_ms(1000);
    }
    
    //--------------------------------------------------------------
    /**@brief Function for handling the data from the Alco Service.
     *
     * @details This function will process the event of Alco BLE Service 
     *
     * @param[in] p_evt       Alco Service event.
     */
    /**@snippet [Handling the Alco Service event] */
    static void alco_evt_handler(ble_alco_evt_t * p_evt)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
        uint32_t err_code;
        switch (p_evt->type)
        {
             /*case BLE_ALCO_EVT_NOTIFICATION_ENABLED:
                
                NRF_LOG_INFO("Notification enabled!");
                notification_enabled = true;
                if (CONNECTION_MODE == 0)
                {
                  send_sensor_data();
                }
            break;原始的*/
    
            case BLE_ALCO_EVT_NOTIFICATION_ENABLED:
            NRF_LOG_INFO("Notification enabled!");
            notification_enabled = true;
            /*if (CONNECTION_MODE == 0)
            {
            send_sensor_data_BLE();
            }*/
            break;
    
    
    				
    	/*case BLE_ALCO_EVT_NOTIFICATION_DISABLED:
                NRF_LOG_INFO("Notification disabled!");
                notification_enabled = false;
    							    
            break;*/
            case BLE_ALCO_EVT_NOTIFICATION_DISABLED:
            NRF_LOG_INFO("Notification disabled!");
            notification_enabled = false;
            //app_timer_stop(m_send_data_timer_id); // 停止定时器
            break;
    
    				
            case BLE_ALCO_EVT_RX_DATA:
                //NRF_LOG_INFO ("BLE_ALCO_EVT_RX_DATA");
                switch (*p_evt->params.rx_data.p_data)
                {
                  case BLE_MSG_ACKNOWLEDGEMENT:
                    cnt += 1;
                    if (cnt == data_ptr)
                    {
                        //NRF_LOG_INFO ("%i records succefully sent",data_ptr);
                        if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
                        {
                          ack = 0x0;
    
                          if (CONNECTION_MODE == 0)
                          {
                            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                            APP_ERROR_CHECK(err_code);  
                          }  
                        }
    							  
                        data_ptr = 0;
                        cnt = 0;
                    }
                    break;
                    
                  case BLE_MSG_CONTROLLED_DISASSEMLBY:
                    trigger_controlled_disassebly();   //触发解体
                    break;
    
                  default:
                    // No implementation needed.
                    break; 
                }
    
                
    	  	
               //**@brief If you want to check the received data, please change NRF_LOG_DEFAULT_LEVEL to "Debug".
               // NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);   
            break;
    				
          case BLE_ALCO_EVT_TX_RDY:
    	NRF_LOG_INFO("--BLE_ALCO_EVT_TX_RDY--");
            break;
    				
          default:
            // No implementation needed.
            break;        
        }
    
    }
    
    //--------------------------------------------------------------
    
    
    /**@snippet [Handling the Alco Service event] */
    
    /**@brief Function for initializing services that will be used by the application.
     */
    static void services_init(void)
    {
         #if (ENABLED_PRINTF)
    			NRF_LOG_INFO("----- %s -----", __FUNCTION__);
         #endif
    	
        uint32_t            err_code;
        ble_alco_init_t     alco_init;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
        APP_ERROR_CHECK(err_code);
    
        // Initialize NUS.
        memset(&alco_init, 0, sizeof(alco_init));
    
        alco_init.event_handler = alco_evt_handler;
    
        err_code = ble_alco_init(&m_alco, &alco_init);
        APP_ERROR_CHECK(err_code);
    }
    
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for handling an event from the Connection Parameters Module.
     *
     * @details This function will be called for all events in the Connection Parameters Module
     *          which are passed to the application.
     *
     * @note All this function does is to disconnect. This could have been done by simply setting
     *       the disconnect_on_fail config parameter, but instead we use the event handler
     *       mechanism to demonstrate its use.
     *
     * @param[in] p_evt  Event received from the Connection Parameters Module.
     */
    static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
    {
        #if (ENABLED_PRINTF)
          NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        uint32_t err_code;
    
        if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
        {
            err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
            APP_ERROR_CHECK(err_code);
        }
    }
    
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for handling errors from the Connection Parameters module.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	  
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
    
        uint32_t               err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_GATT_HANDLE_INVALID;
        cp_init.disconnect_on_fail             = false;
        cp_init.evt_handler                    = on_conn_params_evt;
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for handling advertising events.
     *
     * @details This function will be called for advertising events which are passed to the application.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	  
        uint32_t err_code;
    
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
                err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
                APP_ERROR_CHECK(err_code);
                break;
            case BLE_ADV_EVT_IDLE:
    
                break;
            default:
                break;
        }
    }
    
    
    //--------------------------------------------------------------
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
        
        
        uint32_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected");
    				
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    				
                // Change TX power level
                //err_code = sd_ble_gap_tx_power_set(BLE_GAP_TX_POWER_ROLE_CONN, m_conn_handle, peripheral_tx_power_levels[peripheral_tx_level_index_conn]);
                //NRF_LOG_INFO("Tx_power not updated for connection");
                //APP_ERROR_CHECK(err_code);
                
                err_code = sd_ble_gap_rssi_start(m_conn_handle, 1, 1);
                APP_ERROR_CHECK(err_code);
    				
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                ble_status = 2;
            break;
    
            case BLE_GAP_EVT_DISCONNECTED:
                NRF_LOG_INFO("RSSI Value: %d dBm \n", rssi_sum_linear/rssi_count);
                NRF_LOG_INFO("Disconnected");
                NRF_LOG_INFO("-----------------------------------");
                // LED indication will be changed when advertising starts.
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                rssi_count = 0;
                rssi_sum_linear = 0;
                ble_status = 0;
                notification_enabled = false;
    
            break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(m_conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
    	    ble_status = 0;
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
    	    ble_status = 0;
                break;
                
            /*case BLE_GAP_EVT_RSSI_CHANGED:
                /*In the BLE_GAP_EVT_CONNECTED case, I call the function sd_ble_gap_rssi_start, which activates the RSSI readings. 
                When the value goes above a threshold chosen, it triggers this event. Here I print the RSSI value. The threshold at which
                the RSSI_CHANGED event is triggered can be changed from the rssi_start function, and also the number of consecutive rssi above 
                the threshold are needed to activate the interrupt need to be defined.
                rssi_average = - (abs(rssi_average) + abs(p_ble_evt->evt.gap_evt.params.rssi_changed.rssi))
                
                rssi_count = rssi_count + 1;  */     
    
            case BLE_GAP_EVT_RSSI_CHANGED:
    {
        
    
        // 累加线性RSSI值
        rssi_sum_linear += pow(10.0, (p_ble_evt->evt.gap_evt.params.rssi_changed.rssi +60) / 10.0);
        //NRF_LOG_INFO("rssi_sum: %d ", rssi_sum_linear);
        // 增加RSSI计数
        rssi_count++;
    
        // 如果RSSI计数达到100,计算平均值
        if (rssi_count == 1000)
        {
            // 计算RSSI平均值
            rssi_average_linear = rssi_sum_linear / rssi_count;
            rssi_average_dBm = 10 * log10(rssi_average_linear) - 60;
    
            // 打印当前的RSSI和平均RSSI
            //NRF_LOG_INFO("RSSI_average_linear * 10^6  :  NRF_LOG_FLOAT_MARKER ", rssi_average_linear);
            NRF_LOG_INFO("RSSI Average: " NRF_LOG_FLOAT_MARKER " dBm", NRF_LOG_FLOAT(rssi_average_dBm));
            //NRF_LOG_INFO("RSSI count: %d", rssi_count);
    
            // 检查RSSI平均值
            if (rssi_average_dBm < -100.0) {
                SI4455 = 1; // 使能RF915
                //err_code = app_timer_start(m_send_data_timer_id, BLE_RETRY_TIME, NULL);
                NRF_LOG_INFO("SI4455 enabled");
            } else {
                SI4455 = 1; // 关闭RF915
                NRF_LOG_INFO("SI4455 disabled");
                //app_timer_stop(m_send_data_timer_id);
            }
    
            // 重置计数器和RSSI累加值,以便开始新的累积
            rssi_count = 0;
            rssi_sum_linear = 0;
        }
    
        break;
    }
    
    		
            default:
                // No implementation needed.
                break;
        }
    }
    
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for the SoftDevice initialization.
     *
     * @details This function initializes the SoftDevice and the BLE event interrupt.
     */
    static void ble_stack_init(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        ret_code_t err_code;
    
        err_code = nrf_sdh_enable_request();
        APP_ERROR_CHECK(err_code);
    
        // Configure the BLE stack using the default settings.
        // Fetch the start address of the application RAM.
        uint32_t ram_start = 0;
        err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Register a handler for BLE events.
        NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for handling events from the GATT library. */
    void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
        {
            m_ble_alco_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
            NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_alco_max_data_len, m_ble_alco_max_data_len);
        }
    
        NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
        p_gatt->att_mtu_desired_central,
        p_gatt->att_mtu_desired_periph);
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for initializing the GATT library. */
    void gatt_init(void)
    {
        #if (ENABLED_PRINTF)
            NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        ret_code_t err_code;
    
        err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
        APP_ERROR_CHECK(err_code);
    }
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for handling events from the BSP module.
     *
     * @param[in]   event   Event generated by button press.
     */
    void bsp_event_handler(bsp_event_t event)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        uint32_t err_code;
        switch (event)
        {
            case BSP_EVENT_SLEEP:
                break;
    
            case BSP_EVENT_DISCONNECT:
                err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                if (err_code != NRF_ERROR_INVALID_STATE)
                {
                    APP_ERROR_CHECK(err_code);
                }
                break;
    
            case BSP_EVENT_WHITELIST_OFF:
                if (m_conn_handle == BLE_CONN_HANDLE_INVALID)
                {
                    err_code = ble_advertising_restart_without_whitelist(&m_advertising);
                    if (err_code != NRF_ERROR_INVALID_STATE)
                    {
                        APP_ERROR_CHECK(err_code);
                    }
                }
                break;
    
            default:
                break;
        }
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for initializing the Advertising functionality.
     */
    static void advertising_init(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        uint32_t               err_code;
        ble_advertising_init_t init;
    
        memset(&init, 0, sizeof(init));
    
        init.advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        init.advdata.include_appearance = false;
        /*BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE --> standard mode
         BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE --> CODED PHY */
        init.advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE; 
    
        init.srdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
        init.srdata.uuids_complete.p_uuids  = m_adv_uuids;
    
        if (CONNECTION_MODE == 0)
        {
          init.config.ble_adv_on_disconnect_disabled = true;
        }
        
        init.config.ble_adv_fast_enabled  = true;
        init.config.ble_adv_fast_interval = APP_ADV_INTERVAL;
        init.config.ble_adv_fast_timeout  = APP_ADV_DURATION;
        init.evt_handler = on_adv_evt;
    
        err_code = ble_advertising_init(&m_advertising, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
    }
    
    
    
    //--------------------------------------------------------------
    
    /**@brief Function for initializing the nrf log module.
     */
    static void log_init(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        ret_code_t err_code = NRF_LOG_INIT(NULL);
        APP_ERROR_CHECK(err_code);
    
        NRF_LOG_DEFAULT_BACKENDS_INIT();
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
    	
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
        NRF_POWER->DCDCEN = 1;
    }
    
    //--------------------------------------------------------------
    
    /**@brief Function for handling the idle state (main loop).
     *
     * @details If there is no pending log operation, then sleep until next the next event occurs.
     */
    static void idle_state_handle(void)
    {
      if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    //--------------------------------------------------------------
    
    
    /**@brief Function for starting advertising.
     */
    static void advertising_start(void)
    {
        #if (ENABLED_PRINTF)
    	NRF_LOG_INFO("----- %s -----", __FUNCTION__);
        #endif
      if(ble_status == 0 )//&& SI4455 == 0测试一起
      {   
          uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
          APP_ERROR_CHECK(err_code);
          if (err_code == NRF_SUCCESS)
          {
              ble_status = 1;
              NRF_LOG_INFO("Advertising started...");
          }
      }
    }
    
    
    
    
    
    //--------------------------------------------------------------
    /**@brief Application main function.
     */
    int main(void)
    {
      // Initialize.
      log_init();  
      timers_init();
      power_management_init();
      ble_stack_init();
      gap_params_init();
      gatt_init();
      services_init();
      advertising_init();
      conn_params_init();
    
      //=== [ADDED] 启动“30秒后休眠”定时器:一定要在 app_timer_init() 后调用 ===//
        ret_code_t err_code = app_timer_start(m_sleep_timer_id, 
                                              SLEEP_AFTER_30S_INTERVAL, 
                                              NULL);
        APP_ERROR_CHECK(err_code);
        NRF_LOG_INFO("Device will go to sleep in 30 seconds...");
        //==========================================================================//
    
      //adc_init();//封存
      saadc_init();
      saadc_sampling_event_init();
      saadc_sampling_event_enable();
      watchdog_init();
    
      /* Start execution */
      NRF_LOG_INFO("Radiation Sensor started: %s %s \r\n",  __DATE__, __TIME__);
      //NRF_LOG_INFO("Firmware version: %s",ALCOHOL_FIRMWARE_VERSION)
      NRF_LOG_INFO("-------------------------");
      NRF_LOG_FLUSH();
            
                  
      #if (POWERED_ON_WITH_DELAY == 1)
        //alcohol_sensor_init_timer();
      #else
        alcohol_sensor_init_timeout_handler();
      #endif      
    
      //is_ready = true;//封存
      // Enter main loop.
    
      
      while (1)
      {
    
        //nrf_delay_ms(10000); //测试看门狗
        feed_watchdog();
        idle_state_handle();
      }  
    }
    
    
    /**
     * @}
     */
  • "when TX was set to -8, the chip's power consumption was significantly higher than when TX was set to 8" I note that Tx=8 resulted in connection, Tx=-8 did not; perhaps fast advertising (when not connected) trying fruitlessly to connect consumes more power than a mostly idle connection (when connected). ie not comparing like-with-like.

Reply Children
Related