ESP8266 SD 카드에서 구성 읽기
이 튜토리얼은 ESP8266에서 마이크로 SD 카드의 설정 파일 사용법을 다루며, 다음과 같은 측면을 포함합니다:
 - Micro SD 카드에 키-값 쌍을 포함하는 config.txt 파일을 배치하는 것. 
 - ESP8266에 Micro SD 카드에서 구성 데이터를 읽고 int 변수에 저장하도록 프로그래밍하는 것. 
 - ESP8266에 Micro SD 카드에서 구성 데이터를 읽고 float 변수에 저장하도록 프로그래밍하는 것. 
 - ESP8266에 Micro SD 카드에서 구성 데이터를 읽고 String 변수에 저장하도록 프로그래밍하는 것. 
| 1 | × | ESP8266 NodeMCU | 쿠팡 |  아마존 |  | 
| 1 | × | USB 케이블 타입-A to 타입-C (USB-A PC용) | 쿠팡 |  아마존 |  | 
| 1 | × | USB 케이블 타입-C to 타입-C (USB-C PC용) | 아마존 |  | 
| 1 | × | 마이크로 SD 카드 | 아마존 |  | 
| 1 | × | 마이크로 SD 카드 모듈 | 쿠팡 |  아마존 |  | 
| 1 | × | 점퍼케이블 | 쿠팡 |  아마존 |  | 
| 1 | × | (옵션) MicroSD to SD 메모리 카드 어댑터 | 아마존 |  | 
| 1 | × | (추천) ESP8266용 스크루 터미널 확장 보드 | 쿠팡 |  아마존 |  | 
| 1 | × | (추천) ESP8266 Type-C용 전원 분배기 | 쿠팡 |  아마존 |  | 
공개: 이 포스팅 에 제공된 일부 링크는 아마존 제휴 링크입니다. 이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다.
 
마이크로 SD 카드 모듈을 잘 모르시거나, 핀 배치, 작동 방식, 프로그래밍 방법 등에 대해 알고 싶으시면 ESP8266 - 마이크로 SD 카드 튜토리얼을 확인해 보세요.
 
각 키-값 쌍은 Micro SD 카드의 단일 줄에 위치하며, 키와 값은 = 문자로 구분됩니다. 추가적으로, 각 쌍은 새 줄 문자로 다른 쌍들로부터 분리됩니다.
ESP8266 코드는 키를 찾아 연관된 값을 찾아내어 변수에 저장할 것입니다. 이 변수는 int, float, 또는 String일 수 있습니다.
 

이 이미지는 Fritzing을 사용하여 만들어졌습니다. 이미지를 확대하려면 클릭하세요.
ESP8266 핀배열 및 ESP8266 전원을 켜는 방법에 대해 더 많이 보십시오.
※ 주의:
이더넷 실드나 Micro SD 카드 홀더가 포함된 다른 실드가 있으면, Micro SD 카드 모듈을 사용할 필요가 없습니다. 단순히 Micro SD 카드를 실드의 홀더에 삽입하면 됩니다.
 
myString_1=Hello
myString_2=newbiely.kr
myInt_1=2
myInt_2=-105
myFloat_1=0.74
myFloat_2=-46.08
 - USB 3.0 SD 카드 리더기를 사용하여 PC에 마이크로 SD 카드를 연결하세요. 
 - 마이크로 SD 카드가 FAT16 또는 FAT32로 포맷되었는지 확인하세요(온라인에서 지침을 찾아보세요). 
 - config.txt 파일을 마이크로 SD 카드의 메인 디렉토리에 넣으세요. 
 - 완료되면, PC에서 마이크로 SD 카드를 분리하세요. 
 - 배선도대로 마이크로 SD 카드 모듈을 사용하여 ESP8266에 마이크로 SD 카드를 연결하세요. 
 - 아래에 주어진 코드를 복사하고 Arduino IDE로 열어보세요. 
#include <SD.h>
#define PIN_SPI_CS D8
#define FILE_NAME "config.txt"
#define KEY_MAX_LENGTH    30 
#define VALUE_MAX_LENGTH  30 
int myInt_1;
int myInt_2;
float myFloat_1;
float myFloat_2;
String myString_1;
String myString_2;
void setup() {
  Serial.begin(9600);
  if (!SD.begin(PIN_SPI_CS)) {
    Serial.println(F("SD Card failed, or not present"));
    while (1); 
  }
  Serial.println(F("SD Card initialized."));
  myInt_1    = SD_findInt(F("myInt_1"));
  myInt_2    = SD_findInt(F("myInt_2"));
  myFloat_1  = SD_findFloat(F("myFloat_1"));
  myFloat_2  = SD_findFloat(F("myFloat_2"));
  myString_1 = SD_findString(F("myString_1"));
  myString_2 = SD_findString(F("myString_2"));
  Serial.print(F("myInt_1 = "));
  Serial.println(myInt_1);
  Serial.print(F("myInt_2 = "));
  Serial.println(myInt_2);
  Serial.print(F("myFloat_1 = "));
  Serial.println(myFloat_1);
  Serial.print(F("myFloat_2 = "));
  Serial.println(myFloat_2);
  Serial.print(F("myString_1 = "));
  Serial.println(myString_1);
  Serial.print(F("myString_2 = "));
  Serial.println(myString_2);
}
void loop() {
}
bool SD_available(const __FlashStringHelper * key) {
  char value_string[VALUE_MAX_LENGTH];
  int value_length = SD_findKey(key, value_string);
  return value_length > 0;
}
int SD_findInt(const __FlashStringHelper * key) {
  char value_string[VALUE_MAX_LENGTH];
  int value_length = SD_findKey(key, value_string);
  return HELPER_ascii2Int(value_string, value_length);
}
float SD_findFloat(const __FlashStringHelper * key) {
  char value_string[VALUE_MAX_LENGTH];
  int value_length = SD_findKey(key, value_string);
  return HELPER_ascii2Float(value_string, value_length);
}
String SD_findString(const __FlashStringHelper * key) {
  char value_string[VALUE_MAX_LENGTH];
  int value_length = SD_findKey(key, value_string);
  return HELPER_ascii2String(value_string, value_length);
}
int SD_findKey(const __FlashStringHelper * key, char * value) {
  File configFile = SD.open(FILE_NAME);
  if (!configFile) {
    Serial.print(F("파일 열기 오류, SD 카드 "));
    Serial.println(FILE_NAME);
    return;
  }
  char key_string[KEY_MAX_LENGTH];
  char SD_buffer[KEY_MAX_LENGTH + VALUE_MAX_LENGTH + 1]; 
  int key_length = 0;
  int value_length = 0;
  
  PGM_P keyPoiter;
  keyPoiter = reinterpret_cast<PGM_P>(key);
  byte ch;
  do {
    ch = pgm_read_byte(keyPoiter++);
    if (ch != 0)
      key_string[key_length++] = ch;
  } while (ch != 0);
  
  while (configFile.available()) {
    int buffer_length = configFile.readBytesUntil('\n', SD_buffer, 100);
    if (SD_buffer[buffer_length - 1] == '\r')
      buffer_length--; 
    if (buffer_length > (key_length + 1)) { 
      if (memcmp(SD_buffer, key_string, key_length) == 0) { 
        if (SD_buffer[key_length] == '=') {
          value_length = buffer_length - key_length - 1;
          memcpy(value, SD_buffer + key_length + 1, value_length);
          break;
        }
      }
    }
  }
  configFile.close();  
  return value_length;
}
int HELPER_ascii2Int(char *ascii, int length) {
  int sign = 1;
  int number = 0;
  for (int i = 0; i < length; i++) {
    char c = *(ascii + i);
    if (i == 0 && c == '-')
      sign = -1;
    else {
      if (c >= '0' && c <= '9')
        number = number * 10 + (c - '0');
    }
  }
  return number * sign;
}
float HELPER_ascii2Float(char *ascii, int length) {
  int sign = 1;
  int decimalPlace = 0;
  float number  = 0;
  float decimal = 0;
  for (int i = 0; i < length; i++) {
    char c = *(ascii + i);
    if (i == 0 && c == '-')
      sign = -1;
    else {
      if (c == '.')
        decimalPlace = 1;
      else if (c >= '0' && c <= '9') {
        if (!decimalPlace)
          number = number * 10 + (c - '0');
        else {
          decimal += ((float)(c - '0') / pow(10.0, decimalPlace));
          decimalPlace++;
        }
      }
    }
  }
  return (number + decimal) * sign;
}
String HELPER_ascii2String(char *ascii, int length) {
  String str;
  str.reserve(length);
  str = "";
  for (int i = 0; i < length; i++) {
    char c = *(ascii + i);
    str += String(c);
  }
  return str;
}
SD Card initialized.
myInt_1 = 2
myInt_2 = -105
myFloat_1 = 0.74
myFloat_2 = -46.08
myString_1 = Hello
myString_2 = newbiely.kr
 
시리얼 모니터는 마이크로 SD 카드에 저장된 것과 동일한 변수의 값을 표시합니다.
이제 코드를 변경하여 추가 변수를 포함할 수 있습니다.
※ 주의:
코드는 키-값 쌍의 배치를 고려하지 않습니다. 키를 찾을 때까지 파일의 시작부터 끝까지 검색할 것입니다.
 
비디오 제작은 시간이 많이 걸리는 작업입니다. 비디오 튜토리얼이 학습에 도움이 되었다면, YouTube 채널 을 구독하여 알려 주시기 바랍니다. 비디오에 대한 높은 수요가 있다면, 비디오를 만들기 위해 노력하겠습니다.