Hardware | ADS1115 16bit 4채널 ADC 를 사용해 보자

|

1. 16 bit ADC


ADC 는 Analog to Digital Converter 의 약자로서, 입력받는 값에 대해 digital 로 표현해 줍니다.

Arduino 에는 이 ADC 가 장착되어 있어서 analog input 에 입력받은 신호에 대해 digital 로 leveling 을 해서 보여줍니다.

즉, analog 값을 digital 로 변환해서 보여주는 것이죠.


참고로, arduino nano 에는 10 bit ADC 가 장착되어 있어서 10 bit (0 ~ 1023) 값으로 표현해 줍니다.


다 좋은데, 민감한 sensor 를 다룰 때에는, 이 10 bit ADC 가 아쉬울 때가 있습니다.

좀더 정밀한 값을 들여다 보고 싶은데, 값과 값의 사이값을 알수가 없는거죠.


이 때 등장하는 것이 외부 ADC 모듈 입니다.

AliExpress 와 arduino 를 사랑하는 사람들의 blog 를 보니 ADS1115 라는 것을 많이 사용하는 군요.


ADS1115 는 Texas Instruments 사의 chip 을 사용한 16 bit ADC 입니다.


ads1115.pdf


- Resolution: 16 Bits

- Programmable Sample Rate: 8 to 860 Samples/Second

- Power Supply/Logic Levels: 2.0V to 5.5V

- Low Current Consumption: Continuous Mode: Only 150µA Single-Shot Mode: Auto Shut-Down

- Internal Low-Drift Voltage Reference

- Internal Oscillator

- Internal PGA: up to x16

- I2C Interface: 4-Pin-Selectable Addresses

- Four Single-Ended or 2 Differential Inputs

- Programmable Comparator


아래 link 의 제품이 적당해 보이네요. 구매합니다.


* I2C ADS1115 16 Bit ADC 4 channel Module with Programmable Gain Amplifier 2.0V to 5.5V for Arduino RPi

https://www.aliexpress.com/item/32850495005.html






2. 도착


그간 업무로 정신 없었는데, 어느샌가 도착했습니다.



블로그 내용을 부풀리기 위해서라도 항상 도착샷을 올리는건 필수 입니다.



저렇코롬 생겼구요.



ALERT 와 ADDR 에 pinheader 는 남겨 놓고 납땜하기로 합니다. 그 덕에 2 pinheader 하나 득템.

그 이유는 이 밑에 설명.





3. Addressing


이 ADS1115 는 I2C 통신을 하는데, 하나의 arduino 와 4개까지 연결할 수 있다 보니, I2C 접근 주소가 겹치지 않게 할 수 있습니다.

방법은 ADDR pin 을 어디로 연결하느냐로 address 를 결정할 수 있습니다.


Adafruit 4-Channel ADC Breakouts

https://learn.adafruit.com/adafruit-4-channel-adc-breakouts


- 0x48 (1001000) ADR -> GND

- 0x49 (1001001) ADR -> VDD

- 0x4A (1001010) ADR -> SDA

- 0x4B (1001011) ADR -> SCL


회로를 꾸밀 때 마다, address 정의를 위한 연결을 해도 되지만, 귀찮겠죠?

또한, addressing 을 위해 I2C 용 핀이나, VCC 로 연결하면 왠지 껄끄럽습니다.


그래서 ground 로 연결하여, 기본 0x48 을 가지게 합니다.

또한, 아래 새다리님의 블로그를 보면, 이 연결을 가장 깔끔하게 처리하셨더군요. 따라쟁이는 바로 따라해 봅니다.


* 16비트, 4채널 ADC ADS1115 아두이노 Test

https://m.blog.naver.com/twophase/220801664646


예전에 파손된 멀티탭 전원선에서 동선 한가닥을 짧게 잘라 내어 아래와 같이 납땜 해 주섰습니다.

캡톤 테이프로 혹시 모를 쇼트를 방지했구요.



i2cdetect 로 addressing 이 잘 되었나 확인해 봅니다.


     0  1  2  3  4  5  6  7  8  9  a  b  c  d  e  f
00:          -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --


흠흠. 잘 되었네요.




4. Layout


* Arduino ADS1115 Module Getting Started Tutorial

http://henrysbench.capnfatz.com/henrys-bench/arduino-voltage-measurements/arduino-ads1115-module-getting-started-tutorial/


위의 tutorial 사이트에서 보면 ADS1115 를 활용하여, arduino 자체 3.3V 출력을 세밀하게 검증해 보는 소스가 있습니다.

따라쟁이는 당연 따라서 검증해 봅니다.


연결은 I2C 용 연결 2가닥과 VCC/GND 그리고, 입력용에 arduino 3.3V output 을 연결합니다.


 ADS1115 | Arduino Nano
------------------------
    VCC  |      5V
    GND  |      GND
    SCL  |      A5
    SDA  |      A4
    A0   |      3.3V
------------------------


그림으로 그려보면 다음과 같습니다.






5. Sketch


이미 관련한 library 가 나와 있기 때문에, library 를 설치합니다.

역시 God Adafruit. 없는게 없습니다.



ads1115 로 검색하면 나오지 않고, ads1x 로 검색해야 나옵니다.


이제 HENRY'S BENCH 에서 Henry 아저씨가 arduino 3.3V output 에 대해, ADS1115 를 검증해 놓은 소스를 사용해 봅니다.


#include "Wire.h"
#include "Adafruit_ADS1015.h"

Adafruit_ADS1115 ads(0x48);
float Voltage = 0.0;

void setup(void) {
	Serial.begin(9600);
	ads.begin();
}

void loop(void) {
	int16_t adc0;	// we read from the ADC, we have a sixteen bit integer as a result
	
	adc0 = ads.readADC_SingleEnded(0);
	Voltage = (adc0 * 0.1875)/1000;
	
	Serial.print("AIN0: ");
	Serial.print(adc0);
	Serial.print("\tVoltage: ");
	Serial.println(Voltage, 7);
		
	delay(1000);
}


이 소스에서 가장 중요한 것은 PGA (Programmable Gain Amplifier) 값 입니다.

이 ADS1115 의 default output 최대값이 6.144V 이므로, 이를 15 bit (16 bit 이지만, 부호를 표시하는 1 bit 를 빼면 15 bit 만 활용 가능) 인 32767 로 나누면, 출력 1 에 대해 0.1875mV 라는 계산이 나옵니다.


In the default mode, the setting is +/-6.144 volts.

Thus the value of 32767 would represent a value of 6.144 volts.

Dividing 6.144 volts by 32767 yields a scale factor of 0.1875 mV per bit.   This is a significant improvement over the Arduino ADC which resolution of approximately 5 mV per bit.  In fact, its about 26 times better!


위의 로직이 소스에 활용되었습니다.





6. 결과


지금까지 구성한 layout 과 위의 소스를 가지고 실행해 보면 다음과 같이 결과가 나옵니다.



3.3V 이지만, 미세하게 값이 변하고 있다는 것을 알 수 있습니다.

이게 USB 를 통해서 연결하지 않고 Power source 를 통해서 입력 받으면 좀더 정확하고 잘 변하지 않는 3.3V 를 얻을 수 있다고 해요.





7. 비교


Arduino nano 의 자체 3.3V 를 16 bit ADC 를 거치지 않은 채로, anlogRead (10 bit ADC) 를 하면 어떨까?


참고로 Arduino 의 AnalogReference 의 정의는 다음과 같습니다.

--------------------------------

Arduino AVR Boards (Uno, Mega, Leonardo, etc.)

- DEFAULT: the default analog reference of 5 volts (on 5V Arduino boards) or 3.3 volts (on 3.3V Arduino boards)

- INTERNAL: an built-in reference, equal to 1.1 volts on the ATmega168 or ATmega328P and 2.56 volts on the ATmega32U4 and ATmega8 (not available on the Arduino Mega)

- INTERNAL1V1: a built-in 1.1V reference (Arduino Mega only)

- INTERNAL2V56: a built-in 2.56V reference (Arduino Mega only)

- EXTERNAL: the voltage applied to the AREF pin (0 to 5V only) is used as the reference.

--------------------------------


AnalogReference(DEFAULT) 를 사용하여, 5V 기준으로 입력값을 leveling 하게 했으며,

arduino nano 에는 PGA 가 없으므로, 단순히 5V 를 10 bit ADC 해상도를 감안하여, 1024 로 나누어, 한 level 당, 0.0049 V 로 계산하도록 했습니다.



최종 소스는 다음과 같습니다.


#include "Wire.h"
#include "Adafruit_ADS1015.h"
 
Adafruit_ADS1115 ads(0x48);
float Voltage = 0.0;
float Voltage2 = 0.0;	// analogRead(A2)
 
void setup(void) {
    analogReference(DEFAULT);
    Serial.begin(9600);
    ads.begin();
}
 
void loop(void) {
    int16_t adc0;   // we read from the ADC, we have a sixteen bit integer as a result
     
    adc0 = ads.readADC_SingleEnded(0);
    Voltage = (adc0 * 0.1875)/1000;
     
    Serial.print("AIN0: ");
    Serial.print(adc0);
    Serial.print("\tVoltage: ");
    Serial.print(Voltage, 7);

	// analogRead(A2) start
    int16_t adc2;
    adc2 = analogRead(A2);
    Voltage2 = (adc2 * 0.0049);
    
    Serial.print("\tAIN2: ");
    Serial.print(adc2);
    Serial.print("\tVoltage2: ");
    Serial.println(Voltage2, 7);
    // analogRead(A2) end
         
    delay(1000);
}


결과값은 이렇게 나왔네요. 많이 부정확 합니다.


그 원인으로는,

- 5V reference 전압이 USB 를 통해 공급받으며, USB 전원은 불안하게 공급받습니다.

- PGA 가 없이, 단순히 5V reference 전압을 10 bit 로 나눈 값을 기준값으로 정했습니다.

- 16 bit 하고는 비교도 안되는 10 bit 해상도 차이가 납니다.



ADS1115 16 bit ADC 를 이용한 센서값 입력은 보다 정확한 값을 보장해 주네요.

향후 자주 사용해야 겠습니다.


And