아두이노 우노에 ESP8266 WiFi 모듈을 연결하고 TCP 서버 프로그램을 실행한 후, 라즈베리파이에서 TCP 클라이언트 프로그램으로 접속하여 아두이노에 연결된 LED를 제어하는 예제입니다.
아두이노에서 사용한 코드는 WeeESP8266 라이브러리 예제를 수정한 것이고, 라즈베리파이에서 사용한 코드는 다음 사이트의 코드를 사용했습니다.
https://www.cs.cmu.edu/afs/cs/academic/class/15213-f99/www/class26/
진행하기 전에 다음 포스팅을 참고하여 아두이노 우노에 ESP8266을 연결하고 필요한 WeeESP8266 라이브러리를 설치해야 합니다.
1. Arduino IDE에 다음 코드를 복사합니다.
#include "ESP8266.h" #include <SoftwareSerial.h> #define SSID "공유기의 SSID" #define PASSWORD "공유기의 비밀번호" #define HOST_PORT (TCP서버_포트번호)
SoftwareSerial mySerial(10, 9); /* RX:D10, TX:D9 */ ESP8266 wifi(mySerial);
void setup(void) { Serial.begin(9600); Serial.print("setup begin\r\n"); Serial.print("FW Version:"); Serial.println(wifi.getVersion().c_str()); if (wifi.setOprToStationSoftAP()) { Serial.print("to station + softap ok\r\n"); } else { Serial.print("to station + softap err\r\n"); } if (wifi.joinAP(SSID, PASSWORD)) { Serial.print("Join AP success\r\n"); Serial.print("IP: "); Serial.println(wifi.getLocalIP().c_str()); } else { Serial.print("Join AP failure\r\n"); } if (wifi.enableMUX()) { Serial.print("multiple ok\r\n"); } else { Serial.print("multiple err\r\n"); } if (wifi.startTCPServer(HOST_PORT)) { Serial.print("start tcp server ok\r\n"); } else { Serial.print("start tcp server err\r\n"); } if (wifi.setTCPServerTimeout(10)) { Serial.print("set tcp server timout 10 seconds\r\n"); } else { Serial.print("set tcp server timout err\r\n"); } Serial.print("setup end\r\n"); pinMode( 13, OUTPUT ); } void loop(void) { uint8_t send_buffer[128] = {0}; uint8_t recv_buffer[128] = {0}; uint8_t mux_id; uint32_t len = wifi.recv(&mux_id, recv_buffer, sizeof(recv_buffer), 100); if (len > 0) { Serial.print("Received:["); for(uint32_t i = 0; i < len; i++) { Serial.print((char)recv_buffer[i]); } Serial.print("]\r\n");
char command = recv_buffer[0]; int ledStatus = digitalRead(LED_BUILTIN);
switch (command){ case '1': if (ledStatus == LOW){ digitalWrite(LED_BUILTIN, HIGH); sprintf(send_buffer, "LED is on\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } else{ sprintf(send_buffer, "LED is already on\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } break; case '2': if (ledStatus == HIGH){ digitalWrite(LED_BUILTIN, LOW); sprintf(send_buffer, "LED is off.\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } else{ sprintf(send_buffer, "LED is already off.\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } break; case 'S': case 's': if (ledStatus == LOW){ sprintf(send_buffer, "LED status: off\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } else { sprintf(send_buffer, "LED status: on\n"); wifi.send(mux_id,send_buffer, strlen(send_buffer)); } break; default: uint8_t buf[]="Usage\n1 : Turn On LED\n2 : Turn Off LED\nS : LED status\n\n"; wifi.send(mux_id, buf, strlen(buf)); break; } } } |
상단에 있는 다음 3줄을 환경에 맞게 수정한 후, Arduino Uno에 업로드시켜줍니다.
포스팅에서는 TCP 서버 포트번호로 23번을 사용하여 진행합니다.
#define SSID "공유기의 SSID" #define PASSWORD "공유기의 비밀번호" #define HOST_PORT (23) |
2. Arduino IDE의 메뉴에서 툴 > 시리얼 모니터를 실행합니다. 서버역활을 하게될 아두이노의 IP를 확인해둡니다.
IP 항목에서 두번째 아이피(붉은색 글씨)를 사용하면 됩니다.
setup begin FW Version:0018000902 to station + softap ok Join AP success IP: 192.168.4.1 192.168.43.239 multiple ok start tcp server ok set tcp server timout 10 seconds setup end
|
3. 라즈베리파이에서 TCP 클라이언트 코드를 컴파일 후, 아두이노의 IP와 포트번호를 사용하여 실행합니다.
$ gcc -o tcpclient tcpclient.c $ ./tcpclient 192.168.43.239 23
|
/* * tcpclient.c - A simple TCP client * usage: tcpclient <host> <port> */ #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netdb.h> #define BUFSIZE 1024 /* * error - wrapper for perror */ void error(char *msg) { perror(msg); exit(0); } int main(int argc, char **argv) { int sockfd, portno, n; struct sockaddr_in serveraddr; struct hostent *server; char *hostname; char buf[BUFSIZE]; /* check command line arguments */ if (argc != 3) { fprintf(stderr,"usage: %s <hostname> <port>\n", argv[0]); exit(0); } hostname = argv[1]; portno = atoi(argv[2]); /* socket: create the socket */ sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd < 0) error("ERROR opening socket"); /* gethostbyname: get the server's DNS entry */ server = gethostbyname(hostname); if (server == NULL) { fprintf(stderr,"ERROR, no such host as %s\n", hostname); exit(0); } /* build the server's Internet address */ bzero((char *) &serveraddr, sizeof(serveraddr)); serveraddr.sin_family = AF_INET; bcopy((char *)server->h_addr, (char *)&serveraddr.sin_addr.s_addr, server->h_length); serveraddr.sin_port = htons(portno); /* connect: create a connection with the server */ if (connect(sockfd, &serveraddr, sizeof(serveraddr)) < 0) error("ERROR connecting"); while(1){ /* get message line from the user */ printf("Please enter msg: "); bzero(buf, BUFSIZE); fgets(buf, BUFSIZE, stdin); if ( buf[0] == 'q' ) break; /* send the message line to the server */ n = write(sockfd, buf, strlen(buf)); if (n < 0) error("ERROR writing to socket"); /* print the server's reply */ bzero(buf, BUFSIZE); n = read(sockfd, buf, BUFSIZE); if (n < 0) error("ERROR reading from socket"); printf("Echo from server: %s", buf); } close(sockfd); return 0; } |
4. 라즈베리 파이에서 1을 보내면 LED가 켜지고, 2를 보내면 LED가 꺼집니다. 이때 상태메시지가 수신됩니다.
S를 입력하면 현재 LED 상태를 알려줍니다.
입력할 수 있는 문자 1, 2, S 외의 문자를 입력하면 사용방법이 수신됩니다.
pi@raspberrypi:~ $ ./tcpclient 192.168.43.239 23 Please enter msg: a Echo from server: Usage 1 : Turn On LED 2 : Turn Off LED S : LED status
Please enter msg: 1 Echo from server: LED is on Please enter msg: 2 Echo from server: LED is off. Please enter msg: s Echo from server: LED status: off Please enter msg: 2 Echo from server: LED is already off. Please enter msg: 1 Echo from server: LED is on Please enter msg: s Echo from server: LED status: on Please enter msg: q
|
시리얼 모니터에는 라즈베리파이에서 전송한 문자열이 출력됩니다.
Received:[a ] Received:[1 ] Received:[2 ] Received:[s ] Received:[2 ] Received:[1 ] Received:[s ]
|
마지막 업데이트 2019. 1. 16
기존에 포함되어 있던 UDP 통신의 경우 정상적으로 동작을 하지 않아서 포스팅 업데이트시 제외되었습니다.