페이지

글목록

레이블이 esp12E인 게시물을 표시합니다. 모든 게시물 표시
레이블이 esp12E인 게시물을 표시합니다. 모든 게시물 표시

2017년 2월 15일 수요일

[ESP8266] MAC Address 읽기

MAC Address 읽는 함수로 ESP-8266 IC 내부의 2가지 MAC Address 를 읽을 수 있습니다.
참고한 사이트 주소는 다음과 같습니다.
http://www.esp8266.com/viewtopic.php?f=29&t=3587


아직 네트웍 개념이 없어서 잘은 모르겠지만,
1개는 일반 맥 어드레스이고(MAC{STA]) , 또 하나는 Wifi 단독 Server ?(MAC[SOFTAP]) 용 MAC Address 입니다.

Soft AP 는 공유기에 붙이지 않고, 8266가 단독으로 SSID,Password 를 치고 연결할 때
사용하는 방식 으로 알고 있습니다. 
그 뭐시냐... 핸드폰으로 Wifi 스캔하면 SSID가 보이죠. (^^ 공부 좀 더 해야겠네요.)

자 나중에 공부 더 해서 추가할께요.
아뭏든, 아두이노 IDE 에서 스케치 소스 코드만 있으면 실험 가능합니다.

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
#include <ESP8266WiFi.h>
 
uint8_t MAC_array[6];
char MAC_char[18];
 
 
void setup() {
  char ser_tx_buff[100];
  
  Serial.begin(115200);
 
  Serial.println();
  // put your setup code here, to run once:
 
  Serial.print("MAC[STA] ->");
  WiFi.macAddress(MAC_array);
  for (int i = 0; i < sizeof(MAC_array); ++i){
    sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
  }
  Serial.println(MAC_char);  
 
  MAC_char[0]=0;
  Serial.print("MAC[SOFTAP] ->");
  WiFi.softAPmacAddress(MAC_array);
  for (int i = 0; i < sizeof(MAC_array); ++i){
    sprintf(MAC_char,"%s%02x:",MAC_char,MAC_array[i]);
  }
  Serial.println(MAC_char);  
}
 
void loop() {
  // put your main code here, to run repeatedly:
}
cs

[ESP8266] Chip Information 읽기

원래는 Chip ID 만 알려고 했다가,
구글링을 해 보니, 더 많은 정보를 얻을 수 있었습니다.

다음 사이트에서 참고했습니다.
https://github.com/adafruit/ESP8266-Arduino

그냥 스케치 프로그램만 건드리면 되네요.

소스 코드는 다음과 같습니다.



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
void setup() {
  char ser_tx_buff[100];
  
  Serial.begin(115200);
 
  Serial.println();
//ESP.getFreeHeap();// returns the free heap size.
//ESP.getChipId();// returns the ESP8266 chip ID as a 32-bit integer.
//Several APIs may be used to get flash chip info:
//ESP.getFlashChipId();// returns the flash chip ID as a 32-bit integer.
//ESP.getFlashChipSize();// returns the flash chip size, in bytes, as seen by the SDK (may be less than actual size).
//ESP.getFlashChipSpeed();// returns the flash chip frequency, in Hz.
//ESP.getCycleCount();// returns the cpu instruction cycle count since start as an unsigned 32-bit. This is useful for accurate timing of very short actions like bit banging.
  sprintf(ser_tx_buff,"1. getFreeHeap = %d\n\r",ESP.getFreeHeap());
  Serial.print(ser_tx_buff);
  sprintf(ser_tx_buff,"2. getChipId = %d\n\r",ESP.getChipId());
  Serial.print(ser_tx_buff);
  sprintf(ser_tx_buff,"3. getFlashChipId = %d\n\r",ESP.getFlashChipId());
  Serial.print(ser_tx_buff);
  sprintf(ser_tx_buff,"4. getFlashChipSize = %d\n\r",ESP.getFlashChipSize());
  Serial.print(ser_tx_buff);
  sprintf(ser_tx_buff,"5. getFlashChipSpeed = %d\n\r",ESP.getFlashChipSpeed());
  Serial.print(ser_tx_buff);
  sprintf(ser_tx_buff,"5. getCycleCount = %d\n\r",ESP.getCycleCount());
  Serial.print(ser_tx_buff);
  // put your setup code here, to run once:
}
 
void loop() {
  // put your main code here, to run repeatedly:
 
}
cs

[ESP8266] SPI 통신 테스트 (ARDUINO IDE)

SPI 통신 테스트를 하려고 보니까, 
함수가 크게 2가지로 나눠서 볼 수 있는데, 특히 transferBytes(uint8_t * out, uint8_t * in, uint32_t size)함수는 
설명을 읽어 보아도 잘 모르겠어서 직접 테스트를 해 보게 되었습니다.

먼저 2가지라고 말씀 드린 함수는 대표적으로 다음과 같습니다.
PC의 다음 위치의 SPI.CPP 파일에 정의되어 있습니다.
C:\Users\trion\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\SPI
1. void SPIClass::transferBytes(uint8_t * out, uint8_t * in, uint32_t size)
2. void SPIClass::writeBytes(uint8_t * data, uint32_t size)

관련된 비슷하거나 파생된 함수는 몇가지 더 있습니다만, 이 2가지 함수가 많은 데이터를 보내면서
테스트하기에 적합해서 2가지 함수로 테스트를 진행했습니다.

하드웨어 구성은 예전에 테스트하다가 중단하고 그냥 놔둔 Serial Nand Flash IC(W25N01GxxIG)를 사용해서
ESP-8266의 HSPI 포트에 연결했습니다. 얼마 전까지 SD-Card 를 연결했던 포트죠.


[ESP-8266 개발 키트에서 사용한 SPI 포트들] 


NAND 랑 연결을 하고 테스트를 크게 2가지로 진행했습니다.
1. 10 바이트 전송.
  - writeBytes() 함수와 transferBytes() 함수의 차이점은 읽기가 되는지 안되는지의 차이 입니다.
    transferBytes() 함수로도 쓰기 기능만 사용할 수 있고 writeBytes() 함수가 약간 더 빠름니다.
  - 쉽게 말하면, writeBytes() 함수는 Write 전용, transferBytes() 함수는 Full Duplex 통신이라고 볼 수 있다.
  - 다음의 그림은 writeBytes() 함수와 읽기/쓰기 겸용(Full Duplex)으로 사용한 transferBytes() 함수의 전송속도 차이를 보여주는 신호 파형이다.



 2. 100 바이트 전송.
다음은 이 2개의 함수에서 대용량 바이트를 전송할 경우의 특성을 살펴 보았다.
여러 바이트를 전송할 경우에, ESP IC는 기본으로 다른 칩에서의 DMA 기능처럼 SCLK가 끊어짐 없이 출력되었다.
하지만 64-Byte 마다 약간의 딜레이가 있다. 
이 딜레이는  transferBytes() 함수에서 읽기 기능을 사용했을 경우 크게 늘어난다. 
읽기 기능을 사용하지 않으면 두 함수의 64 Byte 간의 딜레이의 차이는 별로 없다.
[transferBytes() 함수의 특성]



 [writeBytes() 함수의 특성]



다음은 아두이노 IDE 툴에서 사용한 프로그램 소스 코드입니다.
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
#include <Arduino.h>
#include "SPI.h"
#include "HardwareSerial.h"
#define nSPI_CS   4
void setup() {
  int i;
  uint8_t in_buf[100],out_buf[100];
  char ser_tx_buf[100];
  
  delay(1000);
  
  Serial.begin(115200);
  // put your setup code here, to run once:
  digitalWrite(nSPI_CS, HIGH);
  pinMode(nSPI_CS, OUTPUT);
  pinMode(SCK, SPECIAL);  ///< GPIO14
  pinMode(MISO, SPECIAL); ///< GPIO12
  pinMode(MOSI, SPECIAL); ///< GPIO13
  SPI1C = 0;
  SPI.setFrequency(20000000); ///< 20MHz
  SPI1U = SPIUMOSI | SPIUDUPLEX | SPIUSSE;
  SPI1U1 = (7 << SPILMOSI) | (7 << SPILMISO);
  SPI1C1 = 0;
  for (i=0;i<10;i++)
  {
    out_buf[i] = i;
  }
    out_buf[0= 0x9F;
    out_buf[1= 0;
    out_buf[2= 0;
    out_buf[3= 0;
    out_buf[4= 0;
    
  digitalWrite(nSPI_CS, LOW);
  // 10 Byte Transfer
  //SPI.transferBytes(out_buf,in_buf,10);
  //SPI.writeBytes(out_buf,10);
  // 100 Byte transfer
  //SPI.transferBytes(out_buf,in_buf,100);
  //SPI.transferBytes(NULL,NULL,100);
  //SPI.transferBytes(out_buf,NULL,100);
  //SPI.transferBytes(NULL,in_buf,100);
  SPI.writeBytes(out_buf,100);
  digitalWrite(nSPI_CS, HIGH);
  sprintf(ser_tx_buf,"\n\nSPI Test Program in:%02X,%02X,%02X,%02X,%02X\n\r",in_buf[0],in_buf[1],in_buf[2],in_buf[3],in_buf[4]);
  Serial.print(ser_tx_buf);
}
void loop() {
  // put your main code here, to run repeatedly:
}
cs

2017년 2월 13일 월요일

[ESP-8266] 저장된 SSID/Password 지우기 (Arduino IDE)

어디서 저장이 된 것인지 잘 모르겠지만,
SSID 와 Password가 저장되어서 지우고 싶을 때가 있다.

그럴 땐, 이렇게.. (ARDUINO IDE 에서 사용하는 함수이다.)

WiFi.disconnect();

2017년 2월 12일 일요일

[ESP8266] SD-Card(SPI-mode) 핀/스피드 설정

아두이노 IDE 툴의 스케치 프로그램에서 SD-Card 설정은 다음의 함수로 설정 가능하다.

1
2
3
4
5
6
7
8
9
10
11
12
boolean SDClass::begin(uint8_t csPin, uint32_t speed) {
  /*
    Performs the initialisation required by the sdfatlib library.
    Return true if initialization succeeds, false otherwise.
   */
  return card.init(speed, csPin) &&
         volume.init(card) &&
         root.openRoot(volume);
}
cs
이전에 Ftp 서버 스케치 프로그램의 void setup(void) 함수 내에서, 다음과 같이 사용했다.
1
2
3
4
  if (SD.begin(4)) {
      Serial.println("SD opened!");
      ftpSrv.begin("esp8266","esp8266");    //username, password for ftp.  set ports in ESP8266FtpServer.h  (default 21, 50009 for PASV)
  }    
cs

즉 MISO,MOSI,SCLK 는 HSPI 포트들을 사용하므로 고정되어 있으므로, CS 핀만 따로 지정해 주면 된다.
현재 위의 소스코드에서 Clock Speed는 사용하지 않았는데, 파라메터를 넣지 않으면 디폴트값이 들어간다.
하지만, 디폴트 값이 얼만지는 잘 모르겠다.
GPIO 4번핀을 CS핀으로 사용하고, Clock speed는 기본이다.

가령, SD.begin(4,40000000) 라고 하면 GPIO 4번핀을 CS핀으로 사용하고, Clock speed는 40MHz 이다.
최대 클럭 스피드는 시스템 클럭의 /2 이다.

[ESP8266] WiFi FTP Server with SD-Card[5] (속도 개선)

esp8266 FTP 서버의 전송 속도를 개선하는 방법을 여러가지 찾아보고 적용해 봤습니다.

전송 속도에 관련된 사항은 다음과 같습니다. 
1. WIFI FTP BUFFER 의 크기 : ESP8266FtpServer.h 파일에 FTP_BUF_SIZE 로 정의가 되어 있는데,
   크기가 기본으로 1024 // 512 로 설정되어 있는데 이 설정으로는 너무 느리다.
   512 로 9KB/s , 1024로 18KB/s 밖에 안나온다.
   하지만 이 크기를 1460 의 배수인 1460*2 로 바꾸면 460KB/s 의 속도가 나온다. 
   이 속도는 SD-Card에서 읽어서 PC로 전송하는 속도이고, SPI Single 방식의 SD-Card Write 시에는 약 86KB/s 가 나온다.
   즉, SD 카드를 읽는 데는 엄청 빠른데, 쓸 때는 SPI Single 에다가 Write 할 동안 기다려야 하므로 아주 느리다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include <SPI.h>
#include <SD.h>
//#include <FS.h>
#include <WiFiClient.h>
#define FTP_SERVER_VERSION "FTP-2016-01-14"
#define FTP_CTRL_PORT    21       // Command port on wich server is listening  
#define FTP_DATA_PORT_PASV 50009  // Data port in passive mode
#define FTP_TIME_OUT  5      // Disconnect client after 5 minutes of inactivity
#define FTP_CMD_SIZE 255 + 8 // max size of a command
#define FTP_CWD_SIZE 255 + 8 // max size of a directory name
#define FTP_FIL_SIZE 255     // max size of a file name
//#define FTP_BUF_SIZE 1024 //512   // size of file buffer for read/write
#define FTP_BUF_SIZE 2*1460
cs

2. CPU Clock 속도 Up : 80MHz 에서 160MHz 로 올리면 조금 더 빨라진다. 
3. SPI CLK 속도 UP : 현재 24MHz 까지 올렸는데 50MHz 까지 올려 볼 예정이다.
  이 과정은 선 길이에 영향을 많이 받기 때문에, PCB가 나와봐야 알 수 있을 것이다.


버퍼 크기는 1460 배수가 아니면 속도 차가 읽기 모드에서 최대 51배나 차이가 납니다.
쓰실 때, 꼭 알아두세요. ^^

다음은 FTP 서버에서 PC로 전송시 속도를 동영상으로 찍어 봤습니다.


[ESP8266] WiFi FTP Server with SD-Card[4] (디렉토리 읽기 개선)

ESP8266 FTP 서버에서 파일을 전송을 하던지 PC에서 FTP 서버로 전송을 하면
ESP8266 의 디렉토리가 몇개씩 사라지는 현상이 있어서 원인을 한참 찾다가 고쳐졌습니다.

정확한 원인은 잘 모르겠고, SD Card 에서 디렉토리를 읽어서 보여줄 때,
함수를 1개(rewindDirectory) 더 추가해야 이 현상이 없어졌습니다.

어쩌면 SPIFFS 메모리에서는 이런 현상이 안나타날 지도 모르겠습니다.
제가 SPIFFS 메모리로 된 FTP 서버 프로그램을 SD 카드용으로 바꿔서 여러가지 오동작이 많이 발생하는 것 같습니다.

FTP 서버에서 디렉토리를 새로고치는 명령이 "MLSD" 이므로 
ESP8266FtpServer.ccp 의 processCommand 함수에서 "MLSD" 명령을 처리하는 부분을 수정하면 됩니다.
수정한 코드는 다음과 같습니다.
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
  //
  //  MLSD - Listing for Machine Processing (see RFC 3659)
  //
  else if! strcmp( command, "MLSD" ))
  {
    if! dataConnect())
      client.println( "425 No data connection MLSD");
    else
    {
      client.println( "150 Accepted data connection");
      uint16_t nm = 0;
 
      File dir=SD.open(cwdName);
      File entry;
 
      dir.rewindDirectory();
          
      char dtStr[ 15 ];
 
        while(1)
        {
            entry =  dir.openNextFile();
            if (!entry)
                break;
            String fn,fs;
            fn = entry.name();
            fs = String(entry.size());
              data.println( "Type=file;Size=" + fs + ";"+"modify=20000101160656;" +" " + fn);
              nm ++;
        }
        client.println( "226-options: -a -l");
        client.println( "226 " + String(nm) + " matches total");
      }
      data.stop();
      entry.close();
  }
cs

SD.open() 함수 다음에 rewindDirectory(); 함수를 사용하면 됩니다.

[ESP8266] EEPROM Test (Arduino IDE)

ESP8266 에서 EEPROM 은 실제로는 없고 외부에 있는 SPIFF 플래쉬 메모리의 일부를 사용하는 것이다.

EEPROM 을 다루는 함수들은 Library 에 있는 EEPROM.cpp 에 정의되어 있다.
라이브러리 소스의 위치는 다음과 같다.
C:\Users\trion\AppData\Local\Arduino15\packages\esp8266\hardware\esp8266\2.3.0\libraries\EEPROM

함수들의 종류는 다음과 같다.
1. void EEPROMClass::begin(size_t size)
   : 예를 들어 아두이노 스케치 코드에서 begin.EEPROM(512); 라고 코딩을 하면, EEPROM 을 512바이트 할당하고,
     EEPROM 관련 항목들을 초기화한다.
2. uint8_t EEPROMClass::read(int address)
   : 위에서 예를 든 begin 함수와 같이 설명하자면, 어드레스 0~511 까지 512개의 바이트 데이터를 해당 주소에서 읽어 올 수 있다.
3. void EEPROMClass::write(int address, uint8_t value)
   : 해당 주소(address)에 값을 쓴다. 이 때, 실제로 EEPROM에 물리적으로 기록되는 것이 아니고,
     램으로 된 버퍼값을 바꾸는 것이다.
4. bool EEPROMClass::commit()
   : 실제로 물리적으로 EEPROM(외부 플래쉬 메모리)에 값을 기록해서 리셋이나 전원이 꺼져도 값을 유지할 수 있다.

다음은 아두이노 IDE 툴에서 EEPROM 을 테스트한 코드 입니다.
: NODE MCU V3.0 보드의 Flash 버튼을 누르면 EEPROM 의 0번 어드레스의 값의 0번 비트가 토글 되면서,
  값을 기록하고 소프트웨어 리셋을 이용하여 리셋을 한 후,
  EEPROM의 0번 어드레스의 값이 바뀌어 있는지 EEPROM을 읽어서 시리얼 포트에 출력해 본 테스트입니다.

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
#include <EEPROM.h>
 
const int buttonPin = 0;     // the number of the pushbutton pin
int buttonState = 0,buttonState_old=0;         // variable for reading the pushbutton status
byte value;
 
void setup() {
  // put your setup code here, to run once:
  delay(1000);
  Serial.begin(115200);
  EEPROM.begin(512);
  pinMode(buttonPin, INPUT);
  value = EEPROM.read(0);
  Serial.println("");
  Serial.print("EEPROM value = ");
  Serial.println(value,HEX);
 
  buttonState_old = buttonState = digitalRead(buttonPin);
}
 
void loop() {
  // put your main code here, to run repeatedly:
  buttonState_old = buttonState;
  buttonState = digitalRead(buttonPin);
  if (buttonState_old != buttonState)
  {
    if (buttonState == LOW) 
    {
      value = EEPROM.read(0);
      value ^= 1;
      EEPROM.write(0, value);
      EEPROM.commit(); 
      Serial.print("Button Pressed !, EEPROM value = ");
      Serial.println(value,HEX);
      Serial.println("ESP8266 Software Reset");
      ESP.reset();
    }
  }
 
}
cs


다음은 위의 ESP8266 아두이노 IDE 스케치 코드에의해 디버그용으로 시리얼에 표시한 내용 입니다.


[ESP8266] WiFi FTP Server with SD-Card[3] (Soft AP mode)

1. 오류 발생 : 파일을 전송하는데 처음에만 되고 그 이후로는 안되서 오류 분석 중. 추가로 파일 전송을 하고 난 후, 디렉토리가 없어짐.
2. 오류 원인 : 이름이 한글로된 파일이나 이름에 콤마가 2개 이상인 파일이 문제를 일으켜서 FTP 서버가 동작을 안하는 경우가 있었다.
3. 해결책 : 위의 종류의 파일을 취급하지 않거나, LFN(Long File Name)을 지원하거나 UNICODE(한글 지원)이 되도록 프로그램을 고쳐야 함. (디렉토리 해결책은 다음 글에 올려 놨음)


안녕하세요, 이번에는 Soft AP 를 이용한 8266 FTP Server를 만들어 봤습니다.

주변의 공유기에 붙여서 IP를 할당받아서 사용하는 방법이 아니라, 
8266 자체가 Ftp Server가 됩니다.

이것도 FTP Server가 공식적인 예제가 아니여서인지, 처음에는 Soft AP 는 잘 구현되어서 
SSID 와 Password를 치고 들어갔는데 Ftp Server 동작이 안됐었습니다.

많이 고생을 했는데, 알고 보니 SoftAPIP 주소가 아니라 localIP 주소에 의해 Ftp Server가 동작되도록 되어 있었습니다.
아직 Esp8266 과 네트웍 개념도 없고 c++ 문법도 잘 몰라서 SoftIP 주소에 의해 동작하도록 하는 방법으로 수정할 순 없겠고,
localIP 주소를 수정해서 동작하도록 만들었습니다.

예전의 SD 카드에 의해 동작하는 FTP 예제에서 아두이노 스케치 코드만 조금 고쳐주면 됩니다.

SoftAP 로 동작하는 데에는 독립적인 SSID 와 비밀번호가 필요하니 정의해 놓고,
1
2
3
const char* ssid = "FISI_Server";
const char* password = "0317358631";
 
cs

FTP 에서 사용할 IP 및 Gateway,subnetMask 주소를 정의했습니다.
1
2
3
4
5
// config static IP
IPAddress apIP(19216841);  
IPAddress gateway(19216841); // set gateway to match your network
IPAddress subnet(2552552550); // set subnet mask to match your network
 
cs

config 함수로 실제 local IP,Gateway,SubnetMask 주소를 세팅합니다.
그리고 아무 상관은 없지만 기분이 찝찝하니 SoftAP Ip,gateway,subnetmask 주소도 세팅해 주고,
WiFi.softAP 함수로 위에서 정의해 둔, SSID 와  비밀번호로 AP를 만듭니다.
1
2
3
4
5
6
7
8
9
10
  WiFi.config(apIP, gateway, subnet);
  Serial.println();
  Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.mode(WIFI_AP);
  WiFi.disconnect();
  delay(100);
  WiFi.softAPConfig(apIP, gateway, subnet);
  WiFi.softAP(ssid, password);
 
cs


위의 소스코드에서 쓸데없이 들어있는 것도 있을텐데, 또 할일들이 많아서 더 테스트는 못했습니다.

전체 아두이노 IDE의 스케치 파일의 소스 코드는 다음과 같습니다.
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
83
84
85
86
87
88
89
90
91
92
93
94
95
96
#include <ESP8266WiFi.h>
#include <WiFiClient.h>
#include <ESP8266WebServer.h>
#include <ESP8266FtpServer.h>
 
const char* ssid = "FISI_Server";
const char* password = "0317358631";
 
// config static IP
IPAddress apIP(19216841);  
IPAddress gateway(19216841); // set gateway to match your network
IPAddress subnet(2552552550); // set subnet mask to match your network
 
 
ESP8266WebServer server(80);
FtpServer ftpSrv;   //set #define FTP_DEBUG in ESP8266FtpServer.h to see ftp verbose on serial
 
 
 
void handleRoot() {
  server.send(200"text/plain""hello from esp8266!");
 
}
 
void handleNotFound(){
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET)?"GET":"POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";
  for (uint8_t i=0; i<server.args(); i++){
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }
  server.send(404"text/plain", message);
}
 
void setup(void){
  delay(1000);
  Serial.begin(115200);
 
  Serial.println("");
  Serial.println(WiFi.SSID());
  Serial.println(WiFi.psk());
  WiFi.config(apIP, gateway, subnet);
 
  Serial.println();
  Serial.print("Configuring access point...");
  /* You can remove the password parameter if you want the AP to be open. */
  WiFi.mode(WIFI_AP);
  WiFi.disconnect();
  delay(100);
  WiFi.softAPConfig(apIP, gateway, subnet);
  WiFi.softAP(ssid, password);
 
  IPAddress myIP = WiFi.softAPIP();
  Serial.print("AP IP address: ");
  Serial.println(myIP);
 
  Serial.println("");
  Serial.println("");
 
  WiFi.printDiag(Serial);
  
  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(WiFi.SSID());
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
 
  /////FTP Setup, ensure SPIFFS is started before ftp;  /////////
  
  if (SD.begin(4)) {
      Serial.println("SD opened!");
      ftpSrv.begin("esp8266","esp8266");    //username, password for ftp.  set ports in ESP8266FtpServer.h  (default 21, 50009 for PASV)
  }    
      Serial.println("FTP server On!");
  /*
  if (SPIFFS.begin()) {
      Serial.println("SPIFFS opened!");
      ftpSrv.begin("esp8266","esp8266");    //username, password for ftp.  set ports in ESP8266FtpServer.h  (default 21, 50009 for PASV)
  }    */
}
 
void loop(void){
  ftpSrv.handleFTP();        //make sure in loop you call handleFTP()!!  
  server.handleClient();
 
}
cs

다 준비가 됐으니, Wifi 로 미리 설정해 둔 SSID 와 비번으로 Esp8266 에 접속합니다.



접속이 됐으면 이번에는 랜드폰 앱으로 FTP Client 앱을 받아서 설치합니다.
여러가지가 있는데 저는 터보 클라이언트라는 앱을 사용했습니다.


FTP 프로그램을 실행해서 설정을 다음과 같이 했습니다.


그리고 FTP 서버에 접속하니 SD 카드에 들어있는 내용이 나왔습니다. SOFT AP 도 완료. ~` ^^;