- Piezo 6ch 측정 + 센서(배터리, IMU, 온도) 측정: mbb 명령어 추가
- Flash Memory Piezo 측정 파라미터 추가 Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -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회 측정 시작 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,7 +63,7 @@
|
||||
#define CONFIG_REC_KEY (0x7010)
|
||||
|
||||
/* 매직 넘버: 플래시에 저장된 데이터가 유효한 설정인지 판별하는 데 사용 */
|
||||
#define CONFIG_MAGIC_NUMBER_VALUE (0x20231226)
|
||||
#define CONFIG_MAGIC_NUMBER_VALUE (0x20260318)
|
||||
|
||||
/* 전역 설정 데이터 구조체 인스턴스 */
|
||||
config_data_t m_config;
|
||||
@@ -118,12 +118,15 @@ void fds_default_value_set(void)
|
||||
/* Reset status */
|
||||
m_config.reset_status = reset_status_dflt;
|
||||
|
||||
/* Measurement parameters */
|
||||
m_config.pd_adc_cnt = 8;
|
||||
m_config.pd_delay_us = 8000;
|
||||
|
||||
/* Device usage count */
|
||||
m_config.life_cycle = 0;
|
||||
|
||||
/* 피에조 캡처 파라미터 기본값 */
|
||||
m_config.piezo_freq_option = 1; /* 2.1MHz */
|
||||
m_config.piezo_delay_us = 10; /* 버스트 후 10us */
|
||||
m_config.piezo_num_samples = 100; /* 100샘플 */
|
||||
m_config.piezo_cycles = 7; /* 7사이클 */
|
||||
m_config.piezo_averaging = 5; /* 5회 평균화 */
|
||||
}
|
||||
|
||||
|
||||
@@ -209,7 +212,8 @@ static void wait_for_fds_ready( void )
|
||||
nrf_pwr_mgmt_run();
|
||||
nrf_delay_ms(1);
|
||||
timeout++;
|
||||
if (timeout > 3000) { /* 3 second timeout */
|
||||
if (timeout > 3000) /* 3 second timeout */
|
||||
{
|
||||
DBG_PRINTF("[FDS] TIMEOUT!\r\n");
|
||||
break;
|
||||
}
|
||||
@@ -245,7 +249,8 @@ void config_load( void )
|
||||
DBG_PRINTF("[FDS] find rc=%u\r\n", rc);
|
||||
|
||||
/* FDS may not be fully ready yet - retry before writing defaults */
|
||||
if (rc != NRF_SUCCESS && cfg_retry < 10) {
|
||||
if (rc != NRF_SUCCESS && cfg_retry < 10)
|
||||
{
|
||||
cfg_retry++;
|
||||
DBG_PRINTF("[FDS] retry %u/10\r\n", cfg_retry);
|
||||
nrf_delay_ms(100);
|
||||
@@ -259,7 +264,8 @@ void config_load( void )
|
||||
|
||||
/* Open the record and read its contents. */
|
||||
rc = fds_record_open(&desc, &config);
|
||||
if (rc != NRF_SUCCESS) {
|
||||
if (rc != NRF_SUCCESS)
|
||||
{
|
||||
/* CRC error or corrupt record - delete and use defaults */
|
||||
DBG_PRINTF("[FDS] open ERR=%u, deleting\r\n", rc);
|
||||
(void)fds_record_delete(&desc);
|
||||
@@ -275,8 +281,7 @@ void config_load( void )
|
||||
rc = fds_record_close(&desc);
|
||||
APP_ERROR_CHECK(rc);
|
||||
|
||||
DBG_PRINTF("[FDS] magic=0x%08X (expect 0x%08X)\r\n",
|
||||
m_config.magic_number, CONFIG_MAGIC_NUMBER_VALUE);
|
||||
DBG_PRINTF("[FDS] magic=0x%08X (expect 0x%08X)\r\n", m_config.magic_number, CONFIG_MAGIC_NUMBER_VALUE);
|
||||
|
||||
if( m_config.magic_number != (uint32_t)CONFIG_MAGIC_NUMBER_VALUE )
|
||||
{ // first init
|
||||
@@ -315,14 +320,18 @@ void config_load( void )
|
||||
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_write(&desc, &m_dummy_record);
|
||||
if (rc != NRF_SUCCESS) {
|
||||
|
||||
if (rc != NRF_SUCCESS)
|
||||
{
|
||||
DBG_PRINTF("[FDS] Write ERR=%u\r\n", rc);
|
||||
fds_flag_write = false;
|
||||
}
|
||||
|
||||
while( fds_flag_write )
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
}
|
||||
|
||||
if( (rc != NRF_SUCCESS) && (rc == FDS_ERR_NO_SPACE_IN_FLASH) )
|
||||
{
|
||||
rc = fds_gc();
|
||||
@@ -332,6 +341,7 @@ void config_load( void )
|
||||
{
|
||||
APP_ERROR_CHECK(rc);
|
||||
}
|
||||
|
||||
NRF_LOG_FLUSH();
|
||||
goto cfg_load_start;
|
||||
}
|
||||
@@ -362,15 +372,19 @@ void config_save( void )
|
||||
DBG_PRINTF("[CFG_SAVE] start\r\n");
|
||||
|
||||
/* Wait for any previous FDS operation to complete */
|
||||
if (fds_flag_write) {
|
||||
if (fds_flag_write)
|
||||
{
|
||||
uint32_t wait_cnt = 0;
|
||||
|
||||
DBG_PRINTF("[CFG_SAVE] waiting for prev FDS op...\r\n");
|
||||
while (fds_flag_write && wait_cnt < 3000) {
|
||||
while (fds_flag_write && wait_cnt < 3000)
|
||||
{
|
||||
nrf_pwr_mgmt_run();
|
||||
nrf_delay_ms(1);
|
||||
wait_cnt++;
|
||||
}
|
||||
if (fds_flag_write) {
|
||||
if (fds_flag_write)
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] TIMEOUT! forcing flag clear\r\n");
|
||||
fds_flag_write = false;
|
||||
}
|
||||
@@ -391,6 +405,7 @@ void config_save( void )
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] update rc=%u\r\n", rc);
|
||||
|
||||
if( rc == FDS_ERR_NO_SPACE_IN_FLASH )
|
||||
{
|
||||
fds_flag_write = false;
|
||||
@@ -400,6 +415,7 @@ void config_save( void )
|
||||
rc = fds_record_update(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] retry rc=%u\r\n", rc);
|
||||
}
|
||||
|
||||
if( rc != NRF_SUCCESS )
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
@@ -412,6 +428,7 @@ void config_save( void )
|
||||
fds_flag_write = true;
|
||||
rc = fds_record_write(&desc, &m_dummy_record);
|
||||
DBG_PRINTF("[CFG_SAVE] write rc=%u\r\n", rc);
|
||||
|
||||
if( rc != NRF_SUCCESS )
|
||||
{
|
||||
DBG_PRINTF("[CFG_SAVE] FAIL rc=%u\r\n", rc);
|
||||
|
||||
@@ -40,15 +40,20 @@
|
||||
typedef struct
|
||||
{
|
||||
uint32_t magic_number; /* 4B - 0x20231226 */
|
||||
char hw_no[12]; /* 12B - HW Number */
|
||||
char hw_no[12]; /* 12B - HW Version */
|
||||
char serial_no[12]; /* 12B - Serial Number */
|
||||
uint8_t static_passkey[6]; /* 6B - BLE Passkey */
|
||||
uint8_t bond_data_delete; /* 1B - Bond delete flag */
|
||||
int8_t reset_status; /* 1B - Reset status */
|
||||
uint8_t pd_adc_cnt; /* 1B - ADC sample count */
|
||||
uint16_t pd_delay_us; /* 2B - PD delay (us) */
|
||||
uint32_t life_cycle; /* 4B - Device usage count (sxz/syz command) */
|
||||
} config_data_t; /* Total: 45 bytes - FDS에 저장하는 디바이스 설정 */
|
||||
uint32_t life_cycle; /* 4B - Device usage count */
|
||||
|
||||
/* Piezo 측정 파라미터 - 8B */
|
||||
uint8_t piezo_freq_option; /* 1B - Frequency : 송신 펄스 주파수 (0=1.8M, 1=2.1M, 2=2.0M, 3=1.7M) */
|
||||
uint8_t piezo_cycles; /* 1B - Burst Cycle : 송신 펄스 사이클 수 (3~7) */
|
||||
uint16_t piezo_averaging; /* 2B - 채널당 반복 측정 횟수 */
|
||||
uint16_t piezo_delay_us; /* 2B - 송신 펄스 출력 후 ADC 시작 시까지 대기시간(us) */
|
||||
uint16_t piezo_num_samples; /* 2B - 측정 ADC 샘플 개수(80~140) */
|
||||
} config_data_t; /* Total: 48 bytes - FDS에 저장하는 디바이스 설정 */
|
||||
|
||||
extern config_data_t m_config;
|
||||
|
||||
|
||||
@@ -9,8 +9,8 @@
|
||||
/*******************************************************************************
|
||||
* [모듈 개요] ICM42670P IMU 드라이버 상위 레이어
|
||||
*
|
||||
* ICM42670P IMU 센서의 초기화, 설정, 데이터 읽기를 담당하는 애플리케이션
|
||||
* 레이어 모듈이다. InvenSense 드라이버 API를 래핑하여 사용한다.
|
||||
* ICM42670P IMU 센서의 초기화, 설정, 데이터 읽기를 담당하는 애플리케이션 레이어 모듈
|
||||
* InvenSense 드라이버 API를 래핑하여 사용
|
||||
*
|
||||
* 주요 기능:
|
||||
* 1) setup_imu_device() - IMU 초기화 및 WHOAMI 확인 (0x67 = ICM42670P)
|
||||
@@ -28,8 +28,7 @@
|
||||
* - 센서 설정 → 전원 ON → 80ms 대기 → 12바이트 읽기 → 슬립
|
||||
*
|
||||
* 마운팅 매트릭스:
|
||||
* Q30 고정소수점 형식의 3x3 회전 매트릭스로, 보드에 장착된 센서의
|
||||
* 물리적 방향을 소프트웨어 좌표계에 맞춰 보정한다.
|
||||
* Q30 고정소수점 형식의 3x3 회전 매트릭스로, 보드에 장착된 센서의물리적 방향을 소프트웨어 좌표계에 맞춰 보정
|
||||
******************************************************************************/
|
||||
|
||||
#include "sdk_config.h"
|
||||
@@ -43,7 +42,6 @@
|
||||
|
||||
#include "app_util_platform.h"
|
||||
#include "main.h"
|
||||
/* 2026-03-17: cmd_parse.h 삭제 — main.h는 이미 포함됨 */
|
||||
#include "debug_print.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
@@ -60,7 +58,7 @@
|
||||
* Static and extern variables
|
||||
* -------------------------------------------------------------------------------------- */
|
||||
|
||||
/* IMU 드라이버 객체 — 드라이버 API 호출 시 항상 이 구조체를 전달 */
|
||||
/* IMU 드라이버 객체 — 드라이버 API 호출 시 항상 이 구조체 전달 */
|
||||
static struct inv_imu_device icm_driver;
|
||||
|
||||
/* BLE 전송용 바이너리 버퍼 */
|
||||
@@ -69,11 +67,11 @@ static struct inv_imu_device icm_driver;
|
||||
/*
|
||||
* ICM42670P 마운팅 매트릭스 (Q30 고정소수점)
|
||||
*
|
||||
* 센서가 보드에 장착된 물리적 방향에 따라 좌표 변환을 수행한다.
|
||||
* 센서가 보드에 장착된 물리적 방향에 따라 좌표 변환
|
||||
* Q30 형식: 1.0 = (1 << 30) = 0x40000000
|
||||
*
|
||||
* SM_REVB_DB (개발보드): X→-Y, Y→X 변환 (90도 회전)
|
||||
* 기본 (SmartMotion): 단위 행렬 (변환 없음)
|
||||
* 기본 (SmartMotion): 단위 행렬 (변환 없음)
|
||||
*/
|
||||
#if (SM_BOARD_REV == SM_REVB_DB) /* when DB or EVB are used */
|
||||
static int32_t icm_mounting_matrix[9] = { 0, -(1<<30), 0,
|
||||
@@ -85,13 +83,13 @@ static int32_t icm_mounting_matrix[9] = {(1<<30), 0, 0,
|
||||
0, 0, (1<<30)};
|
||||
#endif
|
||||
|
||||
bool custom_add_data; /* 커스텀 데이터 추가 플래그 (BLE 전송 제어) */
|
||||
extern bool motion_raw_data_enabled; /* 외부에서 원시 데이터 읽기를 요청하는 플래그 */
|
||||
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN]; /* BLE 텍스트 전송 버퍼 */
|
||||
extern which_cmd_t cmd_type_t; /* 현재 명령 소스 (BLE 또는 UART) */
|
||||
uint16_t ssp_data[6]={0,}; /* BLE 전송용 6축 데이터 배열 (accel XYZ + gyro XYZ) */
|
||||
extern bool info4; /* info4 모드 플래그 (cmd_parse에서 설정) */
|
||||
volatile uint16_t info_imu[6]; /* info4 모드에서 IMU 데이터를 저장하는 전역 배열 */
|
||||
bool custom_add_data; /* 커스텀 데이터 추가 플래그 (BLE 전송 제어) */
|
||||
extern bool motion_raw_data_enabled; /* 외부에서 원시 데이터 읽기를 요청하는 플래그 */
|
||||
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN]; /* BLE 텍스트 전송 버퍼 */
|
||||
extern which_cmd_t cmd_type_t; /* 현재 명령 소스 (BLE 또는 UART) */
|
||||
uint16_t ssp_data[6]={0,}; /* BLE 전송용 6축 데이터 배열 (accel XYZ + gyro XYZ) */
|
||||
extern bool info4; /* info4 모드 플래그 (cmd_parse에서 설정) */
|
||||
volatile uint16_t info_imu[6]; /* info4 모드에서 IMU 데이터를 저장하는 전역 배열 */
|
||||
|
||||
/* --------------------------------------------------------------------------------------
|
||||
* static function declaration
|
||||
@@ -143,7 +141,7 @@ int setup_imu_device(struct inv_imu_serif *icm_serif)
|
||||
|
||||
/*
|
||||
* configure_imu_device()
|
||||
* IMU 센서 동작 파라미터를 설정한다.
|
||||
* IMU 센서 동작 파라미터 설정
|
||||
*
|
||||
* 설정 항목:
|
||||
* - FIFO: 비활성화 (USE_FIFO=0일 때, 레지스터 직접 읽기 모드)
|
||||
@@ -161,7 +159,7 @@ int configure_imu_device(void)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
/* FIFO 비활성화 — 레지스터에서 직접 데이터를 읽는다 */
|
||||
/* FIFO 비활성화 — 레지스터에서 직접 데이터를 읽기 */
|
||||
if (!USE_FIFO)
|
||||
rc |= inv_imu_configure_fifo(&icm_driver, INV_IMU_FIFO_DISABLED);
|
||||
|
||||
@@ -199,9 +197,9 @@ int configure_imu_device(void)
|
||||
|
||||
/*
|
||||
* get_imu_data()
|
||||
* IMU에서 센서 데이터를 읽는다.
|
||||
* USE_FIFO 설정에 따라 FIFO 또는 레지스터에서 데이터를 가져온다.
|
||||
* 읽은 데이터는 imu_callback()을 통해 처리된다.
|
||||
* IMU에서 센서 데이터 읽기
|
||||
* USE_FIFO 설정에 따라 FIFO 또는 레지스터에서 데이터를 가져옴
|
||||
* 읽은 데이터는 imu_callback()을 통해 처리
|
||||
*/
|
||||
int get_imu_data(void)
|
||||
{
|
||||
@@ -255,7 +253,7 @@ static void get_accel_and_gyr_fsr(int16_t * accel_fsr_g, int16_t * gyro_fsr_dps)
|
||||
|
||||
/*
|
||||
* imu_callback()
|
||||
* IMU 드라이버가 새 센서 데이터를 읽을 때마다 호출되는 콜백 함수.
|
||||
* IMU 드라이버가 새 센서 데이터를 읽을 때마다 호출되는 콜백 함수
|
||||
*
|
||||
* 처리 흐름:
|
||||
* 1) 이벤트에서 가속도/자이로 원시 데이터 추출
|
||||
@@ -370,45 +368,45 @@ void imu_callback(inv_imu_sensor_event_t *event)
|
||||
{
|
||||
motion_raw_data_enabled = false;
|
||||
|
||||
/* info4 모드: 전역 배열 info_imu[6]에 데이터 저장, 외부 모듈에서 이 배열을 폴링하여 데이터 사용 */
|
||||
if (info4 == true)
|
||||
{
|
||||
/*
|
||||
* info4 모드: 전역 배열 info_imu[6]에 데이터를 저장한다.
|
||||
* 외부 모듈에서 이 배열을 폴링하여 데이터를 사용한다.
|
||||
*/
|
||||
info_imu[0] = (uint16_t)accel[0];
|
||||
info_imu[0] = (uint16_t)accel[0];
|
||||
info_imu[1] = (uint16_t)accel[1];
|
||||
info_imu[2] = (uint16_t) accel[2];
|
||||
info_imu[2] = (uint16_t)accel[2];
|
||||
info_imu[3] = (uint16_t)gyro[0];
|
||||
info_imu[4] = (uint16_t) gyro[1];
|
||||
info_imu[5] = (uint16_t)gyro[2];
|
||||
info_imu[4] = (uint16_t)gyro[1];
|
||||
info_imu[5] = (uint16_t)gyro[2];
|
||||
}
|
||||
|
||||
/* UART 모드: "Tp" 접두사로 6축 데이터를 텍스트 형식으로 출력 */
|
||||
else if(cmd_type_t == CMD_UART) {
|
||||
/* UART 모드: "Tp" 접두사로 6축 데이터를 텍스트 형식으로 출력 */
|
||||
printf("Tp%d,%d,%d,%d,%d,%d\r\n\r\n", accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
|
||||
} else if(cmd_type_t == CMD_BLE) {
|
||||
/*
|
||||
* BLE 모드: 6축 데이터를 바이너리 패킷으로 BLE 전송
|
||||
* ssp_data[0~2] = 가속도 XYZ, ssp_data[3~5] = 자이로 XYZ
|
||||
* format_data()로 "rsp:" 태그 + 12바이트 데이터를 패킷화
|
||||
* dr_binary_tx_safe()로 8바이트 BLE 전송
|
||||
*/
|
||||
ssp_data[0] = (uint16_t)accel[0];
|
||||
ssp_data[1] = (uint16_t)accel[1];
|
||||
ssp_data[2] = (uint16_t)accel[2];
|
||||
ssp_data[3] = (uint16_t)gyro[0];
|
||||
ssp_data[4] = (uint16_t)gyro[1];
|
||||
ssp_data[5] = (uint16_t)gyro[2];
|
||||
format_data(imu_bin_buffer, "rsp:", ssp_data,12);
|
||||
}
|
||||
|
||||
/*
|
||||
* BLE 모드: 6축 데이터를 바이너리 패킷으로 BLE 전송
|
||||
* ssp_data[0~2] = 가속도 XYZ, ssp_data[3~5] = 자이로 XYZ
|
||||
* format_data()로 "rsp:" 태그 + 12바이트 데이터를 패킷화
|
||||
* dr_binary_tx_safe()로 8바이트 BLE 전송
|
||||
*/
|
||||
else if(cmd_type_t == CMD_BLE) {
|
||||
ssp_data[0] = (uint16_t)accel[0];
|
||||
ssp_data[1] = (uint16_t)accel[1];
|
||||
ssp_data[2] = (uint16_t)accel[2];
|
||||
ssp_data[3] = (uint16_t)gyro[0];
|
||||
ssp_data[4] = (uint16_t)gyro[1];
|
||||
ssp_data[5] = (uint16_t)gyro[2];
|
||||
|
||||
format_data(imu_bin_buffer, "rsp:", ssp_data,12);
|
||||
printf("Tp%d,%d,%d,%d,%d,%d\r\n\r\n", accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
|
||||
dr_binary_tx_safe(imu_bin_buffer,8);
|
||||
if(custom_add_data==true)
|
||||
{
|
||||
|
||||
if(custom_add_data==true) {
|
||||
custom_add_data = false;
|
||||
}
|
||||
else{
|
||||
//data_tx_handler(ble_tx_buffer);
|
||||
else {
|
||||
//data_tx_handler(ble_tx_buffer);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -544,7 +542,7 @@ int imu_read_direct(void)
|
||||
DBG_PRINTF("[IMU] A:%d,%d,%d G:%d,%d,%d\r\n",
|
||||
accel[0], accel[1], accel[2], gyro[0], gyro[1], gyro[2]);
|
||||
|
||||
/* BLE 전송용 데이터 패킹: "rsp:" 태그 + 6축 데이터(12바이트) */
|
||||
/* 데이터 패킹 */
|
||||
ssp_data[0] = (uint16_t)accel[0];
|
||||
ssp_data[1] = (uint16_t)accel[1];
|
||||
ssp_data[2] = (uint16_t)accel[2];
|
||||
@@ -552,8 +550,19 @@ int imu_read_direct(void)
|
||||
ssp_data[4] = (uint16_t)gyro[1];
|
||||
ssp_data[5] = (uint16_t)gyro[2];
|
||||
|
||||
format_data(imu_bin_buffer, "rsp:", ssp_data, 12);
|
||||
dr_binary_tx_safe(imu_bin_buffer, 8);
|
||||
if (info4 == true) {
|
||||
/* info4 모드: 전역 배열에 저장 (mbb?에서 rbb: 패킷으로 일괄 전송) */
|
||||
info_imu[0] = ssp_data[0];
|
||||
info_imu[1] = ssp_data[1];
|
||||
info_imu[2] = ssp_data[2];
|
||||
info_imu[3] = ssp_data[3];
|
||||
info_imu[4] = ssp_data[4];
|
||||
info_imu[5] = ssp_data[5];
|
||||
} else {
|
||||
/* 일반 모드: "rsp:" 태그로 BLE 즉시 전송 */
|
||||
format_data(imu_bin_buffer, "rsp:", ssp_data, 12);
|
||||
dr_binary_tx_safe(imu_bin_buffer, 8);
|
||||
}
|
||||
|
||||
/* IMU 슬립 모드: PWR_MGMT0 = 0x00 → 가속도/자이로 모두 OFF (전력 절감) */
|
||||
{
|
||||
|
||||
@@ -278,7 +278,7 @@ char HW_NO[HW_NO_LENGTH]; /* 하드웨어 번호 (FDS
|
||||
bool bond_data_delete; /* 본딩 데이터 삭제 요청 플래그 */
|
||||
uint32_t m_life_cycle; /* 디바이스 수명 사이클 카운터 */
|
||||
uint8_t resetCount = 0; /* 통신 타임아웃 카운터 (리셋 감지용) */
|
||||
bool info4; /* 추가 정보(배터리/온도/IMU) 포함 측정 플래그 */
|
||||
bool info4; /* 센서 측정 정보(배터리/IMU/온도) 포함 측정 플래그 */
|
||||
uint8_t m_reset_status; /* 리셋 상태 코드 (1=정상, 2=SW리셋, 5=보안리셋, 10=본딩완료) */
|
||||
|
||||
/*==============================================================================
|
||||
@@ -318,10 +318,13 @@ static void power_hold_init(void)
|
||||
*/
|
||||
static void power_control_handler(on_off_cont_t device_power_st)
|
||||
{
|
||||
if (device_power_st == OFF) {
|
||||
if (device_power_st == OFF)
|
||||
{
|
||||
nrf_gpio_pin_clear(POWER_HOLD); /* P0.8 LOW → 전원 래치 해제 → 전원 차단 */
|
||||
DBG_PRINTF("[PWR] OFF\r\n");
|
||||
} else if (device_power_st == ON) {
|
||||
}
|
||||
else if (device_power_st == ON)
|
||||
{
|
||||
nrf_gpio_pin_set(POWER_HOLD); /* P0.8 HIGH → 전원 유지 */
|
||||
DBG_PRINTF("[PWR] ON\r\n");
|
||||
}
|
||||
@@ -404,7 +407,8 @@ static void load_flash_config(void)
|
||||
m_need_save_defaults = false;
|
||||
|
||||
/* 하드웨어 번호 — 비어있으면 기본값 채움 */
|
||||
if (m_config.hw_no[0] == 0 || m_config.hw_no[0] == (char)0xFF) {
|
||||
if (m_config.hw_no[0] == 0 || m_config.hw_no[0] == (char)0xFF)
|
||||
{
|
||||
memset(m_config.hw_no, 0, HW_NO_LENGTH);
|
||||
memcpy(m_config.hw_no, HARDWARE_VERSION, strlen(HARDWARE_VERSION));
|
||||
DBG_PRINTF("[CFG] HW empty, set default: %s\r\n", HARDWARE_VERSION);
|
||||
@@ -412,7 +416,8 @@ static void load_flash_config(void)
|
||||
}
|
||||
|
||||
/* 시리얼 번호 — 비어있으면 기본값 채움 */
|
||||
if (m_config.serial_no[0] == 0 || m_config.serial_no[0] == (char)0xFF) {
|
||||
if (m_config.serial_no[0] == 0 || m_config.serial_no[0] == (char)0xFF)
|
||||
{
|
||||
memset(m_config.serial_no, 0, SERIAL_NO_LENGTH);
|
||||
memcpy(m_config.serial_no, FIRMWARE_SERIAL_NO, strlen(FIRMWARE_SERIAL_NO));
|
||||
DBG_PRINTF("[CFG] S/N empty, set default: %s\r\n", FIRMWARE_SERIAL_NO);
|
||||
@@ -472,7 +477,8 @@ static void PM_s(void * p_context)
|
||||
UNUSED_PARAMETER(p_context);
|
||||
APP_ERROR_CHECK(app_timer_stop(m_PM_timer_id));
|
||||
|
||||
if (m_reset_status == 5) {
|
||||
if (m_reset_status == 5)
|
||||
{
|
||||
DBG_PRINTF("[PM] Kill\r\n");
|
||||
sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
|
||||
}
|
||||
@@ -628,7 +634,8 @@ static void nus_data_handler(ble_nus_evt_t * p_evt)
|
||||
DBG_PRINTF("[NUS] RX len=%d\r\n", p_evt->params.rx_data.length);
|
||||
|
||||
/* 콜백에서는 복사만 하고, 메인 루프에서 처리 */
|
||||
if (p_evt->params.rx_data.length <= BLE_NUS_MAX_DATA_LEN) {
|
||||
if (p_evt->params.rx_data.length <= BLE_NUS_MAX_DATA_LEN)
|
||||
{
|
||||
memcpy((void *)pending_cmd_buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
|
||||
pending_cmd_len = p_evt->params.rx_data.length;
|
||||
}
|
||||
|
||||
@@ -215,16 +215,11 @@ void main_loop(void * p_context) /* For x ms */
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* For System Control */
|
||||
/* ---- 시스템 제어 이벤트 처리 ---- */
|
||||
|
||||
|
||||
/* 디바이스 전원 OFF 처리 */
|
||||
if(go_device_power_off == true){
|
||||
main_timer_stop(); /* 타이머 정지 */
|
||||
|
||||
DBG_PRINTF("Off main_timer\r\n");
|
||||
device_power_off(); /* 디바이스 전원 OFF 실행 */
|
||||
}
|
||||
@@ -232,21 +227,14 @@ void main_loop(void * p_context) /* For x ms */
|
||||
/* 슬립 모드 진입 처리 */
|
||||
if(go_sleep_mode_enter == true){
|
||||
main_timer_stop(); /* 타이머 정지 */
|
||||
|
||||
DBG_PRINTF("sleep main timer\r\n");
|
||||
|
||||
|
||||
sleep_mode_enter(); /* 슬립 모드 진입 실행 */
|
||||
}
|
||||
|
||||
/* NVIC 시스템 리셋 처리 */
|
||||
if(go_NVIC_SystemReset == true) {
|
||||
|
||||
|
||||
|
||||
main_timer_stop(); /* 타이머 정지 */
|
||||
|
||||
NVIC_SystemReset(); /* ARM Cortex-M4 시스템 리셋 */
|
||||
NVIC_SystemReset(); /* ARM Cortex-M4 시스템 리셋 */
|
||||
}
|
||||
}
|
||||
|
||||
@@ -254,7 +242,7 @@ void main_loop(void * p_context) /* For x ms */
|
||||
/**
|
||||
* @brief 메인 루프 타이머 시작
|
||||
*
|
||||
* 싱글샷 모드로 MAIN_LOOP_INTERVAL(10ms 또는 80ms) 후 main_loop()를 호출한다.
|
||||
* 싱글샷 모드로 MAIN_LOOP_INTERVAL(10ms 또는 80ms) 후 main_loop()를 호출
|
||||
*/
|
||||
void main_timer_start(void)
|
||||
{
|
||||
@@ -264,7 +252,7 @@ void main_timer_start(void)
|
||||
/**
|
||||
* @brief 지정된 간격(ms)으로 메인 루프 타이머 시작
|
||||
*
|
||||
* IMU 연속 스트리밍 등 기본 간격과 다른 주기가 필요할 때 사용.
|
||||
* IMU 연속 스트리밍 등 기본 간격과 다른 주기가 필요할 때 사용
|
||||
*/
|
||||
void main_timer_start_ms(uint32_t interval_ms)
|
||||
{
|
||||
@@ -282,8 +270,8 @@ void main_timer_stop(void)
|
||||
/**
|
||||
* @brief 메인 루프 타이머 초기화 (앱 시작 시 1회 호출)
|
||||
*
|
||||
* 싱글샷 모드 타이머를 생성하고, 콜백으로 main_loop()를 등록한다.
|
||||
* 싱글샷이므로 매 호출마다 main_timer_start()로 수동 재시작해야 한다.
|
||||
* 싱글샷 모드 타이머를 생성하고, 콜백으로 main_loop()를 등록
|
||||
* 싱글샷이므로 매 호출마다 main_timer_start()로 수동 재시작해야 함
|
||||
*/
|
||||
void main_timer_init(void)
|
||||
{
|
||||
|
||||
@@ -7,11 +7,11 @@
|
||||
******************************************************************************/
|
||||
|
||||
/*******************************************************************************
|
||||
* [한국어 설명] PWM 펄스 생성기
|
||||
* PWM 펄스 생성기
|
||||
*
|
||||
* === 현재 상태 ===
|
||||
* SKIP_PWM 매크로가 정의되어 있어 PWM 기능이 비활성화됨.
|
||||
* init/start/stop 함수는 모두 Stub(빈 껍데기) 구현으로,
|
||||
* init/start/stop 함수는 모두 Stub으로,
|
||||
* 로그만 출력하고 실제 PWM 동작은 하지 않는다.
|
||||
* 빌드 호환성을 위해 함수 인터페이스만 유지.
|
||||
*
|
||||
|
||||
@@ -9,9 +9,8 @@
|
||||
/*******************************************************************************
|
||||
* [모듈 개요] TMP235-Q1 아날로그 온도센서 드라이버
|
||||
*
|
||||
* TMP235-Q1은 온도에 비례하는 아날로그 전압(Vout)을 출력하는 센서이다.
|
||||
* nRF52840 SAADC의 AIN3 채널로 Vout을 읽고, mV로 변환한 뒤
|
||||
* 온도(°C)로 계산한다.
|
||||
* TMP235-Q1은 온도에 비례하는 아날로그 전압(Vout)을 출력하는 센서
|
||||
* nRF52840 SAADC의 AIN3 채널로 Vout을 읽고, mV로 변환한 뒤 온도(°C)로 계산
|
||||
*
|
||||
* 온도 계산 공식 (구간별 선형 보간):
|
||||
* - Vout <= 1500mV (0~100°C): Ta = (Vout - 500) / 10.0
|
||||
@@ -61,13 +60,17 @@
|
||||
static nrf_saadc_value_t adc_buf;
|
||||
extern char ble_tx_buffer[BLE_NUS_MAX_DATA_LEN];
|
||||
extern uint8_t ble_bin_buffer[BLE_NUS_MAX_DATA_LEN] ;
|
||||
|
||||
/* 현재 명령 소스: CMD_UART 또는 CMD_BLE */
|
||||
extern which_cmd_t cmd_type_t;
|
||||
|
||||
/* info4: 전체 센서 데이터 수집 모드 플래그 */
|
||||
extern bool info4; //cmd_parse
|
||||
extern bool info4; // main.c
|
||||
|
||||
/* 온도 측정 순서 제어 플래그 */
|
||||
extern bool go_temp; //cmd_parse
|
||||
/* info4 모드에서 온도값을 임시 저장 (°C x 100, 정수 표현) */
|
||||
extern bool go_temp; // main_timer.c
|
||||
|
||||
/* info4 모드에서 온도값 임시 저장 (°C x 100, 정수 표현) */
|
||||
volatile uint16_t info_temp; //48_C
|
||||
extern bool motion_raw_data_enabled;
|
||||
|
||||
@@ -87,9 +90,9 @@ extern bool motion_raw_data_enabled;
|
||||
*/
|
||||
void tmp235_voltage_handler(nrf_drv_saadc_evt_t const * p_event) /* TMP325 Vout reading */
|
||||
{
|
||||
|
||||
float led_temp; /* 계산된 온도 (°C, 부동소수점) */
|
||||
uint16_t led_temp_16; /* BLE 전송용 온도 (°C x 100, 정수) */
|
||||
|
||||
if (p_event->type == NRF_DRV_SAADC_EVT_DONE)
|
||||
{
|
||||
nrf_saadc_value_t adc_result;
|
||||
@@ -113,50 +116,50 @@ void tmp235_voltage_handler(nrf_drv_saadc_evt_t const * p_event) /* TMP325 Vout
|
||||
* 100~125°C 구간: 기울기 10.1 mV/°C
|
||||
* 125~150°C 구간: 기울기 10.6 mV/°C
|
||||
*/
|
||||
if(tmp235_voltage_in_milli_volts <= 1500) {
|
||||
if(tmp235_voltage_in_milli_volts <= 1500)
|
||||
{
|
||||
/* 0~100°C: Ta = (Vout - 500mV) / 10.0 mV/°C */
|
||||
led_temp = (tmp235_voltage_in_milli_volts - 500.0f) / 10.0f + 0.0f;
|
||||
}else if(tmp235_voltage_in_milli_volts <= 1750) {
|
||||
}
|
||||
else if(tmp235_voltage_in_milli_volts <= 1750)
|
||||
{
|
||||
/* 100~125°C: 기울기가 10.1로 약간 증가 */
|
||||
led_temp = (tmp235_voltage_in_milli_volts - 1500.0f) / 10.1f + 100.0f;
|
||||
}else if(tmp235_voltage_in_milli_volts <= 2000) {
|
||||
}
|
||||
else if(tmp235_voltage_in_milli_volts <= 2000)
|
||||
{
|
||||
/* 125~150°C: 기울기가 10.6으로 더 증가 */
|
||||
led_temp = (tmp235_voltage_in_milli_volts - 1752.5f) / 10.6f + 125.0f;
|
||||
}else {
|
||||
}
|
||||
else
|
||||
{
|
||||
/* 150°C 초과 — 센서 측정 범위 벗어남 */
|
||||
DBG_PRINTF("ERR!!! Temprature is over 150c\r\n");
|
||||
}
|
||||
|
||||
/* info4 모드: 온도값을 정수(°C x 100)로 저장 (예: 36.50°C → 3650) */
|
||||
if (info4 == true){
|
||||
|
||||
if (info4 == true)
|
||||
{
|
||||
info_temp =(uint16_t)(led_temp*100);
|
||||
|
||||
}
|
||||
/* UART 모드: 소수점 2자리까지 텍스트로 출력 */
|
||||
else if(cmd_type_t == CMD_UART) {
|
||||
else if(cmd_type_t == CMD_UART)
|
||||
{
|
||||
DBG_PRINTF("To%.2f\r\n\r\n",led_temp);
|
||||
}
|
||||
/* BLE 모드: °C x 100 정수를 "rso:" 헤더로 바이너리 전송 */
|
||||
} else if(cmd_type_t == CMD_BLE) {
|
||||
led_temp_16 = (uint16_t)(led_temp*100);
|
||||
single_format_data(ble_bin_buffer, "rso:", led_temp_16);
|
||||
else if(cmd_type_t == CMD_BLE)
|
||||
{
|
||||
led_temp_16 = (uint16_t)(led_temp*100);
|
||||
single_format_data(ble_bin_buffer, "rso:", led_temp_16);
|
||||
|
||||
dr_binary_tx_safe(ble_bin_buffer,3);
|
||||
dr_binary_tx_safe(ble_bin_buffer,3);
|
||||
|
||||
// sprintf(ble_tx_buffer, "To%.2f\r\n",led_temp);
|
||||
// data_tx_handler(ble_tx_buffer);
|
||||
}
|
||||
}
|
||||
|
||||
/* info4 모드: 온도 측정 완료 → 다음 단계(IMU 측정)로 전환 */
|
||||
if (info4 == true){
|
||||
|
||||
go_temp = false; /* 온도 측정 완료 표시 */
|
||||
|
||||
|
||||
motion_raw_data_enabled = true; /* IMU 데이터 수집 시작 플래그 */
|
||||
main_timer_start(); /* 메인 타이머 시작 → IMU 측정 트리거 */
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -173,8 +176,7 @@ void tmp235_init(void)
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
/* AIN3 채널 설정: TMP235-Q1 Vout 핀 (싱글엔드 입력) */
|
||||
nrf_saadc_channel_config_t config =
|
||||
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN3); /* TMP235_Q1 Voltage Output Measurement */
|
||||
nrf_saadc_channel_config_t config = NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(NRF_SAADC_INPUT_AIN3); /* TMP235_Q1 Voltage Output Measurement */
|
||||
err_code = nrf_drv_saadc_channel_init(0, &config);
|
||||
APP_ERROR_CHECK(err_code);
|
||||
|
||||
@@ -197,8 +199,7 @@ void tmp235_init(void)
|
||||
*/
|
||||
void tmp235_voltage_level_meas(void)
|
||||
{
|
||||
tmp235_init();
|
||||
tmp235_init(); // init 함수에 있는 걸 그냥 여기 넣어도
|
||||
//tmp235_uninit();
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user