TMS320F28X 개발보드 V2 예제
[F28P55x] 칩 하나가 소리를 듣고 판단한다! 마이크 소리(부저·박수·조용함)를 NPU로 분류하는 Edge AI 예제 (데이터 수집 → 학습 → 보드 추론, DriverLib
| 3줄 요약 ① 개발보드의 마이크로 소리를 모아 부저 · 박수 · 조용함 3가지로 분류하는 Edge AI 예제입니다. 서버나 인터넷 없이 칩 안에서 돌아갑니다. ② 소리 수집 → TI Edge AI Studio 학습 → 결과 파일 적용 → 보드 추론의 전 과정을 화면 캡처와 함께 따라 할 수 있고, 학습 데이터 58개도 함께 제공합니다. ③ 같은 모델을 F28P55x의 NPU(신경망 가속기)와 CPU로 각각 돌려 비교할 수 있습니다. 보드 측정에서 추론 완료까지 NPU 695.73 µs, CPU 9,884.95 µs(약 14.2배 차이)였습니다. |
1. 실습 안내
본 예제는 TMS320F28P55x(F28P559SJ9-Q1) 제어 모듈이 탑재된 TMS320F28X 개발보드(EVM) V2를 대상으로 합니다.Edge AI는 AI 계산을 서버가 아니라 센서 바로 옆의 칩이 하는 방식입니다. 인터넷이 끊겨도 동작하고, 결과가 빠르고, 데이터가 밖으로 나가지 않습니다. 모터·전원 제어에 쓰던 C2000 칩 중 F28P55x에는 AI 계산 전용 회로인 NPU가 들어 있어서, 제어하던 칩이 그 자리에서 판단까지 할 수 있습니다.
개발보드의 '(4) VREF & MIC & BUZZER' 회로에는 마이크와 부저가 있습니다. 이 예제는 이 마이크로 아래 3가지 소리를 구분합니다.
전체 과정은 아래 5단계이며, 예제는 두 개의 프로젝트로 나뉩니다.
| 단계 | 할 일 | 사용하는 것 |
| ① 수집 | 보드 마이크를 20kHz로 녹음해 PC에 CSV 파일로 저장 (클래스별 폴더) | 4_EdgeAI_MicLogger_Driverlib + PC 프로그램 MicCollector.exe |
| ② 학습 | 수집한 데이터를 TI Edge AI Studio에 올려 작은 신경망(CNN)을 학습·컴파일 | PC의 Edge AI Studio (보드 필요 없음) |
| ③ 적용 | Studio가 만든 결과 파일 4개를 프로젝트에 덮어쓰기 | 4_EdgeAI_MicSound_Driverlib |
| ④ 추론 | 25.6 ms마다 마이크 소리를 분류해 결과를 갱신 (NPU / CPU 두 가지 빌드 구성) | 4_EdgeAI_MicSound_Driverlib |
| ⑤ 확인 | CCS Watch 창의 변수로 분류 결과와 시간을 확인 | CCS Expressions |
이미 학습한 모델과 학습 데이터(58개)가 저장소에 들어 있어서, ①~③을 건너뛰고 ④부터 바로 실행해 보실 수도 있습니다.
2. 실습 준비
본 예제는 아래의 개발환경에서 컴파일/링크를 확인했습니다.MicCollector.exe, Python 스크립트)CPU1_FLASH(NPU가 추론)와 CPU1_FLASH_SOFT(CPU가 추론) 두 구성selfTestPass=1, frameOverruns=0, 추론 시간 측정, 조용함/부저/박수 분류npuTimeouts와, 다른 장소·거리·배경 소음에서의 정확도도 확인 전입니다. 학습한 데이터는 58개 파일, 같은 날 같은 환경에서 모은 것입니다.
3. 실습 예제 다운로드 (GitHub ZIP 다운로드 안내)
초보자분들도 손쉽게 다운로드하여 사용하실 수 있도록 전체 소스 코드와 학습 데이터를 GitHub에 공개해 두었습니다.아래 안내에 따라 ZIP 압축 파일로 다운로드하세요.
[다운로드 순서]
압축을 풀면 아래와 같이 구성되어 있습니다.
| 폴더 / 파일 | 내용 |
4_EdgeAI_MicLogger_Driverlib/ | ① 소리 수집 펌웨어 + tools/(MicCollector.exe, 수집 스크립트) |
4_EdgeAI_MicSound_Driverlib/ | ④ 소리 분류 펌웨어 (model_npu/, model_soft/, model/에 모델 파일) |
dataset/, dataset.zip | 학습에 쓴 소리 데이터 58개 (buzzer 18 / clap 22 / silence 18), Studio에 올리는 형식의 zip |
edgeai_studio_result/ | Edge AI Studio가 만든 결과 파일 원본 (mod.a, tvmgen_default.h, test_vector.c, user_input_config.h, model.onnx) |
README.md, docs/ | 전체 설명서와 화면 이미지 |
4. CCS 프로젝트 불러오기 (CCS V20 기준) 및 컴파일
>> [유튜브] CCS V20 기준 프로젝트 불러오기 방법 소개 영상4_EdgeAI_MicSound_NPU_Driverlib입니다.)4_EdgeAI_MicLogger_Driverlib : CPU1_RAM 또는 CPU1_FLASH 구성 중 하나4_EdgeAI_MicSound_NPU_Driverlib : CPU1_FLASH = NPU가 추론, CPU1_FLASH_SOFT = CPU가 추론. Build Configuration에서 원하는 구성을 고르세요. 두 구성은 같은 소스에 모델 라이브러리(mod.a)만 다릅니다.
5. 개발보드 점퍼선 연결 안내
아래와 같이 F28P55x 모듈의 핀-헤더와 개발보드 회로 블록을 점퍼선으로 연결합니다. 마이크는 A Side, 부저와 시리얼은 B Side 핀-헤더를 사용합니다.| 번호 | 신호 | EVM V2 핀-헤더 | 할당 신호명 | 연결 대상 |
| 1 | 마이크 입력 | A Side 41번 핀 | A0/B15 (ADCINA0) | (4) 블록 "MIC OUT" |
| 2 | 부저 출력 | B Side 33번 핀 | GPIO0 / EPWM1A | (4) 블록 "BUZZ IN" |
| 3 | SCI TX (수집할 때만) | B Side 19번 핀 | GPIO43 / SCIC_TX | (11) 블록 "TX1" |
| 4 | SCI RX (수집할 때만) | B Side 21번 핀 | GPIO42 / SCIC_RX | (11) 블록 "RX1" |
* 마이크는 반드시 A Side 41번 핀에 꽂으세요. A Side 46번은 A9/GPIO227이라 ADCINA0이 아닙니다. (이전 버전 소스는 43번(ADCINA1)을 썼습니다. 현재 소스는 41번입니다.)
* 소리를 분류만 할 때(④단계)는 1, 2번(마이크·부저) 점퍼선 2개면 됩니다. 3, 4번은 데이터를 수집할 때(①단계)만 필요합니다.
* F28P55x에서 GPIO42/43의 시리얼 기능은 SCI-C입니다. (F28P65x 예제는 SCI-A이고 TX/RX 핀 번호가 반대이니 혼동하지 마세요.)
* '(11) 2채널 SCI-to-USB' 회로의 미니 5핀 USB 커넥터를 PC와 케이블로 연결하면 PC에서 'USB Serial Port' 2개가 인식됩니다. 이 중 1채널(RX1/TX1)에 해당하는 포트를 사용하세요. 어느 포트인지는 장치관리자에서 확인할 수 있습니다.
* 부저와 마이크가 가까우면 부저 소리가 너무 커서 마이크 신호가 포화될 수 있습니다. 수집할 때 거리를 두세요.

(점퍼선 연결도: 빨강 = 마이크 A Side 41번 → MIC OUT, 파랑 = 부저 B Side 33번 → BUZZ IN, 파랑 · 초록 = SCI B Side 19번 → TX1 / 21번 → RX1. 클릭하시면 큰 이미지를 자세히 확인하실 수 있습니다.)
6. ① 소리 데이터 수집 (MicLogger + MicCollector.exe)
학습할 모델은 직접 모은 소리 데이터로 만듭니다. 보드가 마이크(ADC)를 20kHz로 읽어 시리얼로 보내면, PC 프로그램이 클래스 이름의 폴더에 CSV 파일로 저장합니다. 한 번에 약 1.64초(32,768샘플)를 녹음합니다.※ 저장소의
dataset/에 이미 모은 데이터 58개(buzzer 18 / clap 22 / silence 18)가 들어 있습니다. 이 단계를 건너뛰고 7번으로 가셔도 됩니다.[준비]
4_EdgeAI_MicLogger_Driverlib을 Debug(F11) 한 뒤 Resume(F8)으로 실행해 둡니다.[MicCollector.exe 사용 방법] (저장소의
4_EdgeAI_MicLogger_Driverlib/tools/MicCollector.exe를 더블클릭, Python 설치 불필요)silence, buzzer, clap 중에서 고르거나 직접 입력합니다. 이 이름이 저장 폴더(classes/<클래스>/)가 됩니다.dataset입니다.min, max, 평균이 나옵니다.
(조용함(silence) 수집 중 화면. 로그의 평균이 2045 안팎이면 정상입니다. 클릭하시면 큰 이미지를 확인하실 수 있습니다.)
[클래스별 수집 요령]
| 클래스 | 설정과 요령 |
| silence | 부저 체크를 해제하고 조용한 상태로 둡니다. 로그의 평균이 2045 안팎이면 정상입니다. |
| buzzer | 부저 울리기를 체크합니다. 마이크와 부저가 너무 가까우면 min=0 max=4095(ADC 포화)가 되고 [주의] ADC가 0 또는 4095에 닿았습니다 경고가 뜹니다. 그러면 거리를 두세요. 포화된 녹음은 학습에서 빼는 것이 좋습니다. |
| clap | 부저 체크를 해제하고, 안내 문구에 "녹음 중에 박수를 여러 번 치세요"를 적습니다. 대기 시간 안에 준비한 뒤 녹음 중에 박수를 칩니다. |

(왼쪽 : 부저 수집 (포화 경고 예시) / 오른쪽 : 박수 수집)
* 클래스마다 같은 날, 같은 위치에서 모으면 일관된 데이터가 됩니다. 저장소의 58개도 그렇게 모았습니다.
* 마이크 신호가 평평하게만 나오면(
신호가 거의 평평합니다 경고) A Side 41번 ↔ "MIC OUT" 배선을 확인하세요.* 명령행으로 모으려면
python tools/collect_mic_data.py --port COM5 --label buzzer --count 15 --buzzer 처럼 실행합니다.
7. ② Edge AI Studio로 학습하기
TI의 CCStudio Edge AI Studio for Time Series(화면은 v1.7.1, Tiny ML Backend 1.4.1 기준)에서 위 데이터로 모델을 학습하고 컴파일합니다. 아래는 저장소의 데이터로 처음부터 다시 따라 한 기록입니다. 학습은 PC에서 하며 보드는 필요 없습니다.[미리 준비] Edge AI Studio 설치, 그리고 아래 ⑦번 화면에서 확인하는 TI C28-CLA Compiler 25.11.01.00(Windows에서는
C: i 아래에 설치). 학습 데이터는 저장소 루트의 dataset.zip을 쓰면 됩니다. zip 맨 위에 classes/ 폴더가 와야 합니다.Time Series Classification, Device Family = C2000 real-time microcontrollers, Device = F28P55로 좁힙니다. 목록의 Timeseries Classification 오른쪽 Import Project into Workspace 아이콘을 누릅니다.

dataset.zip을 엽니다. 성공하면 왼쪽 Project Files의 classes 아래에 buzzer, clap, silence가 생깁니다. (폴더 이름이 클래스 이름입니다.)


1. Generic_512Input_FFTBIN_32Feature_8Frame을 고르면 자동으로 채워지고, 회색 칸은 자동 계산입니다.| 항목 | 값 | 의미 |
| Preprocessing Mode / Transform | Feature Extraction / FFTBIN | 파형을 FFT 구간(bin) 값으로 바꿔 넣음 |
| Frame Size | 512 | 512샘플 = 20kHz에서 25.6ms |
| Feature Size per Frame | 32 | 프레임마다 32개 주파수 구간 |
| Frames to Concatenate | 8 | 최근 8프레임(약 0.2초)을 이어 붙임 |
| AI Model Input Feature Size | 256 (자동) | 32 × 8 = 모델 입력 크기 |
| Channels / Stride Size | 1 / 0.1 | 마이크 한 채널 / 프레임 이동 비율 |
| Epochs / Learning Rate / Batch Size | 20 / 0.04 / 256 | 학습 설정 |
| AI Optimization | High Speed | |
| Compilation Preset | Default Preset | c, ti-npu type=hard skip_normalize=true output_int=true (NPU 하드웨어용 코드) |



auto_quantization ... bitwidth will be overridden 같은 WARNING이 나오지만 학습은 계속 진행됩니다. 학습이 끝나면 이어서 컴파일이 진행됩니다.

(왼쪽 : 학습 곡선 / 오른쪽 : 시험 데이터 혼동 행렬 - 클래스당 171개 모두 정답)
8. ③ 결과 파일을 프로젝트에 적용하기
학습 결과 중 4개 파일만4_EdgeAI_MicSound_Driverlib에 덮어쓰면 됩니다. 이번 학습의 원본 파일은 저장소의 edgeai_studio_result/에도 들어 있습니다. Studio에서 프로젝트를 내보낸 ZIP(<프로젝트ID>_project.zip)을 풀었을 때의 위치는 아래와 같습니다. (<Run>은 Studio가 붙인 날짜-시간 이름)| 파일 | Studio 결과 안의 위치 | 복사할 곳 |
mod.a(NPU 모델 라이브러리) | train/<Run>/compile/<Run>/output/artifacts/ | 4_EdgeAI_MicSound_Driverlib/model_npu/ |
tvmgen_default.h(모델 입출력 정의) | 같은 artifacts/ 폴더 | model_npu/ |
user_input_config.h(전처리 설정) | train/<Run>/output/training_quantization/golden_vectors/ | model/ |
test_vector.c(부팅 자체 시험용 입력·정답) | 같은 golden_vectors/ 폴더 | model/ |
놓치기 쉬운 점
golden_vectors는 training_base와 training_quantization 두 곳에 있습니다. training_quantization 것을 쓰세요. (training_base는 양자화 전 float 모델의 것입니다.)mod.a는 compile/<Run>/output/artifacts/ 안의 것입니다. 컴파일 설정이 Default Preset(ti-npu type=hard)이어야 NPU용입니다. forced_soft_npu_preset으로 만든 mod.a는 CPU 추론이 되지 않으니 쓰지 마세요.test_vector.c로 모델을 한 번 돌려 정답과 비교하므로(selfTestPass), 서로 다른 학습의 파일이 섞이면 0이 될 수 있습니다.[적용 순서]
model/, model_npu/ 폴더에 덮어쓰거나, 프로젝트를 지우고 다시 Import하세요.)buzzer 0, clap 1, silence 2). app_config.h의 kClassNames가 같은 순서여야 합니다. 클래스를 바꿨다면 test_vector.c의 Class: ... 주석 순서를 보고 고치세요.model/user_input_config.h가 FE_FRAME_SIZE 512, FE_FEATURE_SIZE_PER_FRAME 32, FE_NUM_FRAME_CONCAT 8, FE_NN_OUT_SIZE 3이어야 펌웨어의 특징 추출과 맞습니다. 샘플링은 수집할 때와 같은 20kHz(SAMPLE_RATE_HZ)입니다..map)에 TINIE_start가 있으면 NPU 코드가 들어간 것입니다.[CPU 구성(CPU1_FLASH_SOFT)까지 바꾸려면]
model_soft/는 NPU 없는 F28P65 대상으로 컴파일한 결과가 필요합니다. Studio에서 장치를 F28P65로 하고 같은 설정으로 새 학습을 만든 뒤, 그 mod.a를 model_soft/make_cpu_mod.py로 변환해 model_soft/에 두고 같은 학습의 tvmgen_default.h도 복사합니다. 자세한 방법은 저장소 README의 4-3절을 보세요.※ 이 절차는 새로 학습한 결과 파일 4개를 위 순서대로 복사한 사본을 CCS와 같은 옵션으로 컴파일·링크해서 오류가 없는 것까지 확인했습니다. 같은 데이터·설정으로 다시 학습하면
test_vector.c와 user_input_config.h는 이전 학습과 바이트 단위로 같았습니다. 새 mod.a를 보드에서 실행한 확인은 아직 하지 않았습니다.
9. ④ 실행 및 동작 확인 (소리 분류)
CPU1_FLASH(NPU) 또는 CPU1_FLASH_SOFT(CPU)입니다.printf를 쓰지 않습니다(실시간 모드에서 CIO 오류가 남). 모든 확인은 Watch 변수로 합니다.| 변수 | 정상 값 | 의미 |
selfTestPass | 1 | 부팅 때 TI 테스트 벡터로 모델을 돌려 정답과 일치한 결과. 0이면 모델 파일이 맞지 않거나 NPU에 문제가 있는 것 |
modelIsNpu | NPU 구성 1 / CPU 구성 0 | 현재 빌드가 NPU 실행인지 확인 |
npuTimeouts | 0 | NPU가 한 프레임(25.6ms) 안에 끝내지 못한 횟수 |
frameOverruns | 0 | 처리가 늦어 덮어쓴 프레임 수 |
frameCount | 계속 증가 | 멈춰 있으면 ADC/타이머 인터럽트가 안 도는 것 |
micResult | 조용할 때 2000 안팎 | 마이크 ADC 값. 0이나 4095에 붙어 있으면 배선 또는 기준전압 문제 |
soundClass | 0 / 1 / 2 | 최근 프레임의 분류 결과 (buzzer 0, clap 1, silence 2) |
stableClass, stableClassName | buzzer / clap / silence | 같은 결과가 3프레임 연속 나온 안정화된 최종 분류값과 그 이름 |
scores[] | - | 클래스별 점수. 결과가 흔들릴 때 어느 클래스와 겹치는지 볼 때 사용 |
feUs, launchUs, inferUs, cpuLoadPct | 10번 표 참고 | 특징 추출 시간, 모델 실행 호출 시간, 추론 완료까지 시간, CPU 부하 (µs / %) |
ToneOutFlag | 직접 1로 쓰기 | 1이면 부저가 4kHz로 울립니다. 분류 시험용 |
selfTestPass == 1, modelIsNpu가 구성과 맞는지 확인합니다.micResult가 2000 안팎이고 stableClassName이 silence인지 확인합니다.ToneOutFlag를 1로 바꿔 부저를 울리면 stableClassName이 buzzer로 바뀝니다. 다시 0으로 되돌립니다.clap으로 바뀌는지 확인합니다.npuTimeouts와 frameOverruns가 0으로 유지되는지 확인합니다.
(CCS Watch 화면 예시. 클릭하시면 큰 이미지를 확인하실 수 있습니다. 마이크를 A Side 43번에 꽂았을 때의 화면입니다.)
10. 측정 결과 : NPU 효과
같은 칩(150MHz), Flash 실행, 최적화 없음(--opt_level=off) 조건에서 같은 모델을 NPU와 CPU로 각각 실행해 Watch 변수로 측정했습니다. 2026-10-19 재측정에서도 같은 경향이었습니다. (마이크를 A Side 43번에 꽂았을 때의 측정입니다.)| 항목 | NPU (CPU1_FLASH) | CPU (CPU1_FLASH_SOFT) |
추론 완료까지 (inferUs) | 695.73 µs | 9,884.95 µs |
특징 추출 (feUs) | 약 401~402 µs | 약 402~403 µs |
CPU 부하 (cpuLoadPct) | 2.17 % | 40.18 % |
selfTestPass / frameOverruns | 1 / 0 | 1 / 0 |

(왼쪽 : NPU 구성 Watch / 오른쪽 : CPU 구성 Watch, 2026-10-19)
해석할 때 주의할 점
cpuLoadPct 2.17%의 의미 : NPU 완료를 바쁜 대기로 기다리는 시간을 뺀 값입니다. 실제 CPU 점유율이 2%라는 뜻이 아닙니다.
11. 자주 묻는 질문과 다음 단계
Q. 왜 이렇게 작은 모델인가요?A. MCU의 메모리·연산 한계 때문입니다. 3가지 소리를 구분하는 데는 파라미터 893개로 충분했습니다.
Q. NPU가 꼭 필요한가요?
A. 지금 모델은 CPU로도 프레임 안에 처리됩니다. 모델이 커지거나 다른 작업이 많아질 때 NPU 가치가 커집니다.
Q. 정확도 100%를 믿어도 되나요?
A. 같은 환경, 소량 데이터의 결과입니다. 장소·거리·소음 환경을 늘려 재검증이 필요합니다.
Q. 학습은 어디서 하나요?
A. PC의 TI Edge AI Studio에서 합니다. 보드는 학습된 모델의 실행만 합니다.
[다음 단계] ① 환경이 다른 데이터를 추가해 재학습 ② NPU 대기를 인터럽트 방식으로 바꿔 CPU 여유 시간 재측정 ③ 다른 Edge AI 예제(이상 감지 등)로 확장
어떤 소리를 알아맞히게 해보고 싶으신지(모터 소리로 고장 감지, 문 닫히는 소리 구분 등) 댓글로 남겨 주세요. 다음 예제에 반영하겠습니다.
| 번호 | 제목 | 작성자 | 날짜 |
|---|
- 1




