반응형


아두이노 우노에 ESP8266 WiFi 모듈을 연결하고 TCP 서버 프로그램을 실행한 후,  라즈베리파이에서 TCP 클라이언트 프로그램으로 접속하여 아두이노에 연결된 LED를 제어하는 예제입니다.



아두이노에서 사용한 코드는 WeeESP8266 라이브러리 예제를 수정한 것이고,  라즈베리파이에서 사용한 코드는 다음 사이트의 코드를 사용했습니다.

https://www.cs.cmu.edu/afs/cs/academic/class/15213-f99/www/class26/





진행하기 전에 다음 포스팅을 참고하여 아두이노 우노에 ESP8266을 연결하고 필요한 WeeESP8266 라이브러리를 설치해야 합니다.  



Arduino UNO에서 ESP8266 WiFi 모듈을 사용하는 방법

http://webnautes.tistory.com/755





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 통신의 경우 정상적으로 동작을 하지 않아서 포스팅 업데이트시 제외되었습니다.



반응형

포스트 작성시에는 문제 없었지만 이후 문제가 생길 수 있습니다.
댓글로 알려주시면 빠른 시일내에 답변을 드리겠습니다.

여러분의 응원으로 좋은 컨텐츠가 만들어집니다.
지금 본 내용이 도움이 되었다면 유튜브 구독 부탁드립니다. 감사합니다 : )

유튜브 구독하기


제가 쓴 책도 한번 검토해보세요.

  1. kmj 2019.09.16 22:20

    안녕하세요 항상 글을 잘 보고 있습니다

    22:18:33.725 -> setup begin
    22:18:33.758 -> FW Version:
    22:18:34.784 -> to station + softap ok
    22:18:44.828 -> Join AP failure
    22:18:44.862 -> multiple ok
    22:18:44.931 -> start tcp server ok
    22:18:44.965 -> set tcp server timout 10 seconds

    계속 AP failure 이 뜨는데 이유를 잘모르겠어요

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.16 23:03 신고

      Join AP failure라고 뜨는 것은 공유기에 연결이 안되고 있는 겁니다.

      공유기 문제일 수도 있으니
      핸드폰 핫스팟으로도 테스트해보세요

+ Recent posts