요약
ESP32를 아두이노에서 아날로그 값을 ADC와 전압으로 읽는 방법에 대해서 알아보겠습니다.
analogRead(PIN)와 analogReadMilliVolts(PIN)를 사용해서 값을 12bit와 3.3V로 읽는 방법입니다.
wokwi에서 ESP32 아날로그 값 읽는 방법
wokwi에서 프로젝트 설정하는 방법은 ESP32 → 장치설정 → ESP32 웹에서 간단히 시뮬레이션 테스트 wokwi에서 확인하실 수 있습니다. (아래 링크로도 확인 가능합니다.)
wokwi에 접속해서 먼저 프로젝트를 생성합니다.
바로 SAVE하셔서 ADC_TEST 이름으로 지정해 줍니다.
Public으로 저장하시면 됩니다.(유료 결제하면 Private 할 수 있으나 그냥 Public으로 진행하는 게 좋습니다.)
Wokwi에 가변저항 ADC 값 읽는 방법
먼저 아래의 사진처럼 + 버튼을 눌러서 Potentionmeter 를 추가해 줍니다.
가변저항에는 GND, SIG, VCC 이렇게 3개의 핀이 있습니다.
아래와 같이 VCC → 3V3, SIG → 34, GND → GND 이렇게 연결 해줍니다.
GND와 VCC를 방향이 반대일 경우도 마찬가지로 동작합니다.
가변저항은 내부 저항의 위치를 변화 시킴으로써 전압의 차이를 SIG로 내보내는 역할이라 VCC, GND를 잘못 연결하셔도 안전합니다.
아래의 코드를 복사 붙여 넣기 해서 실행하면 됩니다.
void setup() {
Serial.begin(115200); // 시리얼 통신 속도 설정
analogReadResolution(12); // 아날로그 입력 해상도 설정
}
void loop() {
// 아날로그 핀에서 값을 읽기
int analogValue = analogRead(34); // 핀 34에서 아날로그 값 읽기
int analogVolts = analogReadMilliVolts(34); // 밀리볼트(mV) 단위로 변환
// 시리얼 모니터에 출력
Serial.printf("ADC analog value = %d\n", analogValue);
Serial.printf("ADC millivolts value = %d\n", analogVolts);
delay(100); // 일정 시간 지연
}
analogReadResolution(12)는 아날로그 입력의 해상도를 12비트로 설정합니다. (이진수로 0b1111 1111 1111 = 4095)
이는 아날로그 입력값의 범위가 0부터 4095까지의 값을 가질 수 있음을 의미합니다.
analogRead(34)는 핀 34에서 아날로그 값을 읽어옵니다. 이 값은 0부터 4095까지의 범위로 나타납니다.
analogRead의 함수를 살펴보면 아래와 같습니다.
- 아래 더보기를 누르면 함수를 보실 수 있습니다.
uint16_t __analogRead(uint8_t pin)
{
int8_t channel = digitalPinToAnalogChannel(pin);
int value = 0;
esp_err_t r = ESP_OK;
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return value;
}
__adcAttachPin(pin);
if(channel > (SOC_ADC_MAX_CHANNEL_NUM - 1)){
channel -= SOC_ADC_MAX_CHANNEL_NUM;
r = adc2_get_raw( channel, __analogWidth, &value);
if ( r == ESP_OK ) {
return mapResolution(value);
} else if ( r == ESP_ERR_INVALID_STATE ) {
log_e("GPIO%u: %s: ADC2 not initialized yet.", pin, esp_err_to_name(r));
} else if ( r == ESP_ERR_TIMEOUT ) {
log_e("GPIO%u: %s: ADC2 is in use by Wi-Fi. Please see https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-reference/peripherals/adc.html#adc-limitations for more info", pin, esp_err_to_name(r));
} else {
log_e("GPIO%u: %s", pin, esp_err_to_name(r));
}
} else {
value = adc1_get_raw(channel);
return mapResolution(value);
}
return mapResolution(value);
}
bool __adcAttachPin(uint8_t pin){
int8_t channel = digitalPinToAnalogChannel(pin);
if(channel < 0){
log_e("Pin %u is not ADC pin!", pin);
return false;
}
__analogInit();
int8_t pad = digitalPinToTouchChannel(pin);
if(pad >= 0){
#if CONFIG_IDF_TARGET_ESP32
uint32_t touch = READ_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG);
if(touch & (1 << pad)){
touch &= ~((1 << (pad + SENS_TOUCH_PAD_OUTEN2_S))
| (1 << (pad + SENS_TOUCH_PAD_OUTEN1_S))
| (1 << (pad + SENS_TOUCH_PAD_WORKEN_S)));
WRITE_PERI_REG(SENS_SAR_TOUCH_ENABLE_REG, touch);
}
#endif
}
#if SOC_DAC_SUPPORTED
else if(pin == DAC_CHANNEL_1_GPIO_NUM){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC1_REG, RTC_IO_PDAC1_XPD_DAC | RTC_IO_PDAC1_DAC_XPD_FORCE);//stop dac1
} else if(pin == DAC_CHANNEL_2_GPIO_NUM){
CLEAR_PERI_REG_MASK(RTC_IO_PAD_DAC2_REG, RTC_IO_PDAC2_XPD_DAC | RTC_IO_PDAC2_DAC_XPD_FORCE);//stop dac2
}
#endif
pinMode(pin, ANALOG);
__analogSetPinAttenuation(pin, (__pin_attenuation[pin] != ADC_ATTENDB_MAX)?__pin_attenuation[pin]:__analogAttenuation);
return true;
}
ESP32에서 ADC에 할당된 핀이 아닐 경우 return하며 할당된 핀일 경우 __adcAttachPIn 함수를 호출해서 ADC channel 값을 매칭시켜줍니다.
그리고 해당 채널의 값을 반환하여 우리가 원하는 ADC 값을 얻게 됩니다. → value = adc1_get_raw(channel);
마찬가지로 analogReadMilliVolts(34)는 핀 34의 아날로그 값을 밀리볼트(mV) 단위로 변환하여 반환합니다.
analogReadMilliVolts 함수는 아래와 같습니다.
- 아래 더보기를 누르면 함수를 볼 수 있습니다.
digitalPinToAnalogChannel(pin): 입력된 디지털 핀 번호를 아날로그 채널 번호로 변환합니다.
만약 변환에 실패하면 함수는 -1을 반환하여 종료합니다.
아날로그 입력값을 읽기 전에, 설정된 아날로그 참조전압(__analogVRef)을 확인하고 설정합니다.
참조전압이 설정되지 않은 경우, eFuse의 값이나 기본값(DEFAULT_VREF)을 이용하여 설정합니다.
아날로그 입력값을 읽어옵니다. 이때, 적용된 감쇄 설정(__analogAttenuation)과 너비 설정(__analogWidth)에 따라서 값을 읽습니다.
ADC를 특성화하고, 특성화된 값들을 출력합니다. 이 때, eFuse 값이나 GPIO를 통해 설정된 참조전압에 따라 특성화를 진행합니다.
마지막으로 esp_adc_cal_raw_to_voltage() 함수를 사용하여 읽은 아날로그 값을 밀리볼트(mV) 단위로 변환하여 반환합니다.
이제 시작을 눌러서 실행하면 됩니다.
delay(100)이므로 0.1초마다 아날로그 값을 모니터로 출력합니다.
아두이노에서 아날로그 값 읽기
이제 아두이노를 실행하여 실제 아날로그 값을 읽어봅시다.
사진은 b10k 로터리형 가변저항이며 인터넷에서 쉽게 구매하실 수 있습니다.
위의 가변저항이 아니어도 아래와 같은 가변저항으로 사용해도 됩니다.
사진에 3가닥이 wokwi와 똑같이 VCC,SIG,GND 입니다.
극성은 따로 없으니 가운데 SIG만 34핀에 잘 연결해주시면 됩니다.
저는 아래처럼 회로를 빵판에 구성했습니다.
아두이노 세팅 및 코드 작성
ESP32를 아두이노 세팅하는 방법은 ESP32 → 장치설정 → ESP32 아두이노 2 설치를 찾아가셔도 되고 아래의 링크로도 확인 가능합니다. [ESP32/장치설정] - ESP32 아두이노 2 설치
코드는 wokwi에서 사용한 코드 그대로를 복사 붙여 넣기 해주면 됩니다.
업로드하시고 결과를 확인하면 wokwi와 정확하게 똑같이 동작합니다.
이렇게 ESP32 아날로그를 analogRead와 analogReadMilliVolts를 사용하여 ADC 읽는 방법을 배웠습니다.
좀 더 ADC를 읽는 방식이 궁금하시면 위의 접은글 안에 코드를 보시고 더 궁금하시면 댓글로 남겨주세요.
오늘도 긴 글 읽어주셔서 감사합니다!
'ESP32 > 센서활용' 카테고리의 다른 글
[아두이노] ESP32 LED 제어하는 방법 (디지털 ON/OFF 방식) (0) | 2024.02.21 |
---|