아두이노와 서버 소켓통신
아두이노 & 라즈베리파이로 특정 프로젝트르 시작할 때
센서값을 기록하기 위해 DB를 구축한다.
이때
아두이노와 아두이노 센서를 사용하여 얻은 센서값을
ESP-01Wifi 모듈과 서버의 Wifi로 TCP 소켓통신을 하게 된다면
안전하게 값을 전송할 수 있다.
🤔 Socket 통신이란??
TCP 연결 기반 서버/클라이언트 간 양방향 통신 방법입니다
위 그림은 소켓 통신 흐름을 보여줍니다
연결을 시도하는 클라이언트 부분과
요청을 받아 데이터를 처리하는 서버 부분에서
각각 자신의 소켓을 생성합니다
서버 측에서는 클라이언트의 연결을 받기 위해
bind()를 통해서 만들어진 소켓에 자신의 IP 주소와 포켓 번호를 입력하여 소켓을 완성시킨다.
완성된 소켓을 listen() 상태로 만들고 난 후,
클라이언트의 요청을 기다리게 되는데
이러한 상황을 Passive open이라고 합니다
클라이언트가 자신의 소켓으로 connect()을 시도하려고 할 때,
listen() 상태에 있던 서버 측의 소캣은 클라이언트의 요청을 받아들여 accept()하게 됩니다.
마무리로 create socket을 한다면 양방향 통신 설정이 완료됩니다
위 그림과 같이 아두이노와 esp-01을 연결한 뒤, 아두이노 시리얼 모니터를 통해
소켓 연결이 잘 되었는지 확인해 볼 수 있습니다
데이터베이스에 저장된 값을 불러와서 아두이노에 데이터 값을 띄우는 과정에 앞서,
ESP 8266Wifi 모듈과 MG811 이산화탄소를 이용하여 센서부를 생성합니다
센서부는 아두이노의 전원을 인가하면 MG811의 센서값을 ESP 8266을 통해
서버로 전송하게 됩니다
서버는 받은 데이터 값을 처리해서 DB에 저장합니다
아두이노 코딩
#include "ESP8266.h" // ESP-01 사용에 관한 객체 생성 라이브러리
#include <SoftwareSerial.h> // 시리얼 통신을 위한 라이브러리
#include <doxygen.h> // ESP-01 사용에 명령어르 다루는 라이브러리
#define SSID "" // Wifi 아이디
#define PASSWORD "" // Wifi 패스워드
#define HOST_NAME "" // 서버 IP
#define HOST_PORT // 서버 포트
SoftwareSerial mySerial(10, 9); // RX: D10, TX: D9
ESP8266 wifi(mySerial); // wifi 라는 이름으로 객체 생성
void setup(void)
{
Serial.begin(9600);
Serial.print("setup begin\r\n");
pinMode(12, OUTPUT); // 12번 핀 출력모드 (LED 제어)
digitalWrite(12, LOW); // 초기 상태는 LOW
wifi.restart(); // ESP-01 재시작
if(wifi.kick ()) // ESP-01 활성 여부 확인
Serial.print("esp8266 is alive\r\n");
else
Serial.print("esp8266 is not alive\r\n");
Serial.print("FW Version: ");
Serial.println(wifi.getVersion().c_str()); // ESP-01의 펌웨어 버전 체크
if (wifi.setOprToStation ()) {
Serial.print("to stataion mode\r\n");
} else {
Serial.print("to station mode error\r\n");
}
if (wifi.disableMUX ()) {
Serial.print("single ok\r\n");
} else {
Serial.print("single err\r\n");
}
if (wifi.joinAP(SSID, PASSWARD) { // Wifi 연결 시도
Serial.print("Join AP success\r\n");
Serial.print("IP: ");
Serial.println( wifi.getLocalIP().c_str()); // ESP8266의 IP 출력
} else {
Serial.print("Join AP failure\r\n");
}
Serial.print("setup end\r\n");
}
void loop(void)
{
uint8_t buffer[128] = {0}; // 자료형 uint8_t int 형의 데이터 타입을 재정의 8bit
String response = "" ;
if (wifi.createTCP (HOST_NAME, HOSP_PORT)) { // 서버의 IP와 포트로 연결시도
Serial.print("create tcp ok\r\n");
} else {
Serial.print("create tcp err\r\n");
}
char *sendData = "NUM Cheak";
wifi.send((const uint8_t*)sendData, strlen(sendData)); //데이터 송신
uint32_t recvData = wifi.recv(buffer, sizeof(buffer), 10000); // 데이터 수신 (이때 타임아웃 시간은 10초)
if (recvData > 0) {
Serial.print("Received: [");
for(uint32_t i = 0; i < recvData; i++) {
Serial.print((char)buffer[i]);
char c = (char)buffer[i];
response += c;
}
Serial.print("] \r\n");
int pinNumber = response.toInt();
Serial.println(pinNumber);
digitalWrite(pinNumber. !digitalRead(pinNumber));
if (wifi.releaseTCP ()) { // TCP 해제
Serial.print("release tcp ok\r\n");
} else {
Serial.print("release tcp err\r\n");
}
delay(5000);
}
}
서버 측 코딩
결과 확인