- Piezo 6ch 측정 + 센서(배터리, IMU, 온도) 측정: mbb 명령어 추가

- Flash Memory Piezo 측정 파라미터 추가

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
jhChun
2026-03-18 13:54:06 +09:00
parent a0c96c6677
commit 4881c7f937
12 changed files with 507 additions and 306 deletions

View File

@@ -7,9 +7,9 @@
******************************************************************************/
/*******************************************************************************
* [모듈 개요] 배터리 전압 및 압력센서 ADC 측정 모듈
* [모듈 개요] 배터리 전압 및 압력센서 ADC 측정 모듈 ---> 압력 센서 미탑재로 압력 센서 부분 삭제 예정
*
* nRF52840의 SAADC(Successive Approximation ADC)를 사용하여 다음을 수행한다:
* nRF52840의 SAADC(Successive Approximation ADC)를 사용하여 다음을 수행:
* 1) 배터리 전압 측정 (AIN2 채널, 1/3 프리스케일링)
* - 5초 주기 타이머(battery_loop)로 반복 측정
* - 저전압(3100mV 이하) 10회 연속 감지 시 자동 전원 OFF
@@ -42,18 +42,22 @@
//#include "fstorage.h"
#include "battery_saadc.h"
#include "main_timer.h"
#include "main.h" /* 2026-03-17: cmd_parse.h 삭제 → main.h */
#include "main.h"
#include "debug_print.h"
/* SAADC 내부 기준전압 600mV */
#define BATTERY_REF_VOLTAGE_IN_MILLIVOLTS 600 /**< Reference voltage (in milli volts) used by ADC while doing conversion. */
/* 1/3 프리스케일링 보상 계수 (입력 전압을 1/3로 분압하므로 x3, 추가 x2 = 총 x6) */
#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.*/
/* 10비트 ADC 최대 디지털 값 */
#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.
@@ -65,29 +69,33 @@
/* 배터리 측정용 더블 버퍼 (SAADC가 비동기로 교대 사용) */
static nrf_saadc_value_t adc_bufs[2];
/* 압력센서 2채널 ADC 버퍼 [0]=AIN7(P1), [1]=AIN4(P2) */
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);
/* 배터리 측정 주기: 5초 (밀리초 단위) */
#define BATTERY_LOOP_INTERVAL 5000
/* 저전압 체크 플래그 — battery_loop에서 true로 설정, 핸들러에서 소비 */
bool low_battery_check = false;
/* info4: 전체 센서 데이터 수집 모드 플래그 (cmd_parse에서 설정) */
extern bool info4; //cmd_parse
extern bool info4; // main.c
// cj add edit 25/11/24
/* info4 모드에서 압력센서 측정값을 임시 저장하는 변수 (mV 단위) */
volatile uint16_t info_p1;
volatile uint16_t info_p2;
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
/* true가 되면 main_timer에서 전원 OFF 시퀀스 실행 */
extern bool go_device_power_off;
/* 다른 작업(IMU 등) 처리 중이면 true — 배터리 측정 스킵용 */
extern volatile bool processing;
@@ -95,15 +103,17 @@ extern volatile bool processing;
extern which_cmd_t cmd_type_t;
extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] ;
/* info4 모드에서 배터리 전압을 임시 저장 (mV 단위) */
volatile uint16_t info_batt; //48_c
/* info4 순차 측정 제어 플래그: go_batt→go_temp→motion */
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 ;
/* info4 순차 측정 제어 플래그: go_batt→ go_temp → motion */
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
@@ -123,7 +133,9 @@ extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] ;
{
/* 음수 ADC 값은 0으로 처리 (노이즈 등으로 발생 가능) */
if (raw_adc < 0)
raw_adc = 0;
{
raw_adc = 0;
}
/* 805 uV/LSB 스케일링: raw x 805 = uV, /1000 = mV */
int32_t mv = (int32_t)raw_adc * MV_PER_ADC_STEP; // 단위: 805 uV
@@ -131,12 +143,15 @@ extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] ;
/* 0~3500mV 범위로 클램핑하여 유효 범위 보장 */
if (mv < 0)
mv = 0;
{
mv = 0;
}
if (mv > 3500)
mv = 3500;
{
mv = 3500;
}
return (uint16_t)mv;
}
@@ -181,26 +196,22 @@ void pressure_all_event_handler(nrf_drv_saadc_evt_t const * p_event)
DBG_PRINTF("P1:%d P2:%d\r\n", p1_mV, p2_mV);
}
/* BLE 모드이고 info4가 아닌 경우(단독 압력 측정) → BLE 바이너리 전송 */
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);
/* 2채널 압력값을 "rpn:" 헤더와 함께 바이너리 포맷으로 BLE 전송 */
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);
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);
/* 2채널 압력값을 "rpn:" 헤더와 함께 바이너리 포맷으로 BLE 전송 */
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);
}
}
}
}
/**
* @brief 배터리 전압 ADC 완료 콜백
*
@@ -214,7 +225,6 @@ void pressure_all_event_handler(nrf_drv_saadc_evt_t const * p_event)
*/
void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
{
/* 저전압 연속 감지 카운터 (static으로 호출 간 유지) */
static uint8_t low_battery_cnt = 0;
@@ -238,60 +248,60 @@ void battery_event_handler( nrf_drv_saadc_evt_t const * p_event )
/* ADC값 → mV 변환 (매크로: ADC x 600/1023 x 6) */
batt_lvl_in_milli_volt_0 = BATTERY_RESULT_IN_MILLI_VOLTS(register_val);
/* 분압 저항 보정 계수 1.42 적용 → 실제 배터리 전압 */
batt_lvl_in_milli_volt_1 = (batt_lvl_in_milli_volt_0) *1.42;
/* === 저전압 체크 모드 (battery_loop 타이머에서 설정) === */
if(low_battery_check == true) {
if(low_battery_check == true)
{
low_battery_check = false;
/* 배터리 전압이 LOW_BATTERY_VOLTAGE(3100mV) 이하인지 확인 */
if(batt_lvl_in_milli_volt_1 <= LOW_BATTERY_VOLTAGE) {
if(batt_lvl_in_milli_volt_1 <= LOW_BATTERY_VOLTAGE)
{
/* 10회 연속 저전압 감지 시 전원 OFF 시퀀스 시작 */
if(low_battery_cnt >= 10) {
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{
}
else
{
/* 아직 10회 미만 — 카운터 증가 후 경고 출력 */
low_battery_cnt++;
DBG_PRINTF("WARNING!!! low_battery cnt = %d, Batt = %d(mV)\r\n", low_battery_cnt, batt_lvl_in_milli_volt_1);
}
}
}
/* === info4 모드: 전체 센서 수집 중 배터리 값 저장 === */
else if (info4 == true){
/* === info4 모드: 전체 센서 수집 중 배터리 값 저장 === */
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) {
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) {
}
else if (cmd_type_t == CMD_BLE)
{
/* "rsn:" 헤더와 함께 배터리 전압을 바이너리로 BLE 전송 */
single_format_data(ble_bin_buffer, "rsn:", batt_lvl_in_milli_volt_1);
dr_binary_tx_safe(ble_bin_buffer,3);
dr_binary_tx_safe(ble_bin_buffer,3);
//data_tx_handler(ble_tx_buffer);
}
}
}
/* info4 모드: 배터리 측정 완료 → 다음 단계(온도 측정)로 전환 */
if (info4 == true){
go_batt =false; /* 배터리 측정 완료 표시 */
go_temp = true; /* 온도 측정 시작 플래그 설정 */
main_timer_start(); /* 메인 타이머 시작 → 온도 측정 트리거 */
}
}
@@ -309,8 +319,7 @@ static void battery_configure(void)
APP_ERROR_CHECK(err_code);
/* AIN2 채널 설정: 싱글엔드 입력, 1/3 프리스케일링 (기본값) */
nrf_saadc_channel_config_t config =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN2);
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);
@@ -335,33 +344,40 @@ void pressure_all_configure(void)
/* SAADC 드라이버 초기화 (이미 초기화된 경우 무시) */
err_code = nrf_drv_saadc_init(NULL, pressure_all_event_handler);
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE) {
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE)
{
DBG_PRINTF("SAADC init err=%d\r\n", err_code);
return;
}
/* 채널 0: AIN7 (압력센서1, P1) */
nrf_saadc_channel_config_t ch0_cfg =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
nrf_saadc_channel_config_t ch0_cfg = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN7);
/* 채널 1: AIN4 (압력센서2, P2) */
nrf_saadc_channel_config_t ch1_cfg =
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN4);
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) {
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) {
if (err_code != NRF_SUCCESS && err_code != NRF_ERROR_INVALID_STATE)
{
DBG_PRINTF("SAADC ch1 init err=%d\r\n", err_code);
return;
}
/* 2채널 ADC 버퍼 등록 ([0]=P1, [1]=P2) */
err_code = nrf_drv_saadc_buffer_convert(pressure_adc_buf, 2);
if (err_code != NRF_SUCCESS) {
if (err_code != NRF_SUCCESS)
{
DBG_PRINTF("SAADC buf conv err=%d\r\n", err_code);
return;
}
@@ -377,11 +393,9 @@ void battery_level_meas(void)
{
ret_code_t err_code;
battery_configure(); /* SAADC 배터리용 초기화 */
battery_configure(); /* SAADC 배터리용 초기화 */
err_code = nrf_drv_saadc_sample(); /* ADC 샘플링 트리거 (비동기) */
APP_ERROR_CHECK(err_code);
}
/**
@@ -409,15 +423,18 @@ void pressure_all_level_meas(void) //add cj add 25/11/19
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(); /* 배터리 ADC 1회 측정 시작 */
return;
}
else
{
low_battery_check = true; /* 저전압 감지 모드로 측정 */
battery_level_meas(); /* 배터리 ADC 1회 측정 시작 */
}
}