티스토리 뷰
[Contents]
- InstrumentManager.cpp
- BiliMon266Constants.h
- cSlave_SensorsActuators.h
- cSlave_SensorsActuators.cpp
[InstrumentManager.cpp]
// 5. T5838 마이크 센서 감지 루틴 (소음 임계값 판단 및 정기 업로드)
if (localT5838) {
// AAD 인터럽트 발생 여부 메인 루프에서 감지 및 시리얼 안전 출력
if (localT5838->checkAndResetAADTrigger()) {
Serial.println("[T5838 Alert] Acoustic Activity Detected (WAKE pin triggered)!");
}
if (currentMillis - lastPollTime_T5838 >= POLL_PERIOD_T5838 || lastPollTime_T5838 == 0) {
lastPollTime_T5838 = currentMillis;
float db = localT5838->readNoiseDb();
if (db >= 0.0f) {
bool thresholdBreached = (db >= T5838_DB_THRESHOLD);
unsigned long uploadInterval = thresholdBreached ? 1000L : UPLOAD_PERIOD_T5838_NORMAL;
static unsigned long lastT5838Upload = 0;
if (thresholdBreached || (currentMillis - lastT5838Upload >= uploadInterval || lastT5838Upload == 0)) {
lastT5838Upload = currentMillis;
cUploadData* micData = new cUploadData();
micData->dataType = "T5838";
micData->dataName = "SOUND_LEVEL";
micData->dataValue1 = "DB:" + String(db, 1);
micData->option1 = thresholdBreached ? "AS:110" : "AS:200";
micData->option2 = networkManager ? networkManager->getTimeString() : "";
micData->isValid = true;
if (uploadQueue != NULL) {
if (xQueueSend(uploadQueue, &micData, 0) != pdTRUE) {
delete micData;
}
}
if (thresholdBreached) {
String msg = "🚨 [BiliMon Master Alert] 주변 소음 데시벨(" + String(T5838_DB_THRESHOLD) + "dB)을 초과했습니다! 현재 소음: " + String(db, 1) + " dB";
if (networkManager) networkManager->sendInstantAlert(msg);
}
}
}
}
}
[BiliMon266Constants.h]
#define PIN_T5838_CLK D6 // T5838 I2S PDM CLK (D6)
#define PIN_T5838_DATA D7 // T5838 I2S PDM DATA (D7)
#define PIN_T5838_WAKE D8 // T5838 AAD Wakeup 인터럽트 핀
#define PIN_T5838_THSEL D9 // T5838 1-Wire 설정 핀
#define PIN_T5838_SEL 255
[cSlave_SensorsActuators.h]
// ==========================================
// 8. T5838 디지털 PDM/I2S 마이크로폰 모듈
// ==========================================
class cSlave_T5838 {
private:
uint8_t m_clkPin;
uint8_t m_dataPin;
uint8_t m_wakePin;
uint8_t m_thselPin;
uint8_t m_selPin;
bool m_isEnabled;
int m_i2sPort;
volatile bool m_aadTriggered; // AAD 발생 감지 플래그
public:
cSlave_T5838(uint8_t clkPin, uint8_t dataPin, uint8_t wakePin, uint8_t thselPin, uint8_t selPin = 255, int i2sPort = 0);
bool begin();
void setEnabled(bool enabled);
bool isEnabled() const { return m_isEnabled; }
float readNoiseDb();
// AAD 인터럽트 처리 및 초기 설정 함수
void IRAM_ATTR handleWakeInterrupt(); // IRAM 배치 지정
bool checkAndResetAADTrigger();
void configureAAD(float thresholdDb);
// 1-Wire 통신용 함수 (Option A: 스텁 / Option B: 비트뱅잉 로직)
void writeRegister1Wire(uint8_t regAddr, uint8_t dataVal);
};
[cSlave_SensorsActuators.cpp]
// ==========================================
// 8. T5838 디지털 PDM/I2S 마이크로폰 모듈
// ==========================================
static cSlave_T5838* g_t5838_instance = nullptr;
void IRAM_ATTR t5838_wake_isr() {
if (g_t5838_instance) {
g_t5838_instance->handleWakeInterrupt();
}
}
cSlave_T5838::cSlave_T5838(uint8_t clkPin, uint8_t dataPin, uint8_t wakePin, uint8_t thselPin, uint8_t selPin, int i2sPort)
: m_clkPin(clkPin), m_dataPin(dataPin), m_wakePin(wakePin), m_thselPin(thselPin), m_selPin(selPin),
m_isEnabled(true), m_i2sPort(i2sPort), m_aadTriggered(false) {}
bool cSlave_T5838::begin() {
if (!m_isEnabled) return false;
// 1. SEL 핀 설정
if (m_selPin != 255) {
pinMode(m_selPin, OUTPUT);
digitalWrite(m_selPin, LOW); // Left 채널로 구동
}
// 2. THSEL 핀 설정 (1-Wire)
pinMode(m_thselPin, INPUT); // 평상시 Hi-Z 상태 유지
// 3. WAKE 핀 설정 및 외부 인터럽트 등록 (Option A)
pinMode(m_wakePin, INPUT_PULLDOWN);
g_t5838_instance = this;
attachInterrupt(digitalPinToInterrupt(m_wakePin), t5838_wake_isr, RISING);
// [Option B - 주석 처리] ESP32 Light Sleep Wakeup Source로 WAKE 핀 등록 코드
/*
esp_sleep_enable_ext0_wakeup((gpio_num_t)m_wakePin, 1); // WAKE 핀이 HIGH일 때 Wakeup
*/
i2s_config_t i2s_config = {
.mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_RX | I2S_MODE_PDM),
.sample_rate = 16000,
.bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
.channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
.communication_format = I2S_COMM_FORMAT_STAND_I2S,
.intr_alloc_flags = ESP_INTR_FLAG_LEVEL1,
.dma_buf_count = 4,
.dma_buf_len = 512,
.use_apll = false,
.tx_desc_auto_clear = false,
.fixed_mclk = 0
};
i2s_pin_config_t pin_config = {
.bck_io_num = I2S_PIN_NO_CHANGE,
.ws_io_num = m_clkPin,
.data_out_num = I2S_PIN_NO_CHANGE,
.data_in_num = m_dataPin
};
esp_err_t err = i2s_driver_install((i2s_port_t)m_i2sPort, &i2s_config, 0, NULL);
if (err != ESP_OK) {
Serial.printf("[T5838] I2S driver install failed: %d\n", err);
return false;
}
err = i2s_set_pin((i2s_port_t)m_i2sPort, &pin_config);
if (err != ESP_OK) {
Serial.printf("[T5838] I2S set pin failed: %d\n", err);
return false;
}
Serial.printf("[T5838] PDM Mic initialized on CLK:%d, DATA:%d\n", m_clkPin, m_dataPin);
return true;
}
void IRAM_ATTR cSlave_T5838::handleWakeInterrupt() {
m_aadTriggered = true; // ISR 내부이므로 Serial 출력 생략 (Thread-Safe)
}
bool cSlave_T5838::checkAndResetAADTrigger() {
if (m_aadTriggered) {
m_aadTriggered = false;
return true;
}
return false;
}
void cSlave_T5838::configureAAD(float thresholdDb) {
Serial.printf("[T5838] Configuring AAD Threshold to %.1f dB...\n", thresholdDb);
// Option A: 하드웨어 기본값 사용 (스텁)
// [Option B - 주석 처리] THSEL을 이용한 실제 레지스터 설정 시나리오 예시
/*
// 예시: 0x02 레지스터에 threshold 데이터 작성
uint8_t rawValue = (uint8_t)(thresholdDb - 40.0f); // T5838에 맞춰 스케일링 가정
writeRegister1Wire(0x02, rawValue);
*/
}
void cSlave_T5838::writeRegister1Wire(uint8_t regAddr, uint8_t dataVal) {
// [Option B - 주석 처리] PDM CLK를 이용한 1-Wire 비트뱅잉 타이밍 전송 예시 코드
/*
pinMode(m_thselPin, OUTPUT);
// 1-Wire 프로토콜에 따라 시작 조건, 레지스터 주소 비트, 데이터 비트 모듈레이션
// 각 비트는 CLK의 엣지에 동기화하여 전송합니다.
// ...
pinMode(m_thselPin, INPUT); // 완료 후 Hi-Z 복귀
*/
}
void cSlave_T5838::setEnabled(bool enabled) {
m_isEnabled = enabled;
if (!m_isEnabled) {
i2s_stop((i2s_port_t)m_i2sPort);
} else {
i2s_start((i2s_port_t)m_i2sPort);
}
}
float cSlave_T5838::readNoiseDb() {
if (!m_isEnabled) return -999.0f;
int16_t samples[512];
size_t bytesRead = 0;
esp_err_t err = i2s_read((i2s_port_t)m_i2sPort, (void*)samples, sizeof(samples), &bytesRead, pdMS_TO_TICKS(50));
if (err != ESP_OK || bytesRead == 0) {
return -999.0f;
}
int sampleCount = bytesRead / sizeof(int16_t);
double sum = 0;
for (int i = 0; i < sampleCount; i++) {
sum += (double)samples[i] * samples[i];
}
if (sampleCount == 0) return 0.0f;
double rms = sqrt(sum / sampleCount);
float db = 20.0f * log10(rms + 1.0);
return db;
}
반응형
'HWDesk > HardwareControl' 카테고리의 다른 글
| NANO ESP32와 XIAO MG24 비교표 (0) | 2026.06.09 |
|---|---|
| 스텝 모터 제어 질의 - ChatGPT (0) | 2025.05.04 |
| DRV88245, ULN2003, MPU60506, AM2302 연결 방법 (0) | 2025.04.27 |
| 스테핑 모터 제어 방법 비교 (0) | 2025.04.26 |
| AM2302 온습도 센서 제어 코드 (2) | 2025.04.19 |
반응형
250x250
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
링크
TAG
- Innovations&Hurdles
- arduino
- 치매
- 빌리칠드
- 티스토리챌린지
- Innovations
- 심심풀이치매방지기
- 빌리언트
- DYOV
- 아두이노
- 전압
- 심심풀이
- image
- 혁신
- 배프
- Innovation&Hurdles
- BSC
- Decorator
- 절연형
- 오블완
- Video
- ServantClock
- 전류
- 혁신과허들
- Hurdles
- 허들
- bilient
- 둎
- 치매방지
- BiliChild
| 일 | 월 | 화 | 수 | 목 | 금 | 토 |
|---|---|---|---|---|---|---|
| 1 | 2 | 3 | 4 | 5 | 6 | |
| 7 | 8 | 9 | 10 | 11 | 12 | 13 |
| 14 | 15 | 16 | 17 | 18 | 19 | 20 |
| 21 | 22 | 23 | 24 | 25 | 26 | 27 |
| 28 | 29 | 30 |
글 보관함

