Files
firmware-test/project/ble_peripheral/ble_app_bladder_patch/battery_saadc.c
jhchun 831dbc2844 fix: BLE TX 먹통 해결 및 메모리 안전성 개선
- binary_tx_handler를 dr_binary_tx_safe로 전체 교체 (APP_ERROR_CHECK 제거)
- data_tx_handler APP_ERROR_CHECK → DBG_PRINTF 교체
- memset/memcpy 하드코딩 크기를 define 상수로 교체 (버퍼 오버런 수정)
- SERIAL_NO_LENGTH, HW_NO_LENGTH, PASSKEY_LENGTH를 main.h로 통합
- 미사용 HW 드라이버/EEPROM 코드 삭제, TWI를 i2c_manager.c로 통합
- EEPROM → FDS 전환, 코드 리뷰 현황 문서 추가

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-16 16:39:26 +09:00

317 lines
9.0 KiB
C

/*******************************************************************************
* @file battery_saadc.c
* @author CandyPops Co.
* @version V1.0.0
* @date 2022-09-05
* @brief
******************************************************************************/
#include "sdk_common.h"
#include <stdint.h>
#include <string.h>
#include "nrf.h"
#include "boards.h"
#include "app_error.h"
#include "nrf_drv_saadc.h"
#include "nrf_drv_timer.h"
#include "ble_nus.h"
#include "nrf_log.h"
#include "main.h"
#include "app_timer.h"
//#include "fstorage.h"
#include "battery_saadc.h"
#include "main_timer.h"
#include <cmd_parse.h>
#include "debug_print.h"
#define BATTERY_REF_VOLTAGE_IN_MILLIVOLTS 600 /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
#define BATTERY_PRE_SCALING_COMPENSATION 6 /**< The ADC is configured to use VDD with 1/3 prescaling as input. And hence the result of conversion is to be multiplied by 3 to get the actual value of the battery voltage.*/
#define BATTERY_ADC_RES_10BITS 1023 /**< Maximum digital value for 10-bit ADC conversion. */
//#define PRESSURE_RESULT_IN_MILLI_VOLTS(adc) ((adc * 3600) / 1023)
#define PRESSURE_OFFSET_DEFAULT 0 // ?? offset. ?? ? ??? ?? ??.
#define MV_PER_ADC_STEP 805 // ? 0.805mV per 1 LSB (nRF 12bit + scaling)
/**@brief Macro to convert the result of ADC conversion in millivolts.
*
* @param[in] ADC_VALUE ADC result.
*
* @retval Result converted to millivolts.
*/
#define BATTERY_RESULT_IN_MILLI_VOLTS(ADC_VALUE)\
((((ADC_VALUE) * BATTERY_REF_VOLTAGE_IN_MILLIVOLTS) / BATTERY_ADC_RES_10BITS) * BATTERY_PRE_SCALING_COMPENSATION)
static nrf_saadc_value_t adc_bufs[2];
static int16_t pressure_adc_buf[2]; //cj add 25/11/19
static uint16_t convert_adc_to_mV(int16_t raw_adc); //cj add 25/11/19
APP_TIMER_DEF(m_battery_loop_timer_id);
#define BATTERY_LOOP_INTERVAL 5000
bool low_battery_check = false;
extern bool info4; //cmd_parse
// cj add edit 25/11/24
volatile uint16_t info_p1;
volatile uint16_t info_p2;
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
extern bool go_device_power_off;
extern volatile bool processing;
extern which_cmd_t cmd_type_t;
extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] ;
volatile uint16_t info_batt; //48_c
extern bool go_temp; //
extern bool go_batt; //cmd_parse
extern bool motion_raw_data_enabled ;
extern bool ble_got_new_data;
extern bool motion_data_once ;
/**@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.
*/
static uint16_t convert_adc_to_mV(int16_t raw_adc)
{
if (raw_adc < 0)
raw_adc = 0;
int32_t mv = (int32_t)raw_adc * MV_PER_ADC_STEP; // ?: 805 uV
mv /= 1000;
// ===== (3) 0~3500mV ??? ???? ?? ?? =====
if (mv < 0)
mv = 0;
if (mv > 3500)
mv = 3500;
return (uint16_t)mv;
}
void pressure_all_event_handler(nrf_drv_saadc_evt_t const * p_event)
{
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
int16_t p1_adc = p_event->data.done.p_buffer[0]; // AIN7
int16_t p2_adc = p_event->data.done.p_buffer[1]; // AIN4
uint16_t p1_mV = convert_adc_to_mV(p1_adc);
uint16_t p2_mV = convert_adc_to_mV(p2_adc);
// PD Full mode(info4=true)When info_p1/info_p2 to Update
if(info4 == true)
{
info_p1 = p1_mV;
info_p2 = p2_mV;
}
// Re-buffer
APP_ERROR_CHECK(nrf_drv_saadc_buffer_convert(p_event->data.done.p_buffer, 2));
// uninit
nrf_drv_saadc_uninit();
nrf_drv_saadc_channel_uninit(0);
nrf_drv_saadc_channel_uninit(1);
// UART send
if(cmd_type_t == CMD_UART)
{
DBG_PRINTF("P1:%d P2:%d\r\n", p1_mV, p2_mV);
}
else if(cmd_type_t == CMD_BLE && info4 == false)
{
DBG_PRINTF("P1:%d P2:%d\r\n", p1_mV, p2_mV);
// uint16_t len = sprintf((char*)ble_bin_buffer,
// "rpn:%04x,%04x", p1_mV, p2_mV);
uint16_t result_data[2];
result_data[0] = p1_mV;
result_data[1] = p2_mV;
format_data(ble_bin_buffer, "rpn:", result_data,2);
dr_binary_tx_safe(ble_bin_buffer,4);
}
}
}
void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
{
static uint8_t low_battery_cnt = 0;
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
{
nrf_saadc_value_t register_val = 0;
uint16_t batt_lvl_in_milli_volt_0 = 0;
uint16_t batt_lvl_in_milli_volt_1 = 0;
uint32_t err_code = 0;
register_val = 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);
nrf_drv_saadc_uninit();
nrf_drv_saadc_channel_uninit(0);
batt_lvl_in_milli_volt_0 = BATTERY_RESULT_IN_MILLI_VOLTS(register_val);
batt_lvl_in_milli_volt_1 = (batt_lvl_in_milli_volt_0) *1.42;
if(low_battery_check == true) {
low_battery_check = false;
if(batt_lvl_in_milli_volt_1 <= LOW_BATTERY_VOLTAGE) {
if(low_battery_cnt >= 10) {
low_battery_cnt = 0;
/*go to power off and fds save */
DBG_PRINTF("Save FDS parameters and then Power OFF\r\n");
go_device_power_off = true;
main_timer_start();
}else{
low_battery_cnt++;
DBG_PRINTF("WARNING!!! low_battery cnt = %d, Batt = %d(mV)\r\n", low_battery_cnt, batt_lvl_in_milli_volt_1);
}
}
}
else if (info4 == true){
info_batt = batt_lvl_in_milli_volt_1;
DBG_PRINTF("INFOTn%d\r\n\r\n", batt_lvl_in_milli_volt_1);
}
else {
if(cmd_type_t == CMD_UART) {
DBG_PRINTF("Tn%d\r\n\r\n", batt_lvl_in_milli_volt_1);
} else if(cmd_type_t == CMD_BLE) {
single_format_data(ble_bin_buffer, "rsn:", batt_lvl_in_milli_volt_1);
dr_binary_tx_safe(ble_bin_buffer,3);
//data_tx_handler(ble_tx_buffer);
}
}
}
if (info4 == true){
go_batt =false;
go_temp = true;
main_timer_start();
}
}
/**@brief Function for configuring ADC to do battery level conversion.
*/
static void battery_configure(void)
{
ret_code_t err_code = nrf_drv_saadc_init(NULL, battery_event_handler);
APP_ERROR_CHECK(err_code);
nrf_saadc_channel_config_t config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
err_code = nrf_drv_saadc_channel_init(0, &config);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(&adc_bufs[0], 1);
APP_ERROR_CHECK(err_code);
err_code = nrf_drv_saadc_buffer_convert(&adc_bufs[1], 1);
APP_ERROR_CHECK(err_code);
}
void pressure_all_configure(void)
{
ret_code_t err_code;
err_code = nrf_drv_saadc_init(NULL, pressure_all_event_handler);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
DBG_PRINTF("SAADC init err=%d\r\n", err_code);
return;
}
nrf_saadc_channel_config_t ch0_cfg =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
nrf_saadc_channel_config_t ch1_cfg =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
err_code = nrf_drv_saadc_channel_init(0, &ch0_cfg);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
DBG_PRINTF("SAADC ch0 init err=%d\r\n", err_code);
return;
}
err_code = nrf_drv_saadc_channel_init(1, &ch1_cfg);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
DBG_PRINTF("SAADC ch1 init err=%d\r\n", err_code);
return;
}
err_code = nrf_drv_saadc_buffer_convert(pressure_adc_buf, 2);
if (err_code != NRF_SUCCESS) {
DBG_PRINTF("SAADC buf conv err=%d\r\n", err_code);
return;
}
}
void battery_level_meas(void)
{
ret_code_t err_code;
battery_configure();
err_code = nrf_drv_saadc_sample();
APP_ERROR_CHECK(err_code);
}
void pressure_all_level_meas(void) //add cj add 25/11/19
{
ret_code_t err_code;
pressure_all_configure(); // 2
err_code = nrf_drv_saadc_sample();
APP_ERROR_CHECK(err_code);
}
void battery_loop(void * p_context) /* For 1sec */
{
UNUSED_PARAMETER(p_context);
if(processing==true)
{
processing = false ; // add 20241218
//low_battery_check = true;
return;}
else{
low_battery_check = true;
battery_level_meas();
}
}
void battery_timer_start(void)
{
APP_ERROR_CHECK(app_timer_start(m_battery_loop_timer_id, APP_TIMER_TICKS(BATTERY_LOOP_INTERVAL), NULL));
}
void battery_timer_stop(void)
{
APP_ERROR_CHECK(app_timer_stop(m_battery_loop_timer_id));
}
void battery_timer_init(void)
{
APP_ERROR_CHECK(app_timer_create(&m_battery_loop_timer_id, APP_TIMER_MODE_REPEATED, battery_loop));
}