- 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
+16 -3
View File
@@ -791,7 +791,7 @@ dr_adc_err_t dr_adc_burst_capture_transmit(uint8_t freq_option, uint16_t delay_u
if (num_samples == 0 || num_samples > DR_ADC_ECHO_SAMPLES_MAX)
return DR_ADC_ERR_INVALID_PARAM;
if (freq_option > 9) freq_option = 0; /* Invalid -> default 1.8MHz */
if (cycles < 3 || cycles > 9) cycles = 5; /* Valid range: 3~9, default 5 */
if (cycles < 3 || cycles > 7) cycles = 5; /* Valid range: 3~7, default 5 */
if (averaging == 0) averaging = 1; /* Minimum 1 */
if (averaging > 1000) averaging = 1000; /* Maximum 1000 */
if (piezo_ch >= MAA_NUM_CHANNELS) piezo_ch = 0; /* 채널 범위 검증 */
@@ -1018,7 +1018,7 @@ dr_adc_err_t dr_adc_capture_channel_only(uint8_t freq_option, uint16_t delay_us,
if (num_samples == 0 || num_samples > MAA_SAMPLES_MAX)
return DR_ADC_ERR_INVALID_PARAM;
if (freq_option > 3) freq_option = 0;
if (cycles < 3 || cycles > 9) cycles = 5;
if (cycles < 3 || cycles > 7) cycles = 5;
if (averaging == 0) averaging = 1;
if (averaging > 1000) averaging = 1000;
if (piezo_ch > (MAA_NUM_CHANNELS - 1)) piezo_ch = 0;
@@ -1448,6 +1448,13 @@ static void maa_async_send_completion(uint16_t status)
g_maa_ctx.state = MAA_ASYNC_IDLE;
ADC_LOG("maa_async: complete, status=0x%04X", status);
/* 완료 콜백 호출 (mbb? 등에서 센서 측정 체인 트리거용) */
if (g_maa_ctx.on_complete_cb) {
void (*cb)(void) = g_maa_ctx.on_complete_cb;
g_maa_ctx.on_complete_cb = NULL; /* 1회성: 재호출 방지 */
cb();
}
}
/*==============================================================================
@@ -1471,12 +1478,13 @@ dr_adc_err_t maa_async_start(uint8_t freq_option, uint16_t delay_us,
g_maa_ctx.freq_option = freq_option;
g_maa_ctx.delay_us = delay_us;
g_maa_ctx.num_samples = num_samples;
g_maa_ctx.cycles = (cycles < 3 || cycles > 9) ? 5 : cycles;
g_maa_ctx.cycles = (cycles < 3 || cycles > 7) ? 5 : cycles;
g_maa_ctx.averaging = (averaging == 0) ? 1 : ((averaging > 1000) ? 1000 : averaging);
g_maa_ctx.ble_buffer = ble_buffer;
g_maa_ctx.current_ch = 0;
g_maa_ctx.current_pkt = 0;
g_maa_ctx.data_offset = 0;
g_maa_ctx.on_complete_cb = NULL; /* 기본: 콜백 없음 (maa?) */
ADC_LOG("maa_async_start: freq=%u delay=%u samples=%u cycles=%u avg=%u",
freq_option, delay_us, num_samples, g_maa_ctx.cycles, g_maa_ctx.averaging);
@@ -1568,3 +1576,8 @@ void maa_async_set_auto_power(bool on)
g_maa_ctx.auto_powered = on;
}
void maa_async_set_on_complete(void (*cb)(void))
{
g_maa_ctx.on_complete_cb = cb;
}
+9 -2
View File
@@ -191,7 +191,7 @@ dr_adc_err_t dr_adc_measure_echo(dr_adc_echo_t *echo, const dr_adc_echo_config_t
/**
* @brief Piezo burst + Echo capture in one call
* @param cycles Number of burst cycles (3~9)
* @param cycles Number of burst cycles (3~7)
* @param delay_us Delay before capture (us)
* @param num_samples Number of samples to capture
* @param echo Pointer to echo result structure
@@ -455,6 +455,7 @@ typedef struct {
uint16_t total_packets; /**< Total packets for current channel */
uint16_t data_packets; /**< Data packets for current channel */
bool auto_powered; /**< true: 자동 전원 ON → 완료 후 OFF */
void (*on_complete_cb)(void); /**< 비동기 캡처 완료 후 호출될 콜백 (NULL이면 미사용) */
} maa_async_ctx_t;
/**
@@ -466,7 +467,7 @@ typedef struct {
* @param freq_option Frequency: 0=1.8MHz, 1=2.1MHz, 2=2.0MHz, 3=1.7MHz
* @param delay_us Capture delay (us)
* @param num_samples Samples per channel (1~200)
* @param cycles Burst cycles (3~9)
* @param cycles Burst cycles (3~7)
* @param averaging Averaging count (1~1000)
* @param ble_buffer Working buffer (>= 240 bytes)
* @return dr_adc_err_t DR_ADC_OK if started successfully
@@ -507,5 +508,11 @@ void maa_async_abort(void);
*/
void maa_async_set_auto_power(bool on);
/**
* @brief
* raa: + OFF . NULL이면 .
*/
void maa_async_set_on_complete(void (*cb)(void));
#endif /* DR_ADC121S051_H */
+176 -65
View File
@@ -16,10 +16,10 @@
* - CRC16: g_plat.crc_check가 true일 2
*
* :
* 1) dr_cmd_parser()
* 2) dr_parse_cmd() CRC + TAG/
* 1) dr_cmd_parser()
* 2) dr_parse_cmd() CRC + TAG/
* 3) dr_cmd_dispatch() (g_cmd_table)
* 4) Cmd_xxx() BLE
* 4) Cmd_xxx() BLE
*/
#include "parser.h"
@@ -57,7 +57,7 @@ extern void dr_sd_delay_ms(uint32_t ms); /* SoftDevice 호환 딜레이 (BLE 스
/* FDS(Flash Data Storage) 설정 관련 */
#include "fstorage.h"
extern char SERIAL_NO[12]; /* 시리얼 넘버 (12자 ASCII, FDS에 저장) */
extern char SERIAL_NO[12]; /* 시리얼 넘버 (12자 ASCII, FDS에 저장) */
extern char HW_NO[12]; /* 하드웨어 넘버 (12자 ASCII, FDS에 저장) */
extern char m_static_passkey[6]; /* BLE 정적 패스키 (6자리 숫자 문자열) */
extern uint32_t m_life_cycle; /* 디바이스 수명 카운터 (FDS에 영구 저장) */
@@ -80,13 +80,18 @@ extern bool con_single; /* 단일 연결 모드 플래그 */
extern bool lock_check; /* 보안 잠금 상태 플래그 */
extern bool info4; /* true: 추가 정보(배터리/온도/IMU) 포함 측정 */
extern bool info4; /* true: 센서값을 전역 변수에 저장 (BLE 전송 안 함) */
extern bool ble_got_new_data; /* true: BLE로 새 데이터 수신됨 (처리 대기) */
extern bool go_batt; /* true: 배터리 측정 요청 플래그 */
extern bool motion_data_once; /* true: IMU 1회 측정, false: 연속 측정 */
extern bool motion_raw_data_enabled;/* true: IMU 원시 데이터 전송 활성화 */
extern int imu_read_direct(void); /* IMU 레지스터 직접 읽기 + BLE 전송 */
/* info4 모드 센서값 저장 변수 (mbb? rbb: 패킷 조립용) */
extern volatile uint16_t info_batt; /* 배터리 전압 (mV) */
extern volatile uint16_t info_temp; /* 온도 (°C x 100) */
extern volatile uint16_t info_imu[6]; /* IMU 6축 (accel XYZ + gyro XYZ) */
extern void pressure_all_level_meas(void); /* 압력 센서 전체 측정 */
extern void battery_timer_stop(void); /* 배터리 타이머 중지 */
extern void main_timer_start(void); /* 메인 타이머 시작 (주기적 측정 트리거) */
@@ -108,7 +113,7 @@ extern config_data_t m_config; /* 전체 설정 구조체 (FDS 저장 대
#define AGC_GAIN_SW(x) do { if(x) nrf_gpio_pin_set(GAIN_SW_PIN); else nrf_gpio_pin_clear(GAIN_SW_PIN); } while(0)
/* 피에조 초음파 트랜스듀서 제어 함수 */
/* ---- 피에조 관련 제어 함수 ---- */
extern void dr_piezo_power_on( void ); /* 피에조 회로 전원 ON (TX/RX 보드) */
extern void dr_piezo_power_off( void ); /* 피에조 회로 전원 OFF */
extern bool dr_piezo_is_power_on( void ); /* 피에조 전원 상태 확인 */
@@ -117,6 +122,7 @@ extern void dr_piezo_burst_sw_18mhz(uint8_t cycles); /* 1.8MHz 버스트 펄스
extern void dr_piezo_burst_sw_20mhz(uint8_t cycles); /* 2.0MHz 버스트 펄스 발생 */
extern void dr_piezo_burst_sw_17mhz(uint8_t cycles); /* 1.7MHz 버스트 펄스 발생 */
/* ---- 전역 변수 정의 (헤더에서 extern 선언) ---- */
dr_platform_if_t g_plat = { 0, 0, 0 };
/* 플랫폼 인터페이스 구조체:
@@ -126,10 +132,11 @@ dr_platform_if_t g_plat = { 0, 0, 0 };
bool g_log_enable = false;
/* 디버그 로그 전역 활성화 플래그 (g_plat.log와 함께 사용) */
/* ---- 내부 상수/구조체 정의 ---- */
/* ---- 내부 상수/구조체 정의 ---- */
#define DR_MAX_DATA 128 /* TAG 이후 데이터의 최대 바이트 수 */
/* 파싱된 명령 구조체 - 수신 패킷을 TAG와 데이터로 분리한 결과 */
typedef struct {
char tag[5]; /* 명령 TAG 문자열 (예: "sta?") 4글자 + '\0' */
@@ -328,8 +335,8 @@ static bool dr_parse_cmd(const uint8_t *buffer, uint8_t length, ParsedCmd *out)
* BLE
*
* A.
* - OFF (msq? / rsq:) :
* - (mss? / rss:) :
* - OFF (msq? / rsq:)
* - (mss? / rss:)
* - (msr? / rsr:) :
* - GPIO ( , cmd? / rmd:)
*
@@ -339,21 +346,22 @@ static bool dr_parse_cmd(const uint8_t *buffer, uint8_t length, ParsedCmd *out)
* - (mrs? / rrs:)
* - (mws? / rws:)
* - (mfv? / rfv:)
* - (mqz? / rqz:) : , ( )
* - (mpz? / rpz:) :
* - (mqz? / rqz:) : ( )
* - (mpz? / rpz:)
*
* C.
* - (msn? / rsn:) - test용
* - IMU (msp? / rsp:) : - test용
* - IMU (msi? / rsi:) : () 1 , - test용
* - (mso? / rso:) : - test용
* - (mso? / rso:) - test용
*
* D. Piezo
* - TX/RX (mpa? / rpa:)
* - TX/RX (mpb? / rpb:)
* - TX/RX (mpa? / rpa:) - test용
* - TX/RX (mpb? / rpb:) - test용
* - Burst (mpc? / rpc:) - test용
* - Burst + ADC -> echo capture (mec? / reb: -> red: -> ree:)
* - Burst + ADC -> echo capture (maa? / reb: -> red: -> raa:) : , = 4
* - Burst + ADC -> echo capture (mec? / reb: -> red: -> ree:) : TX/RX Active -> -> TX/RX Sleep
* - Burst + ADC -> echo capture (maa? / reb: -> red: -> raa:) : TX/RX Active -> -> TX/RX Sleep
* - Burst + ADC -> echo capture (mbb? / reb: -> red: -> raa:) + (, IMU, ) : TX/RX Active -> -> TX/RX Sleep (NEW!)
*
*
* - / : TX /
@@ -364,7 +372,6 @@ static bool dr_parse_cmd(const uint8_t *buffer, uint8_t length, ParsedCmd *out)
* - ADC
*============================================================================*/
/*==============================================================================
*
* - : 1=, 0=/
@@ -399,7 +406,8 @@ static int Cmd_mpa(const ParsedCmd *cmd); /* mpa? 피에조 TX/RX 회로 활
static int Cmd_mpb(const ParsedCmd *cmd); /* mpb? 피에조 TX/RX 회로 비활성화 (전원 OFF) */
static int Cmd_mpc(const ParsedCmd *cmd); /* mpc? 피에조 버스트 발생 (주파수/사이클 제어) */
static int Cmd_mec(const ParsedCmd *cmd); /* mec? 피에조 버스트 + 에코 캡처 (16비트 원시) */
static int Cmd_maa(const ParsedCmd *cmd); /* maa? 4채널 전체 캡처 (비동기 전송) */
static int Cmd_maa(const ParsedCmd *cmd); /* maa? 6채널 전체 캡처 (비동기 전송) */
static int Cmd_mbb(const ParsedCmd *cmd); /* mbb? 6채널 캡처 + 센서 측정 (배터리 + 온도 + IMU) */
/* ---- 명령 테이블 ---- */
@@ -411,42 +419,38 @@ typedef struct {
int (*handler)(const ParsedCmd *cmd); /* 핸들러 함수 포인터 (1=성공, 0=실패) */
} CmdEntry;
/* 전체 명령 테이블 - 수신된 TAG와 순차 비교하여 일치하는 핸들러 호출
*
* enabled=false인
* TAG에 (: mcj?=scj?, msn?=ssn?) ->
*/
/* 전체 명령 테이블 - 수신된 TAG와 순차 비교하여 일치하는 핸들러 호출 */
static CmdEntry g_cmd_table[] = {
/* A. 디바이스 상태 제어 */
{ "msq?", true, Cmd_msq },
{ "mss?", true, Cmd_mss },
#if FEATURE_SECURE_CONNECTION
{ "msr?", true, Cmd_msr },
#endif
{ "cmd?", true, Cmd_cmd },
{ "cmd?", true, Cmd_cmd },
/* C. 디바이스 정보 읽기, 쓰기 */
{ "mwh?", true, Cmd_mwh },
{ "mws?", true, Cmd_mws },
{ "mrh?", true, Cmd_mrh },
{ "mrs?", true, Cmd_mrs },
{ "mpz?", true, Cmd_mpz },
{ "mqz?", true, Cmd_mqz },
{ "mwh?", true, Cmd_mwh },
{ "mws?", true, Cmd_mws },
{ "mrh?", true, Cmd_mrh },
{ "mrs?", true, Cmd_mrs },
{ "mpz?", true, Cmd_mpz },
{ "mqz?", true, Cmd_mqz },
{ "mfv?", true, Cmd_mfv },
/* D. 각종 센서 측정 */
{ "msn?", true, Cmd_msn },
{ "msn?", true, Cmd_msn },
{ "mso?", true, Cmd_mso },
{ "msp?", true, Cmd_msp },
{ "msp?", true, Cmd_msp },
{ "msi?", true, Cmd_msi },
/* E. Piezo 초음파 측정 */
{ "mpa?", true, Cmd_mpa },
{ "mpb?", true, Cmd_mpb },
{ "mpc?", true, Cmd_mpc },
{ "mec?", true, Cmd_mec },
{ "maa?", true, Cmd_maa },
{ "mpa?", true, Cmd_mpa },
{ "mpb?", true, Cmd_mpb },
{ "mpc?", true, Cmd_mpc },
{ "mec?", true, Cmd_mec },
{ "maa?", true, Cmd_maa },
{ "mbb?", true, Cmd_mbb },
};
/* 명령 테이블 엔트리 수 (컴파일 타임 계산) */
@@ -512,7 +516,6 @@ static int dr_cmd_dispatch(const ParsedCmd *cmd)
int dr_cmd_parser(const uint8_t *buf, uint8_t len)
{
ParsedCmd cmd;
g_plat.log("parser!!!!!!!!\r\n");
if (g_plat.log) g_plat.log("[PARSER] in len=%u crc=%u\r\n", len, g_plat.crc_check);
@@ -538,9 +541,6 @@ int dr_cmd_parser(const uint8_t *buf, uint8_t len)
*
*============================================================================*/
/* 2026-03-17: mta?, mtr? 삭제 */
/* msn? - 배터리 잔량 ADC 측정
* : battery_level_meas() BLE */
static int Cmd_msn(const ParsedCmd *cmd)
@@ -553,14 +553,9 @@ static int Cmd_msn(const ParsedCmd *cmd)
return 1;
}
/* 2026-03-17: mpn? 삭제 (압력센서 미탑재) */
/* mso? - TMP235-Q1 온도 센서 전압 측정
* SAADC로 TMP235 BLE로 .
* tmp235_q1.c의 . */
* SAADC로 TMP235 BLE로
* tmp235_q1.c의 */
static int Cmd_mso(const ParsedCmd *cmd)
{
(void)cmd;
@@ -675,8 +670,6 @@ static int Cmd_mss(const ParsedCmd *cmd)
return 1;
}
/* 2026-03-17: mst? 삭제 */
/* mfv? - 펌웨어 버전 읽기
*
* : "rfv:" + 12 ASCII (DR_DEVICE_VERSION)
@@ -748,7 +741,7 @@ static int Cmd_mpb(const ParsedCmd *cmd)
* (/)
*
* (Little-Endian uint16 x 3):
* word 0: cycles (3~9, =5) -
* word 0: cycles (3~7, =5) -
* word 1: freq_option (=1) -
* 0=1.8MHz, 1=2.1MHz(), 2=2.0MHz, 3=1.7MHz, 4=2.2MHz
* word 2: piezo_ch (0~7, =0) -
@@ -785,8 +778,8 @@ static int Cmd_mpc(const ParsedCmd *cmd)
cycles, freq_option, freq_str, piezo_ch);
}
/* 사이클 범위 검증: 3~9 유효 */
if (cycles < 3 || cycles > 9) {
/* 사이클 범위 검증: 3~7 유효 */
if (cycles < 3 || cycles > 7) {
dr_ble_return_1("rpc:", 2); /* 에러 응답: 범위 초과 */
return 1;
}
@@ -840,7 +833,7 @@ static int Cmd_mec(const ParsedCmd *cmd)
{
uint16_t freq_option = 0; /* 기본 1.8MHz */
uint16_t delay_us = 20; /* 기본 20us 딜레이 */
uint16_t num_samples = 140; /* 기본 140샘플 (약 20cm 거리) */
uint16_t num_samples = 140; /* 기본 100샘플 */
uint16_t cycles = 5; /* 기본 5사이클 (유효: 3~7) */
uint16_t averaging = 1; /* 기본 1 (평균화 없음), 최대 1000 */
uint16_t piezo_ch = 0; /* 기본 채널 0 (유효: 0~7) */
@@ -979,11 +972,7 @@ static int Cmd_cmd(const ParsedCmd *cmd)
*
* : 0xA000 (vA) = 4
*/
#define MAA_FREQ_OPTION 1 /* 기본 2.1MHz */
#define MAA_DELAY_US 10 /* 버스트 후 10us 딜레이 */
#define MAA_NUM_SAMPLES 100 /* 140샘플 (약 25cm 거리) */
#define MAA_CYCLES 7 /* 7사이클 버스트 */
#define MAA_AVERAGING 5 /* 5회 평균화 */
/* 피에조 캡처 파라미터: FDS(m_config)에서 로드, 앱에서 변경 가능 */
static int Cmd_maa(const ParsedCmd *cmd)
{
@@ -1023,11 +1012,11 @@ static int Cmd_maa(const ParsedCmd *cmd)
* - auto_powered=true면 OFF
*=======================================================================*/
err = maa_async_start(
(uint8_t)MAA_FREQ_OPTION,
MAA_DELAY_US,
MAA_NUM_SAMPLES,
(uint8_t)MAA_CYCLES,
(uint16_t)MAA_AVERAGING,
m_config.piezo_freq_option,
m_config.piezo_delay_us,
m_config.piezo_num_samples,
m_config.piezo_cycles,
m_config.piezo_averaging,
ble_bin_buffer
);
@@ -1049,6 +1038,128 @@ static int Cmd_maa(const ParsedCmd *cmd)
}
/**
* @brief mbb? -
*
* raa: + OFF
* info4 , rbb:
* SAADC () dr_sd_delay_ms()
*
* : IMU ( ON)
* : rbb: [mV(2)] [IMU 6(12)] [°Cx100(2)] = 20
*/
static void all_sensors(void)
{
if (g_plat.log) g_plat.log("[Cmd_mbb] measuring sensors\r\n");
info4 = true; /* 센서값을 전역 변수에 저장 (BLE 전송 안 함) */
/* 1) 배터리 전압 측정 → info_batt에 저장 */
battery_level_meas();
dr_sd_delay_ms(50); /* SAADC 콜백 완료 대기 */
/* 2) IMU 6축 단발 읽기 → info_imu[6]에 저장 */
hw_i2c_init_once();
imu_read_direct();
/* 3) 온도 측정 → info_temp에 저장 (TMP235는 피에조 전원 필요) */
if (!dr_piezo_is_power_on())
{
if (g_plat.log) g_plat.log("[Cmd_mbb] TX/RX Sleep -> Active for TEMP\r\n");
dr_piezo_system_init();
}
tmp235_voltage_level_meas();
dr_sd_delay_ms(50); /* SAADC 콜백 완료 대기 */
info4 = false;
/* rbb: 패킷 조립 및 전송 : [TAG 4B] [배터리 2B] [IMU 12B] [온도 2B] = 20바이트 = 10워드 */
uint8_t *buf = ble_bin_buffer;
buf[0] = 'r'; buf[1] = 'b'; buf[2] = 'b'; buf[3] = ':';
buf[4] = (uint8_t)(info_batt & 0xFF);
buf[5] = (uint8_t)(info_batt >> 8);
for (int i = 0; i < 6; i++) {
buf[6 + i * 2] = (uint8_t)(info_imu[i] & 0xFF);
buf[6 + i * 2 + 1] = (uint8_t)(info_imu[i] >> 8);
}
buf[18] = (uint8_t)(info_temp & 0xFF);
buf[19] = (uint8_t)(info_temp >> 8);
dr_binary_tx_safe(buf, 10); /* 20바이트 = 10워드 */
if (g_plat.log) g_plat.log("[Cmd_mbb] rbb: sent (batt=%u temp=%u)\r\n", info_batt, info_temp);
}
/**
* @brief mbb? - 6 + (//IMU)
*
* (rbb:) 6 (reb:/red:/raa:) TX/RX OFF
*
* : mode (uint16, word 0) - mode=0
*
* :
* 1) : rbb: [(2) + IMU 6(12) + (2)]
* 2) (CH0~CH5): reb: [] red: [...]
* 3) : raa: []
*/
static int Cmd_mbb(const ParsedCmd *cmd)
{
uint16_t mode = 0;
dr_adc_err_t err;
(void)dr_get_u16(cmd, 0, &mode);
if (mode > 0)
{
dr_ble_return_1("raa:", 0xFFFF);
return 1;
}
all_sensors();
if (maa_async_is_busy())
{
dr_ble_return_1("raa:", 0xFFFE);
return 1;
}
/* 피에조 전원: OFF일 경우 ON → 완료 후 OFF */
if (!dr_piezo_is_power_on())
{
if (g_plat.log) g_plat.log("[Cmd_mbb] TX/RX Sleep -> Active\r\n");
dr_piezo_system_init();
}
/* 비동기 6채널 캡처 시작 (m_config 파라미터 사용) */
err = maa_async_start(
m_config.piezo_freq_option,
m_config.piezo_delay_us,
m_config.piezo_num_samples,
m_config.piezo_cycles,
m_config.piezo_averaging,
ble_bin_buffer
);
if (err != DR_ADC_OK)
{
if (g_plat.log) g_plat.log("[Cmd_mbb] start failed err=%d\r\n", err);
single_format_data(ble_bin_buffer, "raa:", (uint16_t)(0xFF00 | err));
dr_binary_tx_safe(ble_bin_buffer, 3);
dr_piezo_power_off();
return 1;
}
/* 완료 시 무조건 전원 OFF (전체 측정 사이클) */
maa_async_set_auto_power(true);
return 1;
}
/*==============================================================================
* : HW/ FDS /
*