아두이노 강좌 #49 SD-Card를 사용한 웹 서버 - 이더넷 쉴드 사용
Lucy Archive
Lucy 2023
2020. 11. 12. 02:02

Arduino SD-Card WEb ServerArduino SD-Card WEb Server

Arduino Web Server Using SD-Card

지난 포스트에서는 아두이노에서 웹 서버를 구축 후 내장 플래쉬 메모리에 저장된 웹 페이지를 보여주는 방법에 대해 설명하였습니다. 이번 포스트에서는

아두이노 이더넷 쉴드의 SD-Card에 웹 페이지를 이용한 웹 서버 구축 방법

에 대해 소개합니다.

SD 카드 사용 방법과 Arduino Ethernet Shield를 사용하여 LAN에 연결하고 웹 서버 구축하는 방법은 하단의 관련 페이지를 참고해주세요.


SD-Card를 사용하는 이유

아두이노의 메인 프로세서로 사용되는 MCU 메모리 용량은 일반적인 웹 사이트의 파일 크기에 비해 턱없이 작습니다. 아두이노로 웹 서버를 구축하여 간단히 텍스트만 있는 웹페이지를 보여주는 것은 문제가 없지만, 그 이상이 되면 용량의 문제에 부딪히게 됩니다.

※ 참고 : Arduino Uno 보드의 내장 메모리

  • Flash Memory : 32KByte (PC의 HDD 또는 SSD에 해당되는 메모리)
  • SRAM : 2KByte (PC의 RAM에 해당되는 메모리)

이러한 이유로 이더넷, WIfi, LCD와 같이 데이터의 크기가 많이 필요한 기능의 아두이노 쉴드에는 항상 SD-Card 가 부착되어 있습니다.

SD-Card를 사용하여 웹 서버 동작

준비물

본 예제의 구성품은 아래와 같습니다.

  • Arduino Uno x 1EA
  • Arduino Ethernet Shield 2 x 1EA
  • SD-Card x 1EA
  • 유무선 공유기 x 1EA

네트워크 구성

지난 포스트와 동일하게 아래 그림과 같이 네트워크를 구성하였습니다. 제가 가진 유무선 공유기의 내부 네트워크 IP주소는 192.168.0.2 ~ 192.168.0.255의 범위에서 사용할 수 있어, Arduino는 192.168.0.50으로 고정 IP를 사용하였습니다. 

아두이노 웹 서버 네트워크 구성아두이노 웹 서버 네트워크 구성

웹 페이지

아두이노 서버에서 제공되는 웹 페이지는 아래의 HTML 코드를 사용하였습니다. 해당 HTML 파일은 SD-CARD에 저장하기 위해 index.htm으로 저장합니다. 별도의 코드 에디터를 사용하지 않으시는 분은 메모장에서 아래의 코드를 작성해서 확장자를 변경하여 저장하시면 됩니다. HTML 코드를 본문에 삽입 할 수 없어(제가 할 줄 몰라서..) 첨부파일로 index.htm 파일을 참고로 첨부하였습니다.

index.htm

Index.htm 파일Index.htm 파일

SD-CARD 준비

위에서 준비된 Index.htm 파일을 SD-CARD에 저장 후 Arduino Ethernet Shield에 연결합니다. 아두이노에서 SD-CARD를 사용하기 위해 미리 알아 두면 좋은 내용은 아래와 같습니다.

  • SD-CARD를 FAT 파일 시스템으로 포멧
    • 아두이노에서 제공되는 SD.h 라이브러리는 FAT16, FAT32 파일 시스템을 지원
  • 파일 명명 규칙은 8.3 Format 규칙을 준수합니다.
    • 파일명 8자, 확장자 3자 사용
    • index.html -> 사용 불가, index.htm -> 사용 가능
  • Arduino와 SD-Card는 SPI 통신을 사용하기 때문에 SPI.hSD.h 라이브러리를 참조
  • SD.h 라이브러리를 사용하는 경우 SRAM 차지 하는 비율이 크다는 점을 고려해서 코드를 작성해야 함

Ethernet Shield 연결

Arduino Uno와 Arudino Ethernet Shield 2를 아래와 같이 적층 형태로 연결합니다. 위에서 준비된 SD-Card도 이더넷 쉴드에 연결 합니다.

Arduino Ethernet Shield2 연결Arduino Ethernet Shield2 연결

아두이노 코드

아래 코드는 192.168.0.50 IP 주소를 가지는 아두이노 웹 서버 예제입니다. 서버에 접속하는 클라이언트 PC의 브라우저에 보여지는 웹 페이지는 아두이노 이더넷 쉴드의 SD-Card 에 저장되어 있습니다. 아래의 코드는 하단의 [각주:1]링크를 참조하여 수정하였습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
#include <SPI.h>
#include <Ethernet.h>
#include <SD.h>
 
#define CS_PIN 4 // SD-Card CS PIN
#define FILENAME F("index.htm"// SD-CARD의 HTML 파일 이름
 
byte mac[] = {0x900xA20xDA0x100x530x07}; // MAC Address 
IPAddress ip(192168050); // IP Address
EthernetServer server(80); // Server Port 80
 
void setup()
{
    Serial.begin(115200);
    Serial.println(F("Initializing SD card..."));
 
    /* 카드 연결 확인 */
    if (!SD.begin(CS_PIN)) {
        Serial.println(F("Card failed, or not present"));
        while (1);
    }
    Serial.println(F("card initialized."));
 
    /* SD Card에 index.htm 파일이 존재하는지 확인 */
    if (!SD.exists(FILENAME)) {
        Serial.println(F("ERROR - Can't find index.htm file!"));
        while (1); // 파일이 없는 경우 무한 루프
    }
    Serial.println(F("SUCCESS - Found index.htm file."));
 
    /* 이더넷 설정 및 서버 시작 */
    // You can use Ethernet.init(pin) to configure the CS pin
    //Ethernet.init(10);  // Most Arduino shields
    //Ethernet.init(5);   // MKR ETH shield
    //Ethernet.init(0);   // Teensy 2.0
    //Ethernet.init(20);  // Teensy++ 2.0
    //Ethernet.init(15);  // ESP8266 with Adafruit Featherwing Ethernet
    //Ethernet.init(33);  // ESP32 with Adafruit Featherwing Ethernet
    Ethernet.begin(mac, ip);  // initialize Ethernet device
    server.begin(); // Start to listen for clients
}
 
void loop()
{
    EthernetClient client = server.available();  // try to get client
 
    if (client) {  // got client?
        boolean currentLineIsBlank = true;
        while (client.connected()) {
            if (client.available()) {   // client data available to read
                char c = client.read(); // read 1 byte (character) from client
                Serial.print(c);
                // last line of client request is blank and ends with \n
                // respond to client only after last line received
                if (c == '\n' && currentLineIsBlank) {
                    // send a standard http response header
                    client.println(F("HTTP/1.1 200 OK"));
                    client.println(F("Content-Type: text/html"));
                    client.println(F("Connection: close"));
                    client.println();
                    // send web page
                    File webFile = SD.open(FILENAME);        // open web page file
                    if (webFile) {
                        while(webFile.available()) {
                            client.write(webFile.read()); // send web page to client
                        }
                        webFile.close();
                    }
                    break;
                }
                if (c == '\n') {
                    currentLineIsBlank = true;
                } 
                else if (c != '\r') {
                    currentLineIsBlank = false;
                }
            } 
        } 
        delay(1);  
        client.stop(); // close the connection
    }
}
cs

지난 포스트에서 설명한 코드에서 SD카드를 사용하기 위한 코드들이 추가되었고, 핵심적으로 수정된 내용은 62~67줄의 SD-Card의 Index.htm 파일의 데이터를 HTTP 통신으로 클라이언트에 전송하는 부분입니다.

실행 결과

하드웨어 구성을 마치고, 위의 코드를 아두이노에 업로드 하면 아래 우측 그림과 같이 클라이언트 PC의 웹 브라우저에서 아두이노노 웹 서버에 접속하게 되면 SD-Card에 저장된 index.htm 웹 페이지를 볼 수 있습니다. 왼쪽 그림은 아두이노의 시리얼 포트에서 출력되는 메세지를 보여 줍니다. 부팅시 SD-Card 연결 과 index.htm 파일이 존재하는지 확인하고, 클라이언트가 접속되면 SD-Card의 index.htm 파일의 데이터를 전송합니다.

아두이노 SD 카드 웹 서버 실행 결과아두이노 SD 카드 웹 서버 실행 결과


마무리

이번 포스트에서는 아두이노 SD-Card를 사용한 웹 서버 구축 방법에 대해 소개하였습니다. SD-Card와 Ethernet 사용 관련 포스트는 아래를 참조해주세요.


  1. https://startingelectronics.org/tutorials/arduino/ethernet-shield-web-server-tutorial/SD-card-web-server/ [본문으로]