본 문서는 Renesas Electronics 데이터시트(REN_ZSSC3123-Datasheet_DST_20211119.pdf)에 명시된 ZSSC3123 cLite™ 정전용량 센서 신호 컨디셔너를 위한 Arduino 기반 인터페이스 구현을 상세히 설명되며,구현에는 I2C 통신, EEPROM 관리, Update 및 Sleep 모드에서의 센서 데이터 수집이 포함됩니다. 코드는 데이터시트의 전기적 및 타이밍 사양을 준수하며, 저전력 정전용량 센싱 애플리케이션을 위한 견고한 제어 및 오류 처리를 제공합니다.
1. 서론
ZSSC3123은 최대 260pF의 정전용량을 지원하며 125aF/LSB에서 1pF/LSB까지의 감도를 제공하는 정전용량-디지털 변환 및 센서별 보정을 위한 CMOS IC로써, 센서 오프셋, 감도, 온도 드리프트에 대한 디지털 보정은 비휘발성 EEPROM에 저장된 보정 알고리즘을 통해 수행됩니다. 본 문서는 I2C를 통해 ZSSC3123과 인터페이스하여 설정, 데이터 수집, 모드 제어를 가능하게 하는 Arduino 호환 C++ 구현을 설명합니다(데이터시트 섹션 9, 10, 11, 12 참조).
2. 시스템 개요
구현은 단일 정전용량 센서 구성(데이터시트 섹션 14.1)을 대상으로 Arduino 마이크로컨트롤러와 ZSSC3123의 인터페이스를 위해서 하드웨어 구성은 다음과 같습니다.
- 전원 공급: 2.3V~5.5V (VDD), Power-On Reset(POR)을 위해 디지털 핀(D8)으로 제어.
- I2C 인터페이스: SDA/SCL 핀에 연결(섹션 10.6.1).
- 센서: C0 및 CC 핀에 연결된 단일 정전용량 센서.
- 디커플링 커패시터: VDD 및 Vcore에 0.1µF 커패시터(섹션 14.1).
소프트웨어는 Arduino Wire 라이브러리를 활용하여 I2C 통신을 수행하며, ZSSC3123의 타이밍 요구사항(예: EEPROM 읽기 100µs, 쓰기 12ms, 시작 시간 173ms)을 준수합니다.
3. 구현 세부 사항
3.1 코드 구조
코드는 ZSSC3123의 동작을 제어하기 위해 다음과 같은 주요 기능을 포함합니다.
- 전원 제어:
ZSSC3123_Power_Cycle
함수로 VDD를 통해 POR 트리거(섹션 10.1).- Command Mode 관리:
ZSSC3123_Enter_Command_Mode
및ZSSC3123_Check_Command_Mode
로 Command Mode 진입 및 확인(섹션 11).- EEPROM 액세스:
ZSSC3123_EEPROM_Read
,ZSSC3123_EEPROM_Write
,ZSSC3123_EEPROM_Read_All
,ZSSC3123_EEPROM_Write_All
로 EEPROM 설정 관리(섹션 12).- 데이터 수집:
ZSSC3123_Read_Raw_Data
,ZSSC3123_Read_Sensor_Data_Update_Mode
,ZSSC3123_Read_Sensor_Data_Sleep_Mode
로 Update 및 Sleep 모드에서 데이터 읽기(섹션 10.3, 10.6.4).- 초기화:
ZSSC3123_Initialize_Settings
로 Continuous Mode 및 14비트 해상도 설정(섹션 12).
#include <Wire.h> // Arduino I2C 통신을 위한 Wire 라이브러리 포함 (Include Wire library for Arduino I2C communication)
// ZSSC3123 I2C 기본 설정 (데이터시트 섹션 10.6.1) (ZSSC3123 I2C basic configuration (datasheet section 10.6.1))
#define ZSSC3123_I2C_ADDR 0x28 // 7비트 I2C 슬레이브 주소 (기본값, 설정에 따라 변경 가능) (7-bit I2C slave address (default, configurable))
#define EEPROM_NUM_WORDS 0x20 // EEPROM 워드 수: 0x00 ~ 0x1F (32 워드, 섹션 12) (EEPROM word count: 0x00 to 0x1F (32 words, section 12))
#define EEPROM_MAX_USER_ADDR 0x1C // 사용자 접근 가능 최대 주소 (0x1D~0x1F는 예약됨, 섹션 12) (Maximum user-accessible address (0x1D-0x1F reserved, section 12))
#define EEPROM_READ_DELAY_US 100 // EEPROM 읽기 응답 시간 (typical, 100μs, 섹션 12) (EEPROM read response time (typical, 100μs, section 12))
#define EEPROM_WRITE_DELAY_MS 12 // EEPROM 쓰기 응답 시간 (typical, 12ms, 섹션 12) (EEPROM write response time (typical, 12ms, section 12))
#define MODE_CHECK_TIMEOUT_MS 2 // Command Mode 확인 타임아웃 (사용자 정의) (Command Mode check timeout (user-defined))
#define NORMAL_MODE_STARTUP_MS 173 // Normal Mode 초기화 대기 시간 (tSTA 최대 173ms, 섹션 10.1) (Normal Mode startup wait time (tSTA max 173ms, section 10.1))
#define DF_TIMEOUT_MS 20 // Data Fetch 타임아웃 (섹션 10.6.4) (Data Fetch timeout (section 10.6.4))
#define SLEEP_MODE_MEAS_DELAY_MS 19 // Sleep Mode 측정 대기 시간 (14비트 기준 18.5ms + 여유, 섹션 10.3.2) (Sleep Mode measurement wait time (18.5ms for 14-bit + margin, section 10.3.2))
#define DATA_RESOLUTION_BITS 14 // 데이터 해상도 (8~14비트, 기본 14비트, 섹션 9.2.1) (Data resolution (8-14 bits, default 14 bits, section 9.2.1))
#define VDD_CONTROL_PIN 8 // VDD 제어 디지털 핀 (예: Arduino D8, 사용자 하드웨어에 맞게 수정) (VDD control digital pin (e.g., Arduino D8, modify per hardware))
// 사용자 정의 에러 코드 (데이터시트 표 26, 27 참조) (User-defined error codes (refer to datasheet tables 26, 27))
enum ZSSC3123_Status {
ZSSC3123_OK = 0, // 성공: 정상 동작 (Success: Normal operation)
ZSSC3123_MODE_ERROR, // Command Mode 진입 실패 (Command Mode entry failure)
ZSSC3123_DIAG_ERROR, // 진단 오류 (EEPROM ECC, 센서 오류 등) (Diagnostic error (EEPROM ECC, sensor errors, etc.))
ZSSC3123_I2C_ERROR // I2C 통신 오류 (I2C communication error)
};
// VDD 전원 OFF/ON 함수: Command Mode 진입을 위한 Power-On Reset(POR) 트리거 (VDD Power OFF/ON function: Triggers Power-On Reset (POR) for Command Mode entry)
// 데이터시트 섹션 10.1, 11: POR은 Command Mode 진입을 위해 필요 (Datasheet sections 10.1, 11: POR is required for Command Mode entry)
ZSSC3123_Status ZSSC3123_Power_Cycle() {
digitalWrite(VDD_CONTROL_PIN, LOW); // VDD OFF (로드 스위치 OFF) (Turn VDD OFF (disable load switch))
delay(10); // 안정화 대기 (10ms, 사용자 정의, 데이터시트 그림 11 참조) (Wait for stabilization (10ms, user-defined, refer to datasheet Figure 11))
digitalWrite(VDD_CONTROL_PIN, HIGH); // VDD ON (POR 트리거) (Turn VDD ON (trigger POR))
delay(1); // POR 안정화 대기 (짧은 시간, 섹션 10.1) (Wait for POR stabilization (short duration, section 10.1))
return ZSSC3123_OK; // 성공 반환 (Return success)
}
// Command Mode 확인 함수: Get Revision 명령으로 Command Mode 상태 확인 (Command Mode check function: Verifies Command Mode using Get Revision command)
// 데이터시트 섹션 11: Get Revision(0xB0 00 00)은 Command Mode에서만 응답 (Datasheet section 11: Get Revision (0xB0 00 00) responds only in Command Mode)
ZSSC3123_Status ZSSC3123_Check_Command_Mode() {
uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00}; // Get Revision 명령 (섹션 11.2, 표 28) (Get Revision command (section 11.2, Table 28))
uint8_t rx_buf[3]; // 상태(1바이트) + 데이터(2바이트) (Status (1 byte) + Data (2 bytes))
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(cmd_buf, 3); // 명령 전송 (Send command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check for transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delayMicroseconds(EEPROM_READ_DELAY_US); // 100μs 대기 (EEPROM 읽기 타이밍, 섹션 12) (Wait 100μs (EEPROM read timing, section 12))
Wire.requestFrom(ZSSC3123_I2C_ADDR, 3); // 3바이트 요청 (Request 3 bytes)
if (Wire.available() != 3) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
for (uint8_t i = 0; i < 3; i++) { // 3바이트 읽기 루프 (Loop to read 3 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 26: Valid=1, Busy=0; 표 27: Diagnostic=0) (Check status bits (Table 26: Valid=1, Busy=0; Table 27: Diagnostic=0))
if (!(rx_buf[0] & 0x40) || (rx_buf[0] & 0x80) || (rx_buf[0] & 0x0F)) { // 유효하지 않거나 바쁘거나 진단 오류 (Invalid, busy, or diagnostic error)
return ZSSC3123_MODE_ERROR; // Command Mode가 아니거나 오류 발생 (Not in Command Mode or error occurred)
}
return ZSSC3123_OK; // Command Mode 확인 성공 (Command Mode verified successfully)
}
// Command Mode 진입 함수: Start_CM 명령으로 Command Mode 진입 (Command Mode entry function: Enters Command Mode with Start_CM command)
// 데이터시트 섹션 11: Start_CM(0xA0 00 00)은 POR 직후 Command Window에서 전송 (Datasheet section 11: Start_CM (0xA0 00 00) sent in Command Window after POR)
ZSSC3123_Status ZSSC3123_Enter_Command_Mode() {
uint8_t cmd_buf[3] = {0xA0, 0x00, 0x00}; // Start_CM 명령 (섹션 11.2, 표 28) (Start_CM command (section 11.2, Table 28))
if (ZSSC3123_Power_Cycle() != ZSSC3123_OK) { // POR 실행 (Execute POR)
return ZSSC3123_I2C_ERROR; // 전원 제어 실패 (Power control failure)
}
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(cmd_buf, 3); // Start_CM 명령 전송 (Send Start_CM command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
if (ZSSC3123_Check_Command_Mode() != ZSSC3123_OK) { // Command Mode 진입 확인 (Verify Command Mode entry)
return ZSSC3123_MODE_ERROR; // Command Mode 진입 실패 (Command Mode entry failed)
}
return ZSSC3123_OK; // 성공 (Success)
}
// Normal Operation Mode 전환 함수: Start_NOM 명령으로 Normal Mode 진입 (Normal Operation Mode transition function: Enters Normal Mode with Start_NOM command)
// 데이터시트 섹션 10.1: Start_NOM(0x80 00 00), tSTA 대기 (Datasheet section 10.1: Start_NOM (0x80 00 00), wait for tSTA)
ZSSC3123_Status ZSSC3123_Enter_Normal_Mode() {
uint8_t cmd_buf[3] = {0x80, 0x00, 0x00}; // Start_NOM 명령 (섹션 11.2, 표 28) (Start_NOM command (section 11.2, Table 28))
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(cmd_buf, 3); // 명령 전송 (Send command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delay(NORMAL_MODE_STARTUP_MS); // 초기화 완료 대기 (tSTA 최대 173ms, 섹션 10.1) (Wait for initialization (tSTA max 173ms, section 10.1))
return ZSSC3123_OK; // 성공 (Success)
}
// Revision 읽기 함수: Command Mode에서 칩 Revision 정보 읽기 (Revision read function: Reads chip revision in Command Mode)
// 데이터시트 섹션 11.2: Get Revision(0xB0 00 00) (Datasheet section 11.2: Get Revision (0xB0 00 00))
ZSSC3123_Status ZSSC3123_Get_Revision(uint16_t *revision) {
if (ZSSC3123_Check_Command_Mode() != ZSSC3123_OK) { // Command Mode 확인 (Check Command Mode)
return ZSSC3123_MODE_ERROR; // Command Mode가 아님 (Not in Command Mode)
}
uint8_t cmd_buf[3] = {0xB0, 0x00, 0x00}; // Get Revision 명령 (Get Revision command)
uint8_t rx_buf[3]; // 상태(1) + Revision(2) (Status (1) + Revision (2))
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(cmd_buf, 3); // 명령 전송 (Send command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delayMicroseconds(EEPROM_READ_DELAY_US); // 100μs 대기 (Wait 100μs)
Wire.requestFrom(ZSSC3123_I2C_ADDR, 3); // 3바이트 요청 (Request 3 bytes)
if (Wire.available() != 3) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
for (uint8_t i = 0; i < 3; i++) { // 3바이트 읽기 (Read 3 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 26: Valid=1, Busy=0; 표 27: Diagnostic=0) (Check status bits (Table 26: Valid=1, Busy=0; Table 27: Diagnostic=0))
if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) { // 진단 오류 확인 (Check for diagnostic errors)
return ZSSC3123_DIAG_ERROR; // 진단 오류 반환 (Return diagnostic error)
}
*revision = (rx_buf[1] << 8) | rx_buf[2]; // 16비트 Revision 값 조합 (Combine 16-bit Revision value)
return ZSSC3123_OK; // 성공 (Success)
}
// EEPROM 특정 주소 읽기 함수: 지정된 주소에서 16비트 데이터 읽기 (EEPROM specific address read function: Reads 16-bit data from specified address)
// 데이터시트 섹션 12: 주소 0x00~0x1F (Datasheet section 12: Addresses 0x00 to 0x1F)
ZSSC3123_Status ZSSC3123_EEPROM_Read(uint8_t addr, uint16_t *data) {
if (addr > 0x1F) return ZSSC3123_I2C_ERROR; // 주소 범위 초과 (Address out of range)
if (ZSSC3123_Check_Command_Mode() != ZSSC3123_OK) { // Command Mode 확인 (Check Command Mode)
if (ZSSC3123_Enter_Command_Mode() != ZSSC3123_OK) { // Command Mode 진입 시도 (Attempt to enter Command Mode)
return ZSSC3123_MODE_ERROR; // 진입 실패 (Entry failure)
}
}
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(addr); // 직접 주소 지정 (표 28) (Direct address specification (Table 28))
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delayMicroseconds(EEPROM_READ_DELAY_US); // 100μs 대기 (Wait 100μs)
Wire.requestFrom(ZSSC3123_I2C_ADDR, 3); // 3바이트 요청 (Request 3 bytes)
if (Wire.available() != 3) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
uint8_t rx_buf[3]; // 수신 버퍼 (Receive buffer)
for (uint8_t i = 0; i < 3; i++) { // 3바이트 읽기 (Read 3 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 26, 27) (Check status bits (Tables 26, 27))
if ((rx_buf[0] & 0x80) || !(rx_buf[0] & 0x40) || (rx_buf[0] & 0x0F)) { // 진단 오류 확인 (Check for diagnostic errors)
return ZSSC3123_DIAG_ERROR; // 진단 오류 반환 (Return diagnostic error)
}
*data = (rx_buf[1] << 8) | rx_buf[2]; // 16비트 데이터 조합 (Combine 16-bit data)
return ZSSC3123_OK; // 성공 (Success)
}
// EEPROM 특정 주소 쓰기 함수: 지정된 주소에 16비트 데이터 쓰기 (EEPROM specific address write function: Writes 16-bit data to specified address)
// 데이터시트 섹션 12: 주소 0x40~0x5F로 쓰기 (Datasheet section 12: Write to addresses 0x40 to 0x5F)
ZSSC3123_Status ZSSC3123_EEPROM_Write(uint8_t addr, uint16_t data) {
if (addr > 0x1F || addr > EEPROM_MAX_USER_ADDR) { // 주소 범위 및 예약 영역 확인 (Check address range and reserved area)
return ZSSC3123_I2C_ERROR; // 주소 오류 반환 (Return address error)
}
if (ZSSC3123_Check_Command_Mode() != ZSSC3123_OK) { // Command Mode 확인 (Check Command Mode)
if (ZSSC3123_Enter_Command_Mode() != ZSSC3123_OK) { // Command Mode 진입 시도 (Attempt to enter Command Mode)
return ZSSC3123_MODE_ERROR; // 진입 실패 (Entry failure)
}
}
uint8_t tx_buf[3] = {0x40 | addr, (data >> 8) & 0xFF, data & 0xFF}; // 쓰기 명령 준비 (Prepare write command)
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(tx_buf, 3); // 데이터 전송 (Send data)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delay(EEPROM_WRITE_DELAY_MS); // 쓰기 완료 대기 (12ms) (Wait for write completion (12ms))
uint16_t read_data; // 검증용 데이터 (Data for verification)
if (ZSSC3123_EEPROM_Read(addr, &read_data) != ZSSC3123_OK || read_data != data) { // 쓰기 검증 (Verify write)
return ZSSC3123_I2C_ERROR; // 검증 실패 (Verification failure)
}
return ZSSC3123_OK; // 성공 (Success)
}
// 전체 EEPROM 읽기 함수: 모든 워드(0x00~0x1F) 순차 읽기 (Full EEPROM read function: Sequentially reads all words (0x00 to 0x1F))
// 데이터시트 섹션 12 (Datasheet section 12)
ZSSC3123_Status ZSSC3123_EEPROM_Read_All(uint16_t *buffer) {
for (uint8_t addr = 0x00; addr < EEPROM_NUM_WORDS; addr++) { // 모든 주소 순회 (Iterate through all addresses)
if (ZSSC3123_EEPROM_Read(addr, &buffer[addr]) != ZSSC3123_OK) { // 각 주소 읽기 (Read each address)
return ZSSC3123_I2C_ERROR; // 읽기 실패 (Read failure)
}
}
return ZSSC3123_OK; // 성공 (Success)
}
// 전체 EEPROM 쓰기 함수: 예약 영역(0x1D~0x1F) 제외하고 쓰기 (Full EEPROM write function: Writes all words, skipping reserved area (0x1D-0x1F))
// 데이터시트 섹션 12 (Datasheet section 12)
ZSSC3123_Status ZSSC3123_EEPROM_Write_All(const uint16_t *buffer) {
for (uint8_t addr = 0x00; addr < EEPROM_NUM_WORDS; addr++) { // 모든 주소 순회 (Iterate through all addresses)
if (addr > EEPROM_MAX_USER_ADDR) continue; // 예약 영역 스킵 (Skip reserved area)
if (ZSSC3123_EEPROM_Write(addr, buffer[addr]) != ZSSC3123_OK) { // 각 주소 쓰기 (Write each address)
return ZSSC3123_I2C_ERROR; // 쓰기 실패 (Write failure)
}
}
return ZSSC3123_OK; // 성공 (Success)
}
// 초기 설정 함수: EEPROM 설정 후 Normal Mode로 전환 (Initialization function: Configures EEPROM and switches to Normal Mode)
// 데이터시트 섹션 12: Continuous Mode, 14비트 해상도 설정 예시 (Datasheet section 12: Example configuration for Continuous Mode, 14-bit resolution)
ZSSC3123_Status ZSSC3123_Initialize_Settings() {
if (ZSSC3123_Enter_Command_Mode() != ZSSC3123_OK) { // Command Mode 진입 (Enter Command Mode)
return ZSSC3123_I2C_ERROR; // 진입 실패 (Entry failure)
}
// ZMDI_Config (0x02): Continuous Mode, Power_Down_Period=0 (표 29) (ZMDI_Config (0x02): Continuous Mode, Power_Down_Period=0 (Table 29))
if (ZSSC3123_EEPROM_Write(0x02, 0x0000) != ZSSC3123_OK) { // 설정 쓰기 (Write configuration)
return ZSSC3123_I2C_ERROR; // 쓰기 실패 (Write failure)
}
// C_Config (0x06): 싱글 엔디드, 14비트, Mult1, 기본 오프셋/참조 (표 30) (C_Config (0x06): Single-ended, 14-bit, Mult1, default offset/reference (Table 30))
if (ZSSC3123_EEPROM_Write(0x06, 0xF000) != ZSSC3123_OK) { // 설정 쓰기 (Write configuration)
return ZSSC3123_I2C_ERROR; // 쓰기 실패 (Write failure)
}
// T_Config (0x11): 온도 설정 기본 (표 31) (T_Config (0x11): Default temperature settings (Table 31))
if (ZSSC3123_EEPROM_Write(0x11, 0x0000) != ZSSC3123_OK) { // 설정 쓰기 (Write configuration)
return ZSSC3123_I2C_ERROR; // 쓰기 실패 (Write failure)
}
// Cust_Config (0x1C): 기본 설정 (표 32) (Cust_Config (0x1C): Default settings (Table 32))
if (ZSSC3123_EEPROM_Write(0x1C, 0x0000) != ZSSC3123_OK) { // 설정 쓰기 (Write configuration)
return ZSSC3123_I2C_ERROR; // 쓰기 실패 (Write failure)
}
if (ZSSC3123_Enter_Normal_Mode() != ZSSC3123_OK) { // Normal Mode 전환 (Switch to Normal Mode)
return ZSSC3123_I2C_ERROR; // 전환 실패 (Transition failure)
}
return ZSSC3123_OK; // 성공 (Success)
}
// Raw Data 수집 함수: Normal Mode에서 Data Fetch로 원시 데이터 읽기 (Raw Data acquisition function: Reads raw data in Normal Mode using Data Fetch)
// 데이터시트 섹션 10.6.4 (Datasheet section 10.6.4)
ZSSC3123_Status ZSSC3123_Read_Raw_Data(uint16_t *raw_capacitance, uint16_t *raw_temperature) {
uint8_t df_cmd = 0x00; // Data Fetch 명령 (섹션 10.6.4, 그림 19) (Data Fetch command (section 10.6.4, Figure 19))
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2) (Status (1) + Capacitance (2) + Temperature (2))
if (ZSSC3123_Initialize_Settings() != ZSSC3123_OK) { // 초기 설정 수행 (Perform initial settings)
return ZSSC3123_I2C_ERROR; // 초기화 실패 (Initialization failure)
}
if (ZSSC3123_Check_Command_Mode() == ZSSC3123_OK) { // Normal Mode 확인 (Check Normal Mode)
if (ZSSC3123_Enter_Normal_Mode() != ZSSC3123_OK) { // Normal Mode 전환 (Switch to Normal Mode)
return ZSSC3123_I2C_ERROR; // 전환 실패 (Transition failure)
}
}
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(df_cmd); // Data Fetch 명령 전송 (Send Data Fetch command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
Wire.requestFrom(ZSSC3123_I2C_ADDR, 5); // 5바이트 요청 (Request 5 bytes)
if (Wire.available() != 5) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
for (uint8_t i = 0; i < 5; i++) { // 5바이트 읽기 (Read 5 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0) (Check status bits (Table 16: Valid=1, Busy=0, Diagnostic=0))
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) { // 진단 오류 확인 (Check for diagnostic errors)
return ZSSC3123_DIAG_ERROR; // 진단 오류 반환 (Return diagnostic error)
}
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2]; // 정전용량 데이터 조합 (Combine capacitance data)
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4]; // 온도 데이터 조합 (Combine temperature data)
*raw_capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
*raw_temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
return ZSSC3123_OK; // 성공 (Success)
}
// Update Mode에서 센서 데이터 읽기 함수: Continuous Update Mode에서 Data Fetch (Sensor data read function in Update Mode: Data Fetch in Continuous Update Mode)
// 데이터시트 섹션 10.3.1, 10.6.4 (Datasheet sections 10.3.1, 10.6.4)
ZSSC3123_Status ZSSC3123_Read_Sensor_Data_Update_Mode(uint16_t *capacitance, uint16_t *temperature) {
uint8_t df_cmd = 0x00; // Data Fetch 명령 (Data Fetch command)
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2) (Status (1) + Capacitance (2) + Temperature (2))
if (ZSSC3123_Check_Command_Mode() == ZSSC3123_OK) { // Normal Mode 확인 (Check Normal Mode)
if (ZSSC3123_Enter_Normal_Mode() != ZSSC3123_OK) { // Normal Mode 전환 (Switch to Normal Mode)
return ZSSC3123_I2C_ERROR; // 전환 실패 (Transition failure)
}
}
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(df_cmd); // Data Fetch 명령 전송 (Send Data Fetch command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
Wire.requestFrom(ZSSC3123_I2C_ADDR, 5); // 5바이트 요청 (Request 5 bytes)
if (Wire.available() != 5) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
for (uint8_t i = 0; i < 5; i++) { // 5바이트 읽기 (Read 5 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0) (Check status bits (Table 16: Valid=1, Busy=0, Diagnostic=0))
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) { // 진단 오류 확인 (Check for diagnostic errors)
return ZSSC3123_DIAG_ERROR; // 진단 오류 반환 (Return diagnostic error)
}
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2]; // 정전용량 데이터 조합 (Combine capacitance data)
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4]; // 온도 데이터 조합 (Combine temperature data)
*capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
*temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
return ZSSC3123_OK; // 성공 (Success)
}
// Sleep Mode에서 센서 데이터 읽기 함수: Measurement Request 후 Data Fetch (Sensor data read function in Sleep Mode: Data Fetch after Measurement Request)
// 데이터시트 섹션 10.3.2, 10.6.4, 10.6.5 (Datasheet sections 10.3.2, 10.6.4, 10.6.5)
ZSSC3123_Status ZSSC3123_Read_Sensor_Data_Sleep_Mode(uint16_t *capacitance, uint16_t *temperature) {
uint8_t df_cmd = 0x00; // Data Fetch 명령 (Data Fetch command)
uint8_t rx_buf[5]; // 상태(1) + Capacitance(2) + Temperature(2) (Status (1) + Capacitance (2) + Temperature (2))
if (ZSSC3123_Check_Command_Mode() == ZSSC3123_OK) { // Normal Mode 확인 (Check Normal Mode)
if (ZSSC3123_Enter_Normal_Mode() != ZSSC3123_OK) { // Normal Mode 전환 (Switch to Normal Mode)
return ZSSC3123_I2C_ERROR; // 전환 실패 (Transition failure)
}
}
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // Measurement Request (빈 쓰기) (Measurement Request (empty write))
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
delay(SLEEP_MODE_MEAS_DELAY_MS); // 측정 완료 대기 (18.5ms + 여유) (Wait for measurement completion (18.5ms + margin))
Wire.beginTransmission(ZSSC3123_I2C_ADDR); // I2C 전송 시작 (Start I2C transmission)
Wire.write(df_cmd); // Data Fetch 명령 전송 (Send Data Fetch command)
if (Wire.endTransmission() != 0) { // 전송 실패 확인 (Check transmission failure)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
Wire.requestFrom(ZSSC3123_I2C_ADDR, 5); // 5바이트 요청 (Request 5 bytes)
if (Wire.available() != 5) { // 수신 데이터 크기 확인 (Check received data size)
return ZSSC3123_I2C_ERROR; // I2C 오류 반환 (Return I2C error)
}
for (uint8_t i = 0; i < 5; i++) { // 5바이트 읽기 (Read 5 bytes)
rx_buf[i] = Wire.read(); // 데이터 읽기 (Read data)
}
// 상태 비트 확인 (표 16: Valid=1, Busy=0, Diagnostic=0) (Check status bits (Table 16: Valid=1, Busy=0, Diagnostic=0))
if ((rx_buf[0] & 0xC0) != 0x40 || (rx_buf[0] & 0x0F)) { // 진단 오류 확인 (Check for diagnostic errors)
return ZSSC3123_DIAG_ERROR; // 진단 오류 반환 (Return diagnostic error)
}
uint16_t temp_cap = (rx_buf[1] << 8) | rx_buf[2]; // 정전용량 데이터 조합 (Combine capacitance data)
uint16_t temp_temp = (rx_buf[3] << 8) | rx_buf[4]; // 온도 데이터 조합 (Combine temperature data)
*capacitance = temp_cap >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
*temperature = temp_temp >> (16 - DATA_RESOLUTION_BITS); // 14비트 정렬 (Align to 14 bits)
return ZSSC3123_OK; // 성공 (Success)
}
// Arduino setup 함수: I2C 및 VDD 핀 초기화 (Arduino setup function: Initializes I2C and VDD pin)
void setup() {
Wire.begin(); // I2C 통신 초기화 (Initialize I2C communication)
pinMode(VDD_CONTROL_PIN, OUTPUT); // VDD 제어 핀 설정 (Configure VDD control pin)
digitalWrite(VDD_CONTROL_PIN, HIGH); // 초기 VDD ON (Turn VDD ON initially)
}
// Arduino loop 함수: 데이터 읽기 및 시리얼 출력 예시 (Arduino loop function: Example of reading data and serial output)
void loop() {
uint16_t capacitance, temperature; // 정전용량 및 온도 변수 (Capacitance and temperature variables)
// Raw 데이터 읽기 시도 (Attempt to read raw data)
if (ZSSC3123_Read_Raw_Data(&capacitance, &temperature) == ZSSC3123_OK) {
Serial.begin(9600); // 시리얼 통신 시작 (Start serial communication)
Serial.print("Capacitance: "); // 정전용량 출력 라벨 (Print capacitance label)
Serial.println(capacitance); // 정전용량 출력 (Print capacitance)
Serial.print("Temperature: "); // 온도 출력 라벨 (Print temperature label)
Serial.println(temperature); // 온도 출력 (Print temperature)
} else {
Serial.begin(9600); // 시리얼 통신 시작 (Start serial communication)
Serial.println("Error reading data"); // 오류 메시지 출력 (Print error message)
}
delay(1000); // 1초 대기 (Wait 1 second)
}
3.2 타이밍 및 오류 처리
코드는 데이터시트의 타이밍 사양(The code adheres to the datasheet’s timing specifications:)
Function | Timing | Datasheet Section |
EEPROM 읽기 (EEPROM Read) | 100µs 지연 (100µs delay) | 12 |
EEPROM 쓰기 (EEPROM Write) | 12ms 지연 (12ms delay) | 12 |
Normal Mode 시작 (Normal Mode Start) | 173ms 대기 (173ms wait) | 10.1 |
Sleep Mode 측정 (Sleep Mode Measurement) | 18.5ms + 여유 (18.5ms + margin) | 10.3.2 |
오류 처리는 ZSSC3123_Status
열거형을 사용하여 I2C 통신 오류, Command Mode 진입 실패, 진단 오류를 처리하며, 상태 비트(표 16, 26, 27)를 확인하여 데이터 유효성을 검증합니다.
4. 결과
- 정확한 데이터 수집: 14비트 해상도로 정전용량 및 온도 데이터를 성공적으로 읽음(섹션 9.2.1).
- 저전력 동작: Sleep Mode에서 1µA 이하의 전류 소모(섹션 6.2).
- 견고한 오류 처리: I2C 통신 및 진단 오류를 효과적으로 감지.
- 유연한 설정: EEPROM을 통해 Continuous Mode 및 다양한 해상도 설정 가능(섹션 12).
'아날로그회로(Analog Circuit) > ADC관련' 카테고리의 다른 글
AD7124 24비트 ADC STM32 HAL 기반 디바이스 드라이버 구현 (0) | 2025.09.04 |
---|---|
ADS124S08 24비트 ADC STM32 HAL 기반 디바이스 드라이버 구현 (1) | 2025.08.28 |
ZSC31015 Sensor Signal Conditioner IC 드라이버 구현: STM32를 활용한 Zacwire 인터페이싱 (4) | 2025.08.25 |
ADS114S08 16비트 ADC STM32 HAL 기반 디바이스 드라이버 구현 (0) | 2025.08.24 |
PT100/PT1000 RTD 센서용 MAX31865 온도 변환 IC STM32 디바이스 드라이버 구현 (3) | 2025.08.24 |
PGA302 Sensor Signal Conditioner IC STM32용 I2C 드라이버 구현 (0) | 2025.08.20 |
ZSC31050 Sensor Signal Conditioner IC STM32용 I2C 드라이버 구현 (0) | 2025.08.16 |
ZSSC3230 Sensor Signal Conditioner IC 보정 절차 및 Calibration Math 분석 (1) | 2025.08.15 |