반응형


라즈베리파이에서 보낸 문자열을 아두이노 우노에 연결된 캐릭터 LCD에 보여주는 예제입니다.

아두이노 우노에 연결된 ESP8266을 사용하여 TCP 소켓 통신을 합니다.



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

 


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

http://webnautes.tistory.com/755


 

 

 


1. 아두이노 IDE에 다음 코드를 복사합니다.

다음 포스팅에서 사용한 코드에 LCD에 수신한 문자열을 보여주는 코드를 추가했습니다.



TCP 소켓 통신으로 Raspberry Pi에서 Arduino UNO에 연결된 LED 제어하기

https://webnautes.tistory.com/1110



#include "ESP8266.h"
#include <SoftwareSerial.h>
#include <LiquidCrystal.h>


#define SSID        "공유기의 SSID"

#define PASSWORD    "공유기의 비밀번호"

#define HOST_PORT   (TCP서버_포트번호)



SoftwareSerial mySerial(10, 9); /* RX:D10, TX:D9 */
ESP8266 wifi(mySerial);


const int rs = 12, en = 11, d4 = 5, d5 = 4, d6 = 3, d7 = 2;
LiquidCrystal lcd(rs, en, d4, d5, d6, d7);


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 );
   lcd.begin(16, 2);
}

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:[");
       lcd.setCursor(0, 0);lcd.clear();
       for(uint32_t i = 0; i < len; i++) {
           Serial.print((char)recv_buffer[i]);

           if ( i < len-1 )
               lcd.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);

       if (n == 0){
               printf("Disconnected\n");
               break;
       }
   }

   close(sockfd);

   return 0;
}




4. 기존에 LED 제어하는 명령에 기능이 추가되었습니다.  입력한 문자열을 LCD에 보여줍니다.



라즈베리파이에서 문자열 송신시 약간의 딜레이가 생기면서 오동작하는 현상이 있습니다.  

원인을 찾아보니 read 함수에서 0바이트를 수신할때가 문제입니다.

현재는 TCP 클라이언트 프로그램을 종료하도록 하고 있습니다.  기존의 접속을 끊고 서버에 재접속하도록 수정하면 해결될듯합니다.


       if (n == 0){
               printf("Disconnected\n");
               break;
       }




시리얼 버퍼의 크기를 늘려주고 해결된 듯합니다. 변경 방법은 다음 포스팅에 포함되어 있습니다.


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

http://webnautes.tistory.com/755




마지막 업데이트  2019. 1. 17



반응형

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

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

유튜브 구독하기


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

  1. 김종민 2019.05.15 23:00

    도와주세요!

  2. 김종민 2019.05.15 23:29

    안녕하세요! 정말 도움이 필요해서 이렇게 댓글을 달아보네요. 현재 저는 4학년 학생입니다. 졸업작품을 하는데 어려움이 생겼습니다. 이번 달 말까지 끝내야하는데, 같은 조원들에게 피해를 주기 싫어서 이렇게 도움을 청합니다. 저희 조는 라즈베리파이를 이용해서 로봇팔을 제어하고 이용하는 제품을 만들려고 하고 있습니다. 서보모터 전압을 smps를 사용해서 전원을 넣었는데, 라즈베리파이에서 로봇팔이 발진하면서 제어가 안됩니다. 그래서 라즈베리에 아두이노를 깔아서 라즈베리 파이에서 0,1,2,3,4 라고 신호를 아두이노로 보내고, 아두이노로 로봇팔을 제어를 하려고 합니다. 인터넷에 보통은 아두이노에서 라즈베리로 신호를 보내는 경우는 많은데 라즈베리에서 아두이노로 보내는 간단한 방법이 없어서 힘드네요. 실례가 되지 않는다면, 도움을 주실 수 있나요 ㅠㅠㅠㅠ

    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.05.16 05:25 신고

      지금 댓글을 작성한 포스트나 다음 포스트를 참고하면 되듯합니다.

      https://webnautes.tistory.com/1110

  3. TT 2019.09.24 19:33

    안녕하세요. 좋은 정보 너무 감사합니다.
    덕북에 큰 도움이 되었습니다.
    그리고 조금 더 여쭤보고싶은게 있는데
    본문에 코드들을 긁어와서 아두이노에서 컴파일을 하면 오류가 나네요 ㅠㅠㅠ

    exit status 1
    no matching function for call to 'ESP8266::getVersion()'
    오류내용입니다...

    코드에서 에러가 나는 부분은
    void setup(void)
    {
    Serial.begin(9600);
    Serial.print("setup begin\r\n");

    Serial.print("FW Version:");
    Serial.println(wifi.getVersion().c_str());
    맨 마지막 줄이 에러가 납니다...

    혹시 도움 주실 수 있나요 ㅠㅠ


    • Favicon of https://webnautes.tistory.com BlogIcon webnautes 2019.09.24 20:07 신고

      혹시 ESP8266.h 파일에서 아래 줄의 주석을 제거했나요?

      //#define ESP8266_USE_SOFTWARE_SERIAL


      자세한 내용은 아래 포스트를 참고하세요

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

      http://webnautes.tistory.com/755

+ Recent posts