md 파일 추가
This commit is contained in:
@@ -0,0 +1,197 @@
|
||||
# VesiScan BASIC — 초음파 측정 파이프라인 (Zephyr 포팅 계획)
|
||||
|
||||
## 1. 하드웨어 구성
|
||||
|
||||
| 역할 | 칩 | 핀 |
|
||||
|---|---|---|
|
||||
| 피에조 전원 | DC/DC 컨버터 (+/-20V) | PWR_EN: P1.9 |
|
||||
| TX Pulse Enable | MOSFET 드라이버 | PE: P0.25 |
|
||||
| TX 양극 출력 | MOSFET | P_OUT: P1.7 |
|
||||
| TX 음극 출력 | MOSFET | N_OUT: P1.6 |
|
||||
| TX 방전 | Dump 회로 | DMP: P1.0 |
|
||||
| 채널 선택 | 8ch 아날로그 MUX | EN_MUXA: P0.21, EN_MUXB: P0.23, SEL0: P1.10, SEL1: P0.28 |
|
||||
| Echo ADC | ADC121S051 (TI, 12-bit) | SCLK: P0.14, MISO: P0.15, CS: P0.19 |
|
||||
|
||||
### MUX 채널 매핑 (6채널 사용)
|
||||
|
||||
| CH | EN_MUXA | EN_MUXB | SEL0 | SEL1 |
|
||||
|---|---|---|---|---|
|
||||
| 0 | 1 | 0 | 0 | 0 |
|
||||
| 1 | 1 | 0 | 1 | 0 |
|
||||
| 2 | 1 | 0 | 0 | 1 |
|
||||
| 3 | 1 | 0 | 1 | 1 |
|
||||
| 4 | 0 | 1 | 1 | 1 |
|
||||
| 5 | 0 | 1 | 0 | 1 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 전체 측정 흐름
|
||||
|
||||
```
|
||||
[측정 커맨드 수신]
|
||||
│
|
||||
▼
|
||||
piezo_power_on()
|
||||
└─ PWR_EN = HIGH
|
||||
└─ 3ms 안정화 대기
|
||||
|
||||
echo_adc_init()
|
||||
└─ SPIM3 초기화 (16MHz, SPI Mode 3, CPOL=1 CPHA=1)
|
||||
└─ dummy read 1회 (ADC wake-up)
|
||||
|
||||
│
|
||||
▼
|
||||
┌─── for ch = 0 ~ 5 ───────────────────────────────────────────┐
|
||||
│ │
|
||||
│ piezo_select_channel(ch) │
|
||||
│ └─ MUX 핀 설정 │
|
||||
│ └─ 1300us settling 대기 │
|
||||
│ │
|
||||
│ [averaging 횟수만큼 반복] (기본 3회) │
|
||||
│ piezo_burst_sw(cycles) ← SW NOP 버스트 │
|
||||
│ ├─ __disable_irq() │
|
||||
│ ├─ PE ON │
|
||||
│ ├─ for i in cycles: │
|
||||
│ │ P_OUT=HIGH, N_OUT=LOW (NOP × 14) ┐ 2.1MHz │
|
||||
│ │ P_OUT=LOW, N_OUT=HIGH (NOP × 9) ┘ │
|
||||
│ ├─ DMP 펄스 (500ns) │
|
||||
│ ├─ PE OFF │
|
||||
│ └─ __enable_irq() │
|
||||
│ │
|
||||
│ delay_us 대기 (기본 20us) ← 버스트 → ADC 시작 딜레이 │
|
||||
│ │
|
||||
│ echo_adc_capture(buf, num_samples) ← SPIM3 연속 읽기 │
|
||||
│ └─ 100샘플 × 2byte = 200byte │
|
||||
│ └─ 소요시간: ~100us (16MHz SPI) │
|
||||
│ │
|
||||
│ 샘플 합산 (averaging용) │
|
||||
│ │
|
||||
│ averaging 나눗셈 → channel_buf[ch] 저장 │
|
||||
│ │
|
||||
└───────────────────────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
BLE 전송 (채널별)
|
||||
reb: [샘플수(2B)] [raw data (200B)] + CRC16 ← 채널당 1패킷
|
||||
...
|
||||
raa: [상태(2B)] + CRC16 ← 완료 패킷
|
||||
|
||||
│
|
||||
▼
|
||||
piezo_power_off()
|
||||
└─ PE, P_OUT, N_OUT, DMP = LOW
|
||||
└─ MUX EN 핀 = LOW
|
||||
└─ PWR_EN = LOW
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 타이밍 정리
|
||||
|
||||
| 구간 | 시간 | 비고 |
|
||||
|---|---|---|
|
||||
| 전원 안정화 | 3ms | DC/DC +/-20V 안정화 |
|
||||
| MUX settling | 1.3ms | 채널 전환 후 아날로그 경로 안정화 |
|
||||
| SW 버스트 (5 cycles @ 2.1MHz) | ~2.4µs | __disable_irq() 구간 |
|
||||
| burst → ADC 딜레이 | 20µs (기본) | 에코 신호 도달 대기 |
|
||||
| ADC 캡처 (100샘플 @ 16MHz SPI) | ~100µs | 1샘플 = 16 SCLK = 1µs |
|
||||
| 채널당 총 측정 시간 (averaging 3회) | ~4.4ms + 3ms | MUX + (burst+딜레이+ADC) × 3 |
|
||||
| 6채널 전체 측정 | ~30ms | 채널 × 6 |
|
||||
|
||||
---
|
||||
|
||||
## 4. ADC121S051 SPI 프레임
|
||||
|
||||
```
|
||||
CS ────┐ ┌────
|
||||
└────────────────────┘
|
||||
|
||||
SCLK ────┐ ┌─┐ ┌─┐ ┌─┐ ┌─┐ ──── (idle HIGH, 16 clocks)
|
||||
└─┘ └─┘ └─ ... └─┘ └─┘
|
||||
|
||||
DATA ----<Z2><Z1><Z0><D11>...<D1><D0>----
|
||||
│← 3 zeros →│← 12 data bits →│
|
||||
|
||||
변환 공식: value = (raw16 >> 1) & 0x0FFF
|
||||
```
|
||||
|
||||
- SPI Mode 3: CPOL=1(idle HIGH), CPHA=1(rising edge sample)
|
||||
- 16MHz clock → 1샘플 = 16 clocks = 1µs
|
||||
- 12-bit 출력 (0 ~ 4095), VREF = 3.3V
|
||||
- 1LSB = 3300mV / 4096 ≈ 0.8mV
|
||||
|
||||
---
|
||||
|
||||
## 5. BLE 응답 패킷 포맷
|
||||
|
||||
### reb: (echo raw data)
|
||||
```
|
||||
[r][e][b][:] [num_samples H][num_samples L] [s0_H][s0_L] [s1_H][s1_L] ... [CRC_L][CRC_H]
|
||||
4 bytes 2 bytes num_samples × 2 bytes 2 bytes
|
||||
```
|
||||
- 100샘플 기준: 4 + 2 + 200 + 2 = **208 bytes**
|
||||
- BLE MTU 247byte 이내이므로 단일 패킷으로 전송 가능
|
||||
|
||||
### raa: (완료)
|
||||
```
|
||||
[r][a][a][:] [status H][status L] [CRC_L][CRC_H]
|
||||
4 bytes 2 bytes 2 bytes = 8 bytes
|
||||
```
|
||||
- status 0x0000 = 성공
|
||||
|
||||
---
|
||||
|
||||
## 6. Zephyr 구현 계획
|
||||
|
||||
### 신규 파일
|
||||
|
||||
| 파일 | 내용 |
|
||||
|---|---|
|
||||
| `src/drivers/piezo/piezo.c` | SW 버스트, MUX 제어, 전원 제어 |
|
||||
| `src/drivers/piezo/piezo.h` | 공개 API 선언 |
|
||||
| `src/drivers/echo_adc/echo_adc.c` | ADC121S051 SPIM3 드라이버 |
|
||||
| `src/drivers/echo_adc/echo_adc.h` | 공개 API 선언 |
|
||||
|
||||
### 수정 파일
|
||||
|
||||
| 파일 | 변경 내용 |
|
||||
|---|---|
|
||||
| `boards/nrf52840dk_nrf52840.overlay` | 피에조/MUX GPIO, SPI 핀 비활성화 충돌 처리 |
|
||||
| `prj.conf` | `CONFIG_NRFX_GPIOTE=y`, `CONFIG_NRFX_SPIM3=y` 추가 |
|
||||
| `CMakeLists.txt` | 신규 소스/인클루드 추가 |
|
||||
| `src/parser.c` | `maa?` 커맨드 핸들러 추가 |
|
||||
|
||||
### 기존 SDK → Zephyr 변환표
|
||||
|
||||
| nRF5 SDK | Zephyr |
|
||||
|---|---|
|
||||
| `#include "nrf_gpio.h"` | `#include <hal/nrf_gpio.h>` |
|
||||
| `#include "nrf_gpiote.h"` | `#include <hal/nrf_gpiote.h>` |
|
||||
| `#include "nrfx_spim.h"` | `#include <nrfx_spim.h>` |
|
||||
| `nrf_delay_ms(x)` | `k_msleep(x)` |
|
||||
| `nrf_delay_us(x)` | `k_busy_wait(x)` |
|
||||
| `NRF_P0->OUTSET/OUTCLR` | 동일 (레지스터 직접 접근) |
|
||||
| `__disable_irq()` / `__NOP()` | 동일 (ARM CMSIS) |
|
||||
| `NRFX_SPIM_INSTANCE(3)` | 동일 |
|
||||
|
||||
### SW 버스트 NOP 타이밍 (변경 없음)
|
||||
|
||||
CPU 64MHz → 1 NOP = 15.625ns. nRF5 SDK, Zephyr 모두 동일하므로 NOP 개수 수정 불필요.
|
||||
|
||||
| 주파수 | 반주기 | 1st half NOP | 2nd half NOP |
|
||||
|---|---|---|---|
|
||||
| 1.7 MHz | 294ns | 18 | 10 |
|
||||
| 1.8 MHz | 278ns | 17 | 11 |
|
||||
| 1.9 MHz | 263ns | 15 | 9 |
|
||||
| 2.0 MHz | 250ns | 15 | 10 |
|
||||
| 2.1 MHz | 238ns | 14 | 9 |
|
||||
| 2.2 MHz | 227ns | 13 | 8 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 구현 순서 (권장)
|
||||
|
||||
1. `piezo.c` — GPIO 초기화, MUX, 전원, SW 버스트
|
||||
2. `echo_adc.c` — SPIM3 초기화, 단일 샘플 읽기, 연속 캡처
|
||||
3. `parser.c` — `maa?` 커맨드 핸들러 (6채널 측정 → BLE 전송)
|
||||
4. 빌드 검증 및 오실로스코프로 타이밍 확인
|
||||
@@ -0,0 +1,425 @@
|
||||
# VesiScan-Basic — 시스템 전체 파이프라인
|
||||
|
||||
## 목차
|
||||
|
||||
1. [전체 동작 개요](#1-전체-동작-개요)
|
||||
2. [부팅 및 BLE 연결 흐름](#2-부팅-및-ble-연결-흐름)
|
||||
3. [커맨드/응답 테이블](#3-커맨드응답-테이블)
|
||||
4. [msp? 흐름 (1초 주기 IMU)](#4-msp-흐름-1초-주기-imu)
|
||||
5. [mbb? 흐름 (10초 주기 전체 측정)](#5-mbb-흐름-10초-주기-전체-측정)
|
||||
6. [구현 현황](#6-구현-현황)
|
||||
7. [핀 배치 전체 정리](#7-핀-배치-전체-정리)
|
||||
8. [IMU 테스트 가이드](#8-imu-테스트-가이드-msp)
|
||||
9. [다음 구현 순서](#9-다음-구현-순서)
|
||||
|
||||
---
|
||||
|
||||
## 1. 전체 동작 개요
|
||||
|
||||
```
|
||||
[앱] ──BLE NUS── [디바이스]
|
||||
│ │
|
||||
│── msp? (1초마다) ──▶ │ IMU 측정 → rsp: (accel+gyro)
|
||||
│ │
|
||||
│── mbb? (10초마다) ──▶ │ 6ch 피에조 측정 + 배터리/IMU/온도
|
||||
│ │ → rbb: (센서 번들)
|
||||
│◀── rbb: ────────────│
|
||||
│◀── reb: × 6 ────────│ (채널별 echo 데이터)
|
||||
│◀── raa: ────────────│ (완료)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 부팅 및 BLE 연결 흐름
|
||||
|
||||
```
|
||||
[부팅]
|
||||
│
|
||||
▼
|
||||
전원 버튼 2초 유지
|
||||
│
|
||||
▼
|
||||
P0.08 래치 ON (전원 자가유지)
|
||||
│
|
||||
▼
|
||||
HW 초기화
|
||||
├─ GPIO, LED
|
||||
├─ Battery ADC (SAADC AIN2)
|
||||
├─ IMU (I2C0, ICM42670P @ 0x68)
|
||||
├─ Temperature ADC (SAADC AIN3, TMP235-Q1)
|
||||
├─ [TODO] Piezo 드라이버 (GPIO + SW burst)
|
||||
└─ [TODO] Echo ADC (SPIM3, ADC121S051)
|
||||
│
|
||||
▼
|
||||
BLE 스택 초기화 (NUS)
|
||||
│
|
||||
▼
|
||||
Advertising 시작 → LED: 파란불 깜빡임
|
||||
│
|
||||
▼
|
||||
앱 연결됨 → LED: 연결 표시
|
||||
│
|
||||
▼
|
||||
앱에서 주기적 커맨드 수신
|
||||
├─ msp? (1초마다)
|
||||
└─ mbb? (10초마다)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 커맨드/응답 테이블
|
||||
|
||||
| 커맨드 | 설명 | 응답 | 주기 | 구현 상태 |
|
||||
|---|---|---|---|---|
|
||||
| `msp?` | IMU 1회 측정 | `rsp:` (accel+gyro, 12B) | 1초 | ✅ 완료 |
|
||||
| `mbb?` | 전체 측정 (센서+피에조 6ch) | `rbb:` + `reb:` ×6 + `raa:` | 10초 | ❌ 미구현 |
|
||||
| `maa?` | 피에조 6ch 단독 측정 | `reb:` ×6 + `raa:` | 수동 | ❌ 미구현 |
|
||||
| `msn?` | 배터리 전압 단독 측정 | `rsn:` (mV) | 수동 | ✅ 완료 |
|
||||
| `mls?` | LED 상태 설정 | `rls:` (state echo) | 수동 | ✅ 완료 |
|
||||
|
||||
---
|
||||
|
||||
## 4. msp? 흐름 (1초 주기 IMU)
|
||||
|
||||
```
|
||||
앱 → msp?
|
||||
│
|
||||
▼
|
||||
imu_read(accel, gyro)
|
||||
├─ GYRO_CONFIG0 = 0x09 (±2000dps, 100Hz)
|
||||
├─ ACCEL_CONFIG0 = 0x29 (±4g, 100Hz)
|
||||
├─ PWR_MGMT0 = 0x0F (low-noise ON)
|
||||
├─ 80ms 대기 (자이로 스타트업)
|
||||
├─ 0x0B부터 12바이트 읽기
|
||||
└─ PWR_MGMT0 = 0x00 (슬립)
|
||||
│
|
||||
▼
|
||||
rsp: [accel X(2)] [accel Y(2)] [accel Z(2)]
|
||||
[gyro X(2)] [gyro Y(2)] [gyro Z(2)]
|
||||
[CRC16(2)] = 18 bytes
|
||||
```
|
||||
|
||||
**구현 상태: ✅ 완료**
|
||||
- `src/drivers/imu/imu_i2c.c` — ICM42670P I2C 드라이버
|
||||
- `src/parser.c` — `msp?` 핸들러, `rsp:` 응답
|
||||
|
||||
---
|
||||
|
||||
## 5. mbb? 흐름 (10초 주기 전체 측정)
|
||||
|
||||
```
|
||||
앱 → mbb?
|
||||
│
|
||||
▼
|
||||
[Phase 1] 피에조 6채널 캡처 (타이밍 크리티컬)
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ piezo_power_on() ← PWR_EN=HIGH, 3ms 대기 │
|
||||
│ echo_adc_init() ← SPIM3 초기화 │
|
||||
│ │
|
||||
│ for ch = 0 ~ 5: │
|
||||
│ piezo_select_channel(ch) ← MUX, 1.3ms │
|
||||
│ for avg = 0 ~ 2: ← 3회 평균 │
|
||||
│ piezo_burst_sw(5) ← 2.1MHz SW burst│
|
||||
│ delay 20us │
|
||||
│ echo_adc_capture(buf, 100) ← SPIM3 │
|
||||
│ channel_data[ch] = 평균값 │
|
||||
└──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
[Phase 2] 센서 측정 (피에조 캡처 완료 후)
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ battery_read_mv() → info_batt (mV) │
|
||||
│ imu_read(accel, gyro) → info_imu[6] │
|
||||
│ temperature_read() → info_temp (°Cx100) │
|
||||
└──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
[Phase 3] BLE 전송
|
||||
┌──────────────────────────────────────────────┐
|
||||
│ rbb: [batt(2)][IMU(12)][temp(2)][CRC(2)] │
|
||||
│ = 20 bytes │
|
||||
│ │
|
||||
│ for ch = 0 ~ 5: │
|
||||
│ reb: [num_samples(2)][raw(200)][CRC(2)] │
|
||||
│ = 204 bytes per channel │
|
||||
│ │
|
||||
│ raa: [status(2)][CRC(2)] = 8 bytes │
|
||||
└──────────────────────────────────────────────┘
|
||||
│
|
||||
▼
|
||||
piezo_power_off()
|
||||
```
|
||||
|
||||
**rbb: 패킷 포맷**
|
||||
```
|
||||
[r][b][b][:] [batt_L][batt_H]
|
||||
[imu0_L][imu0_H] ... [imu5_L][imu5_H] ← accel XYZ + gyro XYZ
|
||||
[temp_L][temp_H]
|
||||
[CRC_L][CRC_H]
|
||||
= 4 + 2 + 12 + 2 + 2 = 22 bytes
|
||||
```
|
||||
|
||||
**reb: 패킷 포맷 (채널당)**
|
||||
```
|
||||
[r][e][b][:] [num_samples_H][num_samples_L]
|
||||
[s0_H][s0_L] [s1_H][s1_L] ... [s99_H][s99_L]
|
||||
[CRC_L][CRC_H]
|
||||
= 4 + 2 + 200 + 2 = 208 bytes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 구현 현황
|
||||
|
||||
### ✅ 완료
|
||||
|
||||
| 모듈 | 파일 | 기능 |
|
||||
|---|---|---|
|
||||
| BLE NUS | `src/ble/ble_service.c` | advertising, 연결, RX/TX |
|
||||
| 전원 제어 | `src/power_control.c`, `src/main.c` | 버튼 상태머신, 래치, 슬립 |
|
||||
| LED | `src/drivers/led/led_control.c` | 상태별 LED 패턴 |
|
||||
| 배터리 ADC | `src/drivers/battery/battery_adc.c` | SAADC AIN2, 주기 모니터링 |
|
||||
| IMU | `src/drivers/imu/imu_i2c.c` | ICM42670P I2C (SCL=P1.14, SDA=P1.15) |
|
||||
| 온도 센서 | `src/drivers/temperature/tmp235.c` | TMP235-Q1, SAADC AIN3 (P0.05) |
|
||||
| 파서 | `src/parser.c` | `msn?`, `mls?`, `msp?` |
|
||||
|
||||
#### SAADC 채널 공유 (배터리 ↔ 온도)
|
||||
|
||||
배터리(AIN2)와 온도(AIN3)는 nRF52840 SAADC 하나를 공유한다.
|
||||
|
||||
**nRF5 SDK에서는** 채널 전환 시 `nrfx_saadc_uninit()`을 명시적으로 호출하지 않으면 다음 `nrfx_saadc_channel_init()` 호출에서 `NRFX_ERROR_BUSY`가 발생하는 문제가 있었다.
|
||||
|
||||
**Zephyr에서는** `adc_channel_setup_dt()` + `adc_read_dt()` 내부적으로 init/uninit 처리가 되므로 명시적 uninit 불필요. `battery_read_mv()`와 `temp_read_cdeg()` 모두 읽기 전에 `adc_channel_setup_dt()`를 호출하여 해당 채널로 SAADC를 재설정하기 때문에 임의 순서로 교대 호출해도 정상 동작한다.
|
||||
|
||||
> 단, 두 함수를 **서로 다른 스레드에서 동시에** 호출하면 안 됨. mbb? 핸들러에서 직렬로 호출하는 한 문제없음.
|
||||
|
||||
### 🔲 테스트 필요
|
||||
|
||||
| 모듈 | 테스트 방법 | 확인 항목 |
|
||||
|---|---|---|
|
||||
| 배터리 ADC (`msn?`) | RTT 로그 확인 + 앱에서 `msn?` 전송 | 아래 테스트 가이드 참고 |
|
||||
| 온도 센서 | RTT 로그 확인 | 아래 테스트 가이드 참고 |
|
||||
| IMU (`msp?`) | RTT 로그 확인 + 앱에서 `msp?` 전송 | 아래 테스트 가이드 참고 |
|
||||
|
||||
#### 배터리 ADC 테스트 가이드 (msn?)
|
||||
|
||||
**1. 부팅 시 확인 (RTT 로그)**
|
||||
|
||||
`[1] HW Init` 단계에서 아래 줄이 나와야 함:
|
||||
```
|
||||
[BATT] ADC init OK (DT-based, ch=2, res=12, os=2)
|
||||
```
|
||||
|
||||
실패 패턴:
|
||||
|
||||
| 로그 | 원인 | 조치 |
|
||||
|---|---|---|
|
||||
| `[BATT] ADC device not ready` | SAADC 드라이버 초기화 실패 | `CONFIG_ADC=y` 확인, overlay channel@2 확인 |
|
||||
| `[BATT] Channel setup failed (err -x)` | 채널 설정 실패 | overlay AIN2 설정 확인 |
|
||||
|
||||
**2. msn? 전송 시 확인 (RTT 로그)**
|
||||
|
||||
앱에서 `msn?` 전송 시 아래 형식으로 출력됨:
|
||||
```
|
||||
[CMD] msn -> 3800 mV
|
||||
```
|
||||
- 정상 범위: 3500 ~ 4200 mV (완충 4200mV, 저전압 경고 3500mV)
|
||||
- 3500mV 미만이 10회 연속이면 자동 전원 OFF
|
||||
|
||||
**3. BLE 응답 패킷 포맷**
|
||||
```
|
||||
[r][s][n][:] [mV_H][mV_L] [CRC_L][CRC_H] = 8 bytes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### 온도 센서 테스트 가이드 (TMP235)
|
||||
|
||||
**1. 부팅 시 확인 (RTT 로그)**
|
||||
|
||||
`[1] HW Init` 단계에서 아래 줄이 나와야 함:
|
||||
```
|
||||
[TEMP] OK — TMP235 ch=3, res=12, os=2
|
||||
```
|
||||
|
||||
실패 패턴:
|
||||
|
||||
| 로그 | 원인 | 조치 |
|
||||
|---|---|---|
|
||||
| `[TEMP] FAIL — ADC device not ready` | SAADC 드라이버 초기화 실패 | overlay channel@3 확인 |
|
||||
| `[TEMP] FAIL — channel setup (err=-x)` | 채널 설정 실패 | overlay AIN3 설정 확인, P0.05 핀 확인 |
|
||||
|
||||
**2. 측정 시 확인 (RTT 로그)**
|
||||
|
||||
`temp_read_cdeg()` 호출 시 아래 형식으로 출력됨:
|
||||
```
|
||||
[TEMP] raw=1234 -> 25.50 C
|
||||
```
|
||||
- 실온(25°C) 기준 raw 값 약 1404 (V = 750mV, raw = 750 × 4095 / 3600 ≈ 853)
|
||||
> 실제 분압 회로가 있으면 값이 다를 수 있음, 첫 측정값 보고 판단
|
||||
- `INT16_MIN(-32768)` 반환 시 ADC 읽기 실패
|
||||
|
||||
**3. mbb? 패킷 내 위치**
|
||||
```
|
||||
rbb: ... [temp_L][temp_H] ... ← °C × 100 단위 (25.50°C = 2550)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
#### IMU 테스트 가이드 (msp?)
|
||||
|
||||
**1. 부팅 시 확인 (RTT 로그)**
|
||||
|
||||
`[1] HW Init` 단계에서 아래 줄이 나와야 함:
|
||||
```
|
||||
[IMU] OK — ICM42670P detected (WHOAMI=0x67, addr=0x68)
|
||||
```
|
||||
|
||||
실패 패턴:
|
||||
|
||||
| 로그 | 원인 | 조치 |
|
||||
|---|---|---|
|
||||
| `[IMU] FAIL — I2C bus not ready` | Zephyr I2C 드라이버 초기화 실패 | `CONFIG_I2C=y` 확인, overlay 확인 |
|
||||
| `[IMU] FAIL — WHOAMI read error (check SCL=P1.14, SDA=P1.15)` | I2C 통신 자체 실패 | 핀 납땜/연결 확인, 풀업 저항 확인 |
|
||||
| `[IMU] FAIL — WHOAMI mismatch (got=0x00, expected=0x67)` | 버스는 살아있으나 응답 이상 | I2C 주소(0x68) 확인, AD0 핀 상태 확인 |
|
||||
|
||||
**2. msp? 전송 시 확인 (RTT 로그)**
|
||||
|
||||
앱에서 `msp?` 전송 시 아래 형식으로 출력됨:
|
||||
```
|
||||
[IMU] msp: A=( 12345, -1234, 3210) G=( 100, -50, 200)
|
||||
```
|
||||
- `A=` : 가속도 XYZ (int16, ±4g 풀스케일 → 1g ≈ 8192)
|
||||
- `G=` : 자이로 XYZ (int16, ±2000dps 풀스케일 → 1dps ≈ 16.4)
|
||||
- 디바이스 수평 정치 시 Z축 가속도 약 `+8192` 근처, 자이로 `0` 근처 (±수십 이내)
|
||||
|
||||
실패 패턴:
|
||||
|
||||
| 로그 | 원인 |
|
||||
|---|---|
|
||||
| `[IMU] FAIL — gyro config write (ret=-5)` | I2C TX 에러 |
|
||||
| `[IMU] FAIL — data read (ret=-5)` | I2C RX 에러 |
|
||||
| BLE로 `rsp: 0xFFFF` 수신 | 위 에러 발생 시 앱으로 전송되는 에러 응답 |
|
||||
|
||||
**3. BLE 응답 패킷 포맷**
|
||||
```
|
||||
[r][s][p][:] [AX_H][AX_L] [AY_H][AY_L] [AZ_H][AZ_L]
|
||||
[GX_H][GX_L] [GY_H][GY_L] [GZ_H][GZ_L]
|
||||
[CRC_L][CRC_H] = 18 bytes
|
||||
```
|
||||
|
||||
### ❌ 미구현
|
||||
|
||||
| 모듈 | 목표 파일 | 필요 기능 |
|
||||
|---|---|---|
|
||||
| 피에조 드라이버 | `src/drivers/piezo/piezo.c` | SW burst (2.1MHz), MUX, 전원 제어 |
|
||||
| Echo ADC | `src/drivers/echo_adc/echo_adc.c` | ADC121S051, SPIM3 @ 16MHz |
|
||||
| `maa?` 커맨드 | `src/parser.c` 추가 | 피에조 6ch 단독 측정 → `reb:` ×6 + `raa:` |
|
||||
| `mbb?` 커맨드 | `src/parser.c` 추가 | 전체 측정 오케스트레이션 → `rbb:` + `reb:` ×6 + `raa:` |
|
||||
|
||||
---
|
||||
|
||||
## 7. 핀 배치 전체 정리
|
||||
|
||||
| 신호 | 핀 | 방향 | 모듈 | 상태 |
|
||||
|---|---|---|---|---|
|
||||
| POWER_HOLD | P0.08 | OUT | 전원 래치 | ✅ |
|
||||
| POWER_BTN | P1.08 | IN | 전원 버튼 | ✅ |
|
||||
| LED_BLE | P0.12 | OUT | 파란 LED | ✅ |
|
||||
| LED_FUNC | P0.29 | OUT | 주황 LED | ✅ |
|
||||
| BATT_ADC | P0.04 (AIN2) | AIN | 배터리 ADC | ✅ |
|
||||
| IMU_SCL | P1.14 | I2C | ICM42670P | ✅ |
|
||||
| IMU_SDA | P1.15 | I2C | ICM42670P | ✅ |
|
||||
| TEMP_ADC | P0.05 (AIN3) | AIN | TMP235-Q1 | 🔲 |
|
||||
| PIEZO_PWR_EN | P1.09 | OUT | DC/DC +/-20V | ❌ |
|
||||
| PIEZO_PE | P0.25 | OUT | Pulse Enable | ❌ |
|
||||
| PIEZO_P_OUT | P1.07 | OUT | 양극 출력 | ❌ |
|
||||
| PIEZO_N_OUT | P1.06 | OUT | 음극 출력 | ❌ |
|
||||
| PIEZO_DMP | P1.00 | OUT | Dump | ❌ |
|
||||
| MUX_EN_A | P0.21 | OUT | MUXA 활성화 | ❌ |
|
||||
| MUX_EN_B | P0.23 | OUT | MUXB 활성화 | ❌ |
|
||||
| MUX_SEL0 | P1.10 | OUT | MUX 채널 선택 | ❌ |
|
||||
| MUX_SEL1 | P0.28 | OUT | MUX 채널 선택 | ❌ |
|
||||
| ECHO_SCLK | P0.14 | SPI | ADC121S051 CLK | ❌ |
|
||||
| ECHO_MISO | P0.15 | SPI | ADC121S051 DATA | ❌ |
|
||||
| ECHO_CS | P0.19 | OUT | ADC121S051 CS | ❌ |
|
||||
|
||||
---
|
||||
|
||||
## 8. IMU 테스트 가이드 (msp?)
|
||||
|
||||
### 부팅 시 확인 (RTT 로그)
|
||||
|
||||
부팅 직후 `[1] HW Init` 단계에서 아래 줄이 나와야 함:
|
||||
|
||||
```
|
||||
[IMU] OK — ICM42670P detected (WHOAMI=0x67, addr=0x68)
|
||||
```
|
||||
|
||||
#### 실패 패턴별 원인
|
||||
|
||||
| 로그 | 원인 | 조치 |
|
||||
|---|---|---|
|
||||
| `[IMU] FAIL — I2C bus not ready` | Zephyr I2C 드라이버 초기화 실패 | `CONFIG_I2C=y` 확인, overlay 확인 |
|
||||
| `[IMU] FAIL — WHOAMI read error (check SCL=P1.14, SDA=P1.15)` | I2C 통신 자체 실패 | 핀 납땜/연결 확인, 풀업 저항 확인 |
|
||||
| `[IMU] FAIL — WHOAMI mismatch (got=0x00, expected=0x67)` | 버스는 살아있으나 응답 이상 | I2C 주소(0x68) 확인, AD0 핀 상태 확인 |
|
||||
|
||||
---
|
||||
|
||||
### msp? 커맨드 전송 시 확인 (RTT 로그)
|
||||
|
||||
앱에서 `msp?` 전송 시 아래 형식으로 출력됨:
|
||||
|
||||
```
|
||||
[IMU] msp: A=( 12345, -1234, 3210) G=( 100, -50, 200)
|
||||
```
|
||||
|
||||
- `A=` : 가속도 XYZ (int16, ±4g 풀스케일 → 1g ≈ 8192)
|
||||
- `G=` : 자이로 XYZ (int16, ±2000dps 풀스케일 → 1dps ≈ 16.4)
|
||||
- 디바이스가 수평으로 놓여 있으면 Z축 가속도가 약 `+8192` 근처여야 함
|
||||
- 자이로는 정지 상태에서 `0` 근처 (±수십 이내)
|
||||
|
||||
#### 실패 패턴
|
||||
|
||||
| 로그 | 원인 |
|
||||
|---|---|
|
||||
| `[IMU] FAIL — gyro config write (ret=-5)` | I2C TX 에러 (부팅 후 재연결 문제) |
|
||||
| `[IMU] FAIL — data read (ret=-5)` | I2C RX 에러 |
|
||||
| BLE로 `rsp: 0xFFFF` 수신 | 위 에러 발생 시 앱으로 전송되는 에러 응답 |
|
||||
|
||||
---
|
||||
|
||||
### BLE 응답 패킷 확인
|
||||
|
||||
정상 수신 시 앱에서 받는 `rsp:` 패킷 포맷:
|
||||
|
||||
```
|
||||
[r][s][p][:] [AX_H][AX_L] [AY_H][AY_L] [AZ_H][AZ_L]
|
||||
[GX_H][GX_L] [GY_H][GY_L] [GZ_H][GZ_L]
|
||||
[CRC_L][CRC_H]
|
||||
= 18 bytes
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 다음 구현 순서
|
||||
|
||||
```
|
||||
Step 1 ✅ 온도 센서 (tmp235.c) — 완료, 테스트 필요
|
||||
|
||||
Step 2 피에조 드라이버 (piezo.c)
|
||||
└─ GPIO 초기화, MUX, SW burst (NOP 기반, nrf HAL 직접 사용)
|
||||
└─ CONFIG_NRFX_GPIOTE=y 추가
|
||||
|
||||
Step 3 Echo ADC (echo_adc.c)
|
||||
└─ SPIM3 초기화, 연속 샘플 캡처
|
||||
└─ CONFIG_NRFX_SPIM3=y 추가
|
||||
|
||||
Step 4 maa? 커맨드 (parser.c 추가)
|
||||
└─ 피에조 6ch 측정 + BLE 전송 (reb: ×6 + raa:)
|
||||
└─ 센서 번들 없음 — 피에조/ADC 단독 검증용
|
||||
|
||||
Step 5 mbb? 커맨드 (parser.c 추가)
|
||||
└─ 배터리 + IMU + 온도 + 피에조 6ch 전체 오케스트레이션
|
||||
└─ rbb: + reb: ×6 + raa:
|
||||
```
|
||||
Reference in New Issue
Block a user