'ADS1115'에 해당되는 글 2건

  1. 2019.10.12 Hardware | 공기질 측정용 MiCS-6814 센서를 사용해 보자 - 1 26
  2. 2019.08.12 Hardware | ADS1115 16bit 4채널 ADC 를 사용해 보자 6

Hardware | 공기질 측정용 MiCS-6814 센서를 사용해 보자 - 1

|

1. 공기


사람이 건강하게 살아가는데 필요한게 뭘까 라고 생각했을 때, 육체적 관점에서 보면 아래와 같다고 생각합니다.


- 깨끗한 공기

- 깨끗한 물

- 오염되지 않은 먹거리

- 쾌적한 주거 환경

- 충분한 수면

- 충분한 운동


예전에는 당연한 것이였지만, 이 시대에 와서는 가장 돈을 많이 들여야 하는 항목들이 되었습니다.

과거로 회기하는데 드는 비용이죠.


자고로, 산업혁명이 일어나 지구가 오염되기 전 상황으로 되돌아 가는 것이, 육체적인 건강한 삶 되겠습니다. (나의 생각)

나만 잘한다고 되는건 아니라 요원하긴 하지만...


이 arduino 나 sensor 를 가지고 노는 이유도, 전자적인 지식을 습득해 나가는 것에 대한 희열 말고도,

위의 "건강한 삶을 보낼 수 있는 환경" 에 대한 추구가 다른 주된 이유이기도 합니다.


그래서, "깨끗한 공기" 가 목적이지만, 그 이전에 현재 "어떤 공기" 속에서 살고 있는지 알아보고 싶어졌습니다.

일전에 공기질의 척도만 나타내 주는 센서를 가지고 놀아본 적이 있습니다.


* Hardware | ZP07-MP901 공기질 측정 센서

https://chocoball.tistory.com/entry/Hardware-ZP07-MP901-air-quality-sensor


다만 위의 센서는 공기의 성분까지는 알려주지 못해 그닥 쓸모가 없었죠.





2. 센서


기체를 알아보는 sensor 는 꽤 많이 나와 있습니다. 대표적으로는 MQ series 가 있지요.





이 MQ 시리즈를 이용하면 왠만한건 다 잡아 낼 수 있을 것 같습니다.


다만, 이 MQ 시리즈의 단점이 히터를 통해서 기체를 태우고 그에 따른 반응으로 측정을 하는 방법인지라,

가스나 화기를 취급하는 곳에서는 발화의 원인이 될 수 있습니다. 그래서 인화 물질을 취급하는 공장이나 병원에서는 사용되지 못합니다.


그러던 중, MiCS-6814 라는 센서의 존재를 알게 됩니다.



이 센서는 metal oxide = 기체에 의한 금속 산화도 에 따른 저항 값을 가지고 측정하므로, MQ 시리즈보다는 더 안전합니다.


SGX-CMOS-Gas-Sensor-MiCs-6814.pdf

pollutant-visualizer.pdf


잡아낼 수 있는 기체들은 다음과 같다고 하네요.


• Carbon monoxide CO 1 – 1000ppm

• Nitrogen dioxide NO2 0.05 – 10ppm

• Ethanol C2H5OH 10 – 500ppm

• Hydrogen H2 1 – 1000ppm

• Ammonia NH3 1 – 500ppm

• Methane CH4 >1000ppm

• Propane C3H8 >1000ppm

• Iso-butane C4H10 >1000ppm


하나의 센서 chip 으로 많은 성분을 잡아 낼 수 으며, 소형인지라,

MQ 시리즈를 구입해서 실험 해보기 보단, 이놈으로 결정하였습니다.




3. Grove - Multichannel Gas Sensor


MiCS-6814 를 활용하기 위해 가장 좋은 방법은,

MiCS-6814 를 활용한 breakout board 인 Grove 사의 Multichannel Gas Sensor 를 구입하는 것 입니다.


* Grove - Multichannel Gas Sensor

http://wiki.seeedstudio.com/Grove-Multichannel_Gas_Sensor/



Arduino 와의 통신도 I2C로 이루어 지며, 센서의 3개 측정값 - CO, NH3, NO3 - 의 조합으로 다른 기체도 유추해 놓는것 같습니다.

거기에 정확하지는 않지만, 어느정도 calibration 도 잡혀 있을 것이구요.


다만, 항상 그렇 듯, 가격이 문제 입니다. 요즘은 팔지도 않거니와, 실 구매 가격은 약 10만원 정도.

나중에 혹시 PCB 라도 꾸며서 만들 수 있으면 만들어 보고자, 여기에 회로 관련 정보를 올려 놓습니다.


Grove-Multichannel_Gas_Sensor_v1.0_sch.pdf

Grove-Multichannel_Gas_Sensor_v1.0_eagle_files.zip

1143_Datasheet-MiCS-6814-rev-8.pdf


* Firmware (Seeed-Studio/Mutichannel_Gas_Sensor)

https://github.com/Seeed-Studio/Mutichannel_Gas_Sensor




4. 구입


눈물을 뒤로 하고, AliExpress 로 향합니다.


* 1pcs CJMCU- MICS-6814 Air Quality CO VOC NH3 Nitrogen Oxygen Gas Sensor

- https://www.aliexpress.com/item/32762216430.html



저를 위로해 주는 기교적 착한 가격. 거진 3만원돈 이지만, 과감하게 투자해 봅니다. (6개월 고민... ㅠㅠ)



대단한건 아니지만, 도착했을 시 꽤 기뻤습니다. 이제야 이런 고급진 센서 써보는구나~ 라고.



정말 단순한 구조. 레귤레이터도 없어...



뒷면입니다.





5. 연결


어떻게 arduino 와 연결하여, 각 기체의 값을 알아낼까 찾아보던 중 아래 사이트를 발견합니다.


* Wiring MiCs 5524 / 6814 CMOS MEMS Gas Detection Sensor

https://www.14core.com/wiring-mics-5524-6814-cmos-mems-gas-detection-sensor/



걍 analog pin 에 직결하라고 하네요?

제가 구매한 breakout 보드에는 MOSFET 도 없고 그렇지만, 일단 아래 소스를 가지고 돌려 봅니다.


int NH3 = 0;
int NO2 = 1;
int CO = 2;

void setup() {
	pinMode(NH3, OUTPUT);
	pinMode(NO2, OUTPUT);
	pinMode(CO, OUTPUT);
	
	Serial.begin(9600);
	Serial.println("MiCS 6814 simple test");
}
 
void loop() {
	int sense_val_1 = analogRead(NH3);
	int sense_val_2 = analogRead(NO2);
	int sense_val_3 = analogRead(CO);
	
	Serial.print("NH3 : ");
	Serial.print(sense_val_1);
	Serial.print(" \t NO2 : ");
	Serial.print(sense_val_2);
	Serial.print(" \t CO : ");
	Serial.println(sense_val_3);
	
	delay(1000);
}


Serial Monitor 로 값을 확인해 보고, EXCEL 로 그래프를 그려 봅니다.



음... 뭔가 알아보기 힘드네요. 각 기체의 값이 서로 비슷하게 나와버립니다.






6. 저항을 추가하여 연결


아래 사이트에서 이 아저씨가 한 작업은,

측정값이 현실적으로 되려면 analog pin 에 입력되는 값은, 3.3V 를 저항을 거쳐서 연결하라고 합니다.

(이론적으로는 50K ohm 이 좋으나, 제품으로 나오는 저항은 47K ohm 이 제일 가까운 값)


* ESP32, PMS5003, BME280, MICS6814 Sensor Build

http://kstobbe.dk/2019/02/16/esp32-pms5003-bme280-mics6814-sensor-build/



또한, 아래 arduino forum 에서는, 각 단자에 47K ohm 통해 연결하는 전원은 3.3V 보단, 5V 를 먹이라고 하네요.

아마도 MiCS-6814 구동 전압이 5V 임을 감안하면, 동일한 입력 값이 좀더 예민한 값의 도출에 좋다는 이야기 같습니다.

(솔직히 잘 모름)


* CJMCU-6814 adapter board with MICS-6814 CO/NH3/NO2-sensor

https://forum.arduino.cc/index.php?topic=619992.0


Tested the sensor with the code and schematic. Connected 47k to 3 gases and 5v rather than 3v. The results seem to reflect well to CO. Have not tested NO2 and NH3.


바로 따라해 봅니다.



Serial Monitor 에서 측정된 값이구요.



EXCEL 에서 그래프화 해 봤습니다.

오오오오오, 뭔가 나오네요.



가능한 24시간동안 예열하도록 안내가 되어 있듯이, 예열 구간동안 특정 값으로 꾸준히 변화되는 것을 알 수 있습니다.

위의 빨간 표시한 부분은, 시험삼아 숨을 한번 불어본 구간입니다. 변화를 잘 감지하는군요!



하룻밤 측정해본 결과 입니다.

각 기체의 상관 관계와 실내 공기 내에서의 NH3, NO2, CO 의 값은 이정도인 듯 합니다.




7. 15bit ADC + 저항을 추가하여 연결


Arduino 내장 10 bit ADC 를 가지고 측정한 결과 보다는 15 bit ADC 가 훨씬 정확합니다.

아래 포스트 이후로, 향후 모든 측정값은 더 높은 ADC 를 통하라고 배웠습니다.


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

https://chocoball.tistory.com/entry/Hardware-ADS1115-16bit-4channel-ADC


ADS1115 이 입력값을 받구요.



소스를 ADS1115 용으로 살짝 수정해 줍니다.

#include "Wire.h"
#include "Adafruit_ADS1015.h"
 
Adafruit_ADS1115 ads(0x48);
 
void setup(void) {
    Serial.begin(115200);
    ads.begin();
}
 
void loop(void) {
    int16_t adc1; // CO
    int16_t adc2; // NH3
    int16_t adc3; // NO2
     
    adc1 = ads.readADC_SingleEnded(1);
    adc2 = ads.readADC_SingleEnded(2);
    adc3 = ads.readADC_SingleEnded(3);

    Serial.print("NH3 : ");
    Serial.print(adc2);
    Serial.print(" \t NO2 : ");
    Serial.print(adc3);
    Serial.print(" \t CO : ");
    Serial.println(adc1);
     
    delay(1000);
}


Serial Monitor 에서 확인한 값 들 입니다.

확실히 뭔가 엄청나게 숫자가 불어나 있습니다.



EXCEL 을 통해서 그래프화 시켜 봅니다.



패턴은 47K ohm 저항 꼽고 측정할 때와 비슷하게 나왔습니다.


다만, 높은 ADC 를 통하여 해상도는 좋아졌지만,

어떤 기준값으로 나누어야 할지 알지 못하기 때문에, trend 만 알 수 있지 정확한 수치화까지는 진행하지 못했습니다.




8. Next Step


이런 공기질 측정에서의 수치화는 calibration 인데,

그렇게 하려면 실제 실험실 환경을 통해서, 실제 기체를 가지고 기준을 잡아야 합니다.


위의 방법이 현실적으로 불가능 하기에,

다음에 할 것으로는 Grove - Multichannel Gas Sensor 의 breakout 을 만들어서 (아님 구입해서),

제조사인 SeeedStudio 의 경험이 녹아들어가 있는 firmware 와 소스코드를 가지고 수치화 해보는 것 이겠습니다.


공기 질에 관한 센서는 몇 개가 더 있습니다. 계속 놀아보도록 하지요.

To Be Continued...


And

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
prev | 1 | next