| 연결 방법아두이노 우노: UART아두이노 우노: I2CUART 설정UART COMMAND| 예제 코드모드 설정UART 통신 센서 값 읽기Streaming mode에서 CO2 값 읽기Polling mode에서 CO2값 읽기I2C 통신 센서 값 읽기디지털 필터(Digital filter)
| 연결 방법
PIN | 기능 |
Rx_ In | Digital Input |
Tx_out | Digital Output |
I2C_ENABLE | Digital Input |
I2C_SCL | I2C clock |
I2C_SDA | I2C data |
아두이노 우노: UART
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F1f10ce62-e341-4933-b92e-b1b0ff4b59df%252FUntitled.png%3Ftable%3Dblock%26id%3Dbf609e1f-5833-4895-a223-1c2533de8ef7%26cache%3Dv2&w=3840&q=75)
아두이노 우노: I2C
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F2ee1ee73-3584-4897-97e4-f55a8ed7257c%252FUntitled.png%3Ftable%3Dblock%26id%3Dd7b3c3d0-4478-44be-810f-d83ff994b453%26cache%3Dv2&w=3840&q=75)
UART 설정
매개변수 | 설명 |
Buad Rate | 9600 Bits/s |
Data Bits | 8 |
Parity | None |
Stop Bits | 1 |
Hardware Flow Control | None |
UART COMMAND
명령어 | 설명 |
K 0 | Command를 기다리는 상태, 측정 |
K 1 | 연속적으로 값을 측정 |
K 2 | 센서 값 요청시에만 응답 |
Z | 가장 최근에 측정한 CO2 필터 된 값 |
z | 가장 최근에 측정한 CO2 필터 되지 않은 값 |
A ### | CO2 필터 값 설정 |
a | CO2 필터 값 확인 |
U | 질소를 사용하여 제로 교정 |
u | 초기 설정 값으로 제로 교정 |
G | Fresh Air를 사용하여 제로 교정 |
X ##### | 현재 값으로 스팬 교정 |
P 10### | Fresh Air에서 사용할 대기 중 농도를 설정 (기본값 400ppm) |
P 11### | Fresh Air에서 사용할 대기 중 농도를 설정 (기본값 400ppm) |
S ### | 고도 설정 |
s | 고도 설정 값 확인 |
M ### | 측정 데이터 문자열로 전송 |
| 예제 코드
모드 설정
- COMMAND 모드
- COMMAND를 기다리는 상태, 측정 X
- Streaming 모드(default)
- 연속적으로 값을 측정함(초당 2회 측정), 측정 외 다른 Command시 100ms delay가 필요함
- Polling 모드
- 센서 값 요청 시에만 응답, 센서 값 요청하지 않을 때에는 백그라운드에서 계속 측정을 수행함
모드 명령어 | 설명 |
K 0 | 명령어 기다리는 상태, 측정 |
K 1 | 연속적으로 값 측정 |
K 2 | 센서 값 요청 시에만 응답 |
UART 통신 센서 값 읽기
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F1b041b29-580d-41f1-9111-585dc0d2768f%252FUntitled.png%3Ftable%3Dblock%26id%3Dedcf448c-9fb2-40ce-80cd-f5dd2b761f5a%26cache%3Dv2&w=3840&q=75)
Streaming mode에서 CO2 값 읽기
#include <SoftwareSerial.h> SoftwareSerial mySerial(12, 13); //Uno Rx Tx (12 13) = SoftwareSerial const char* Polling_mode = "K 2\r\n"; const char* Stream_mode = "K 1\r\n"; const char* Standby_mode = "K 0\r\n"; bool tx_ready; bool rx_ready; String str; void setup() { Serial.begin(9600); //시리얼 통신 초기화 mySerial.begin(9600); while(!mySerial){} //시리얼 통신 포트가 연결되기 전까지 대기 delay(14); // power on data ready mySerial.print(Stream_mode); //Polling 모드로 변경 mySerial.print("Z\r\n"); //CO2값 읽기 명령 } void loop() { if(rx_ready == 0) // overflow 처리 { delay(31); // Measurement data ready if(mySerial.available()>0) //수신받은 데이터가 0 초과, 즉 데이터가 존재한다면 { //버퍼에서 읽어드린 char의 데이터를 String 형태로 반환 str = ""; str = mySerial.readStringUntil('\n'); Serial.println(str); rx_ready = 1; tx_ready = 1; } } else if(tx_ready == 1) { mySerial.print("Z\r\n"); //CO2값 읽기 명령 tx_ready = 0; rx_ready = 0; } }
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252Fcd33c706-f196-4100-9d8c-0c664776c66d%252FUntitled.png%3Ftable%3Dblock%26id%3Dd2562fd5-439e-442e-8720-c2a39cdca3c9%26cache%3Dv2&w=3840&q=75)
Polling mode에서 CO2값 읽기
#include <SoftwareSerial.h> SoftwareSerial mySerial(12, 13); //Uno Rx Tx (12 13) = SoftwareSerial const char* Polling_mode = "K 2\r\n"; const char* Stream_mode = "K 1\r\n"; const char* Standby_mode = "K 0\r\n"; String str; void setup() { Serial.begin(9600); //시리얼 통신 초기화 mySerial.begin(9600); while(!mySerial){} //시리얼 통신 포트가 연결되기 전까지 대기 delay(14); // power on data ready mySerial.print(Polling_mode); //Polling 모드로 변경 } void loop() { if(Serial.read() == 'R') { mySerial.print("Z\r\n"); //CO2값 읽기 명령 } if(mySerial.available()>0) //수신받은 데이터가 0 초과, 즉 데이터가 존재한다면 { //버퍼에서 읽어드린 char의 데이터를 String 형태로 반환 str = ""; str = mySerial.readStringUntil('\n'); Serial.println(str); } }
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F0670daaa-002b-4ee5-a192-aa1d1ccda657%252FUntitled.png%3Ftable%3Dblock%26id%3D0d238841-9e09-45be-8d16-66e70c2e1aac%26cache%3Dv2&w=3840&q=75)
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252Ff3adc096-9b45-4ea9-8776-2e69b7d006ea%252FUntitled.png%3Ftable%3Dblock%26id%3Dc534b589-a2ab-4c18-9e9b-6c93466c2f88%26cache%3Dv2&w=3840&q=75)
I2C 통신 센서 값 읽기
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252Fb1823576-f336-4edf-a16b-41bc41f8fdaf%252FUntitled.png%3Ftable%3Dblock%26id%3D467eb696-a84b-4b0c-a142-db56dd489592%26cache%3Dv2&w=3840&q=75)
#include <Wire.h> #define Slave_adddress 0x41 #define CO2_READ_command 0x34 #define CO2_READ_and_test_command 0x02 void setup() { Wire.begin(); Serial.begin(9600); } void loop() { int CO2_value = 0; Wire.beginTransmission(Slave_adddress); // transmit to slave address Wire.write(CO2_READ_and_test_command); // transmit to register address Wire.endTransmission(); // stop transmitting Wire.requestFrom(Slave_adddress, 3); //from slave request 2byte while ( Wire.available()) { int CO2_high_value = Wire.read(); int CO2_low_value = Wire.read(); /* CO2_Self_test value = 85(DEC) : Sensor is nominal , CO2_Self_test value = 170(DEC): Sensor error */ int CO2_self_test = Wire.read(); CO2_high_value = CO2_high_value <<8; CO2_value = CO2_high_value + CO2_low_value; Serial.print("CO2_value : "); Serial.print(CO2_value); //reading CO2 value Serial.println(" PPM "); } delay(1000); }
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252Fc591897a-a04f-4653-8138-662be9fb14a8%252FUntitled.png%3Ftable%3Dblock%26id%3Dba32bc01-2381-4562-9e6f-155dacfa9861%26cache%3Dv2&w=3840&q=75)
디지털 필터(Digital filter)
필터(Filtered)된 값과 필터 되지 않은(Unfiltered) CO2 값의 차이는 아래 그림과 같음
필터(Filtered)된 CO2 값은 노이즈를 제거하여 더 정확한 값을 제공함
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F03fca0ef-15f5-444c-a4fd-10a95c7100c0%252FUntitled.png%3Ftable%3Dblock%26id%3D686c96d2-9167-469c-b687-2c92a3befdeb%26cache%3Dv2&w=3840&q=75)
Digital filter 설정
- 필터 설정 범위: 1~255( 1= Unfiltered)
- 필터의 설정 값이 증가하면 측정 출력 응답 시간이 늘어남
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252Fc7920185-2e16-4a21-a544-0a5e4fc027e7%252FUntitled.png%3Ftable%3Dblock%26id%3Dc28328dc-3403-4109-82a5-cb2e78f83cd0%26cache%3Dv2&w=3840&q=75)
- A=필터 설정 값
- A = 32 가 A = 16(default) 보다 T90에 도달하는 시간이 늘어남
Digital filter Command
명령어 | 설명 |
A ### | CO2 필터 값 설정 (예: A 16) |
a | CO2 필터 값 확인 |
CO2 필터 값 확인
#include <SoftwareSerial.h> SoftwareSerial mySerial(12, 13); //Uno Rx Tx (12 13) = SoftwareSerial const char* Polling_mode = "K 2\r\n"; const char* Stream_mode = "K 1\r\n"; const char* Standby_mode = "K 0\r\n"; bool tx_ready; bool rx_ready; String str; void setup() { Serial.begin(9600); //시리얼 통신 초기화 mySerial.begin(9600); while(!mySerial){} //시리얼 통신 포트가 연결되기 전까지 대기 delay(14); // power on data ready mySerial.print(Stream_mode); //Polling 모드로 변경 } void loop() { if(rx_ready == 0) // overflow 처리 { delay(31); // Measurement data ready if(mySerial.available()>0) //수신받은 데이터가 0 초과, 즉 데이터가 존재한다면 { //버퍼에서 읽어드린 char의 데이터를 String 형태로 반환 str = ""; str = mySerial.readStringUntil('\n'); Serial.println(str); rx_ready = 1; tx_ready = 1; } } else if(tx_ready == 1) { mySerial.print("a\r\n"); //현재 설정된 필터 값 읽기 명령어 tx_ready = 0; rx_ready = 0; } }
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F50b0b545-0cd2-431d-8bea-7a147bb2679d%252FUntitled.png%3Ftable%3Dblock%26id%3D3268be4b-b62c-4fb4-adac-8b7e84fd7636%26cache%3Dv2&w=3840&q=75)
CO2 필터 값 설정
#include <SoftwareSerial.h> SoftwareSerial mySerial(12, 13); //Uno Rx Tx (12 13) = SoftwareSerial const char* Polling_mode = "K 2\r\n"; const char* Stream_mode = "K 1\r\n"; const char* Standby_mode = "K 0\r\n"; bool tx_ready; bool rx_ready; String str; void setup() { Serial.begin(9600); //시리얼 통신 초기화 mySerial.begin(9600); while(!mySerial){} //시리얼 통신 포트가 연결되기 전까지 대기 delay(14); // power on data ready mySerial.print(Stream_mode); //Polling 모드로 변경 } void loop() { if(rx_ready == 0) // overflow 처리 { delay(31); // Measurement data ready if(mySerial.available()>0) //수신받은 데이터가 0 초과, 즉 데이터가 존재한다면 { //버퍼에서 읽어드린 char의 데이터를 String 형태로 반환 str = ""; str = mySerial.readStringUntil('\n'); Serial.println(str); rx_ready = 1; tx_ready = 1; } } else if(tx_ready == 1) { mySerial.print("A 32\r\n"); //필터 값 변경 명령어 tx_ready = 0; rx_ready = 0; } }
![notion image](https://inblog.ai/_next/image?url=https%3A%2F%2Fwww.notion.so%2Fimage%2Fhttps%253A%252F%252Fprod-files-secure.s3.us-west-2.amazonaws.com%252F89917f5a-4e07-4d31-9f02-aa72f79c2cdc%252F3d5b473d-42ed-4341-b713-95ec81d857ab%252FUntitled.png%3Ftable%3Dblock%26id%3D64078f80-65d9-4292-8d07-0cbcebf05e03%26cache%3Dv2&w=3840&q=75)
Share article