테스트 완료 8ch 정상작동
This commit is contained in:
321
ads8688_esp32_fixed.ino
Normal file
321
ads8688_esp32_fixed.ino
Normal file
@@ -0,0 +1,321 @@
|
||||
/*
|
||||
* ESP32 WROOM32D + ADS8688 Test Code
|
||||
* Based on working Orange Pi 5 SPI implementation
|
||||
*
|
||||
* Connections:
|
||||
* ESP32 VSPI Pins:
|
||||
* - SCLK: GPIO18
|
||||
* - MISO: GPIO19
|
||||
* - MOSI: GPIO23
|
||||
* - CS: GPIO5
|
||||
* - RST: GPIO17
|
||||
*/
|
||||
|
||||
#include <SPI.h>
|
||||
|
||||
// SPI 핀 정의
|
||||
#define ADS8688_CS 5 // Chip Select
|
||||
#define ADS8688_RST 17 // Reset
|
||||
|
||||
// ADS8688 명령어 레지스터 (Orange Pi 코드 참조)
|
||||
#define NO_OP 0x00 // Continue operation in previous mode
|
||||
#define STDBY 0x82 // Device is placed into standby mode
|
||||
#define PWR_DN 0x83 // Device is powered down
|
||||
#define RST 0x85 // Program register is reset to default
|
||||
#define AUTO_RST 0xA0 // Auto mode enabled following a reset
|
||||
#define MAN_Ch_0 0xC0 // Channel 0 input is selected
|
||||
#define MAN_Ch_1 0xC4 // Channel 1 input is selected
|
||||
#define MAN_Ch_2 0xC8 // Channel 2 input is selected
|
||||
#define MAN_Ch_3 0xCC // Channel 3 input is selected
|
||||
#define MAN_Ch_4 0xD0 // Channel 4 input is selected
|
||||
#define MAN_Ch_5 0xD4 // Channel 5 input is selected
|
||||
#define MAN_Ch_6 0xD8 // Channel 6 input is selected
|
||||
#define MAN_Ch_7 0xDC // Channel 7 input is selected
|
||||
|
||||
// 레지스터 주소
|
||||
#define AUTO_SEQ_EN 0x01 // Auto Sequencing Enable
|
||||
#define CH_PWR_DN 0x02 // Channel Power Down
|
||||
|
||||
// 범위 선택 레지스터
|
||||
#define RG_Ch_0 0x05
|
||||
#define RG_Ch_1 0x06
|
||||
#define RG_Ch_2 0x07
|
||||
#define RG_Ch_3 0x08
|
||||
#define RG_Ch_4 0x09
|
||||
#define RG_Ch_5 0x0A
|
||||
#define RG_Ch_6 0x0B
|
||||
#define RG_Ch_7 0x0C
|
||||
|
||||
// 전압 범위 설정
|
||||
#define R0 0x00 // ±10.24V
|
||||
#define R1 0x01 // ±5.12V
|
||||
#define R2 0x02 // ±2.56V
|
||||
#define R3 0x03 // ±1.28V
|
||||
|
||||
SPIClass *vspi = NULL;
|
||||
|
||||
// 샘플링 설정
|
||||
#define SAMPLING_RATE_HZ 500
|
||||
#define SAMPLE_INTERVAL_US 2000
|
||||
#define SAMPLES_PER_SECOND 500
|
||||
|
||||
// 8채널 데이터 버퍼
|
||||
uint32_t channelSum[8];
|
||||
uint16_t sampleCount = 0;
|
||||
static float vref = 4.096;
|
||||
|
||||
// 함수 선언
|
||||
void resetADS8688();
|
||||
void initADS8688();
|
||||
void writeRegister(uint8_t reg, uint8_t value);
|
||||
uint8_t readRegister(uint8_t reg);
|
||||
uint16_t cmdRegister(uint8_t cmd);
|
||||
uint16_t noOp();
|
||||
void setChannelRange(uint8_t ch, uint8_t range);
|
||||
void setGlobalRange(uint8_t range);
|
||||
void setChannelSPD(uint8_t flag);
|
||||
uint16_t powerDown();
|
||||
uint16_t standBy();
|
||||
uint16_t reset();
|
||||
uint16_t autoRst();
|
||||
float adcValueToVoltage(uint16_t adcValue);
|
||||
|
||||
void setup() {
|
||||
Serial.begin(115200);
|
||||
delay(1000);
|
||||
|
||||
Serial.println("\n=== ADS8688 Test Started ===");
|
||||
Serial.println("Sampling Rate: 500Hz");
|
||||
Serial.println("Based on Orange Pi 5 working code\n");
|
||||
|
||||
// VSPI 초기화
|
||||
vspi = new SPIClass(VSPI);
|
||||
vspi->begin();
|
||||
|
||||
// CS, RST 핀 설정
|
||||
pinMode(ADS8688_CS, OUTPUT);
|
||||
pinMode(ADS8688_RST, OUTPUT);
|
||||
|
||||
digitalWrite(ADS8688_CS, HIGH);
|
||||
digitalWrite(ADS8688_RST, HIGH);
|
||||
|
||||
// ADS8688 초기화 (Orange Pi 코드 시퀀스 참조)
|
||||
resetADS8688();
|
||||
delay(1);
|
||||
|
||||
powerDown();
|
||||
delayMicroseconds(1000);
|
||||
|
||||
standBy();
|
||||
delayMicroseconds(1000);
|
||||
|
||||
reset();
|
||||
delayMicroseconds(1000);
|
||||
|
||||
setChannelSPD(0xFF); // 모든 채널 활성화
|
||||
setGlobalRange(R1); // ±5.12V 범위
|
||||
delayMicroseconds(1000);
|
||||
|
||||
autoRst();
|
||||
|
||||
Serial.println("ADS8688 Initialized");
|
||||
Serial.println("Starting data acquisition...\n");
|
||||
|
||||
// 채널 합계 초기화
|
||||
for (int i = 0; i < 8; i++) {
|
||||
channelSum[i] = 0;
|
||||
}
|
||||
}
|
||||
|
||||
void loop() {
|
||||
unsigned long startTime = micros();
|
||||
|
||||
// 1초간 500개 샘플 수집
|
||||
for (int sample = 0; sample < SAMPLES_PER_SECOND; sample++) {
|
||||
unsigned long sampleStartTime = micros();
|
||||
|
||||
// 8개 채널 순차적으로 읽기 (Orange Pi 방식)
|
||||
for (int ch = 0; ch < 8; ch++) {
|
||||
uint16_t adcValue = noOp(); // NO_OP으로 이전 변환 결과 읽기
|
||||
channelSum[ch] += adcValue;
|
||||
}
|
||||
|
||||
sampleCount++;
|
||||
|
||||
// 다음 샘플까지 대기
|
||||
unsigned long elapsed = micros() - sampleStartTime;
|
||||
if (elapsed < SAMPLE_INTERVAL_US) {
|
||||
delayMicroseconds(SAMPLE_INTERVAL_US - elapsed);
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long totalTime = micros() - startTime;
|
||||
|
||||
// 1초간의 평균 계산 및 출력
|
||||
Serial.println("========== 1-Second Average (500 samples @ 500Hz) ==========");
|
||||
Serial.print("Actual sampling time: ");
|
||||
Serial.print(totalTime / 1000.0, 2);
|
||||
Serial.println(" ms");
|
||||
Serial.println();
|
||||
|
||||
for (int ch = 0; ch < 8; ch++) {
|
||||
float avgADC = (float)channelSum[ch] / sampleCount;
|
||||
float avgVoltage = adcValueToVoltage((uint16_t)avgADC);
|
||||
|
||||
Serial.print("CH");
|
||||
Serial.print(ch);
|
||||
Serial.print(": Avg ADC = ");
|
||||
Serial.print(avgADC, 2);
|
||||
Serial.print(" (0x");
|
||||
Serial.print((uint16_t)avgADC, HEX);
|
||||
Serial.print(") | Avg Voltage = ");
|
||||
Serial.print(avgVoltage, 4);
|
||||
Serial.println(" V");
|
||||
}
|
||||
|
||||
Serial.print("\nTotal samples collected: ");
|
||||
Serial.println(sampleCount);
|
||||
Serial.println("===========================================================\n");
|
||||
|
||||
// 다음 측정을 위해 리셋
|
||||
for (int i = 0; i < 8; i++) {
|
||||
channelSum[i] = 0;
|
||||
}
|
||||
sampleCount = 0;
|
||||
|
||||
delay(100);
|
||||
}
|
||||
|
||||
// 하드웨어 리셋 (Orange Pi 방식)
|
||||
void resetADS8688() {
|
||||
digitalWrite(ADS8688_RST, HIGH);
|
||||
delayMicroseconds(1000);
|
||||
digitalWrite(ADS8688_RST, LOW);
|
||||
delayMicroseconds(1000);
|
||||
digitalWrite(ADS8688_RST, HIGH);
|
||||
delayMicroseconds(1000);
|
||||
}
|
||||
|
||||
// 레지스터 쓰기 (Orange Pi 코드 참조)
|
||||
void writeRegister(uint8_t reg, uint8_t value) {
|
||||
digitalWrite(ADS8688_CS, LOW);
|
||||
vspi->beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));
|
||||
|
||||
vspi->transfer((reg << 1) | 0x01); // Write command
|
||||
vspi->transfer(value);
|
||||
vspi->transfer(0x00);
|
||||
|
||||
vspi->endTransaction();
|
||||
digitalWrite(ADS8688_CS, HIGH);
|
||||
delayMicroseconds(10);
|
||||
}
|
||||
|
||||
// 레지스터 읽기 (Orange Pi 코드 참조)
|
||||
uint8_t readRegister(uint8_t reg) {
|
||||
digitalWrite(ADS8688_CS, LOW);
|
||||
vspi->beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));
|
||||
|
||||
vspi->transfer((reg << 1) & 0xFE); // Read command
|
||||
vspi->transfer(0x00);
|
||||
vspi->transfer(0x00);
|
||||
|
||||
vspi->endTransaction();
|
||||
digitalWrite(ADS8688_CS, HIGH);
|
||||
delayMicroseconds(10);
|
||||
|
||||
// 더미 전송으로 데이터 읽기
|
||||
digitalWrite(ADS8688_CS, LOW);
|
||||
vspi->beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));
|
||||
|
||||
vspi->transfer(0x00);
|
||||
vspi->transfer(0x00);
|
||||
uint8_t value = vspi->transfer(0x00);
|
||||
|
||||
vspi->endTransaction();
|
||||
digitalWrite(ADS8688_CS, HIGH);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
// 명령 레지스터 실행 (Orange Pi cmdRegister 참조)
|
||||
uint16_t cmdRegister(uint8_t cmd) {
|
||||
uint16_t result = 0;
|
||||
|
||||
digitalWrite(ADS8688_CS, LOW);
|
||||
vspi->beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE1));
|
||||
|
||||
vspi->transfer(cmd);
|
||||
vspi->transfer(0x00);
|
||||
uint8_t msb = vspi->transfer(0x00);
|
||||
uint8_t lsb = vspi->transfer(0x00);
|
||||
|
||||
vspi->endTransaction();
|
||||
digitalWrite(ADS8688_CS, HIGH);
|
||||
delayMicroseconds(1);
|
||||
|
||||
result = (msb << 8) | lsb;
|
||||
return result;
|
||||
}
|
||||
|
||||
// NO_OP 명령 (데이터 읽기용)
|
||||
uint16_t noOp() {
|
||||
return cmdRegister(NO_OP);
|
||||
}
|
||||
|
||||
// Power Down 명령
|
||||
uint16_t powerDown() {
|
||||
return cmdRegister(PWR_DN);
|
||||
}
|
||||
|
||||
// Standby 명령
|
||||
uint16_t standBy() {
|
||||
return cmdRegister(STDBY);
|
||||
}
|
||||
|
||||
// Reset 명령
|
||||
uint16_t reset() {
|
||||
return cmdRegister(RST);
|
||||
}
|
||||
|
||||
// Auto Reset 명령
|
||||
uint16_t autoRst() {
|
||||
return cmdRegister(AUTO_RST);
|
||||
}
|
||||
|
||||
// 채널 범위 설정
|
||||
void setChannelRange(uint8_t ch, uint8_t range) {
|
||||
uint8_t reg;
|
||||
switch (ch) {
|
||||
case 0: reg = RG_Ch_0; break;
|
||||
case 1: reg = RG_Ch_1; break;
|
||||
case 2: reg = RG_Ch_2; break;
|
||||
case 3: reg = RG_Ch_3; break;
|
||||
case 4: reg = RG_Ch_4; break;
|
||||
case 5: reg = RG_Ch_5; break;
|
||||
case 6: reg = RG_Ch_6; break;
|
||||
case 7: reg = RG_Ch_7; break;
|
||||
default: reg = RG_Ch_0; break;
|
||||
}
|
||||
writeRegister(reg, range);
|
||||
}
|
||||
|
||||
// 모든 채널 범위 설정
|
||||
void setGlobalRange(uint8_t range) {
|
||||
for (uint8_t i = 0; i < 8; i++) {
|
||||
setChannelRange(i, range);
|
||||
}
|
||||
}
|
||||
|
||||
// 채널 시퀀스 및 파워 설정
|
||||
void setChannelSPD(uint8_t flag) {
|
||||
writeRegister(AUTO_SEQ_EN, flag);
|
||||
writeRegister(CH_PWR_DN, (uint8_t)~flag);
|
||||
}
|
||||
|
||||
// ADC 값을 전압으로 변환 (±5.12V 범위 - R1)
|
||||
float adcValueToVoltage(uint16_t adcValue) {
|
||||
// ADS8688은 16비트 ADC, 양극성 모드
|
||||
// 0x0000 = -5.12V, 0x8000 = 0V, 0xFFFF = +5.12V
|
||||
float voltage = ((float)adcValue / 65535.0) * 10.24 - 5.12;
|
||||
return voltage;
|
||||
}
|
||||
Reference in New Issue
Block a user