ESP32

ESP32 Arduino: Getting started with WiFi

기하 2021. 8. 16. 04:07

소개

이 게시물의 목적은 ESP32의 WiFi 기능을 사용하여 시작하는 방법, 보다 정확하게 주변 WiFi 네트워크를 스캔하는 방법 및 특정 WiFi 네트워크에 연결하는 방법을 설명하는 것입니다.

이 게시물은 또한 WiFi 네트워크에 연결될 때 ESP32의 로컬 IP 및 MAC 주소와 같은 일부 매개변수를 가져오는 방법도 다룹니다. WiFi 네트워크에서 연결을 끊는 방법도 설명합니다.

이 자습서는 ESP32를 사용하여 WiFi 네트워크에 연결하는 몇 가지 측면을 다룬 이전 자습서의 맨 위에 있습니다. 그럼에도 불구하고 이 게시물은 훨씬 더 광범위한 기능을 사용하고 있으며 ESP32에서 WiFi 시작 가이드 역할을 하는 것을 목표로 합니다. 이 게시물은 장치 실험을 시작할 때 일반적으로 수행하는 대부분의 기능을 다루기 때문입니다.

ESP32로 WiFi 네트워크에 연결하는 방법에 대한 MicroPython 버전에 관심이 있다면  게시물을 참조하십시오 . ESP32와 작동하도록 Arduino IDE를 아직 구성하지 않은 경우  게시물을 참조하세요 .

여기에서 수행된 모든 테스트  는 ESP32 FireBeetle 보드에 통합된 DFRobot의 ESP-WROOM-32 모듈에서 수행되었습니다 . ESP-WROOM-32 모듈만 사용하는 경우 여기 에서 Arduino IDE를 사용하여 장치에 프로그램을 업로드하는 방법에 대한 가이드를 확인할 수 있습니다.


설정 기능

가장 먼저 할 일은 WiFi.h 라이브러리를 포함하는 것입니다. 이 라이브러리를 사용하면 다른 많은 기능 중에서 WiFi 네트워크에 연결할 수 있습니다. 여기 에서 헤더 파일 정의를 확인하고 여기  에서 구현 파일을 확인할 수 있습니다.

ESP8266을 사용하는 배경이 있는 사람들을 위해 이번에는 헤더 파일이 ESP8266WiFi.h라는 ESP8266 라이브러리와 달리 일반적으로 WiFi라고 합니다.

1 #include <WiFi.h>

주목해야 할 중요한 점은 WiFi 라는 헤더 파일에 정의된 extern 변수 가 있다는 것 입니다. 이것은 WiFi 클래스 의 변수이며 앞으로 보게 되겠지만 많은 WiFi 기능에 액세스하는 데 사용할 것입니다.

다음으로 우리는 WiFi 네트워크 자격 증명, 보다 정확하게는 네트워크 이름(SSID)과 비밀번호를 보유하기 위해 두 개의 전역 변수를 선언할 것입니다. 이렇게 하면 이러한 변수에 쉽게 액세스하고 수정할 수 있습니다. 네트워크에 적용되는 값으로 값을 변경해야 합니다.

1
2
const char* ssid = "yourNetworkName";
const char* password = "yourNetworkPassword";

이제 나머지 코드를 모두 실행할 Arduino 설정 기능으로 이동합니다. 이것은 네트워크 구성 튜토리얼에 가깝기 때문에 메인 루프를 사용할 필요가 없습니다.

설정 기능의 첫 번째 줄에서 직렬 연결을 열어 프로그램 결과를 Arduino IDE 직렬 모니터에 출력할 수 있습니다. 그렇게 하려면 연결의 전송 속도(초당 비트 수)를 입력으로 전달하여 Serial 개체  시작 기능 을 호출하기만 하면 됩니다 .

연결 속도에 115200 값을 사용 합니다. 나중에 Arduino IDE의 직렬 모니터를 사용하여 ESP32에 직렬 연결을 설정할 때 이 값을 존중해야 하므로 이 값을 염두에 두는 것이 중요합니다.

1 Serial.begin(115200);

그런 다음 다음 섹션에서 정의할 두 개의 함수를 호출합니다. 이렇게 하면 코드를 다른 재사용 가능한 함수로 캡슐화하여 다른 프로젝트에서 읽거나 사용하기가 훨씬 쉽습니다.

scanNetworks 라는 첫 번째 함수 는 주변의 사용 가능한 WiFi 네트워크를 스캔하고 이에 대한 일부 정보를 인쇄합니다. connectToNetwork 라는 두 번째 것은 장치를 WiFi 네트워크에 연결합니다.

1
2
scanNetworks();
connectToNetwork();

지금은 이 기능을 블랙박스로 취급하고 작동한다고 가정합니다. 네트워크에 연결되면 ESP32에 로컬 IP가 할당되어야 합니다. 그것을 얻으려면  WiFi extern 변수  localIP 메소드 를 호출하기만 하면 됩니다 .

1 Serial.println(WiFi.localIP());

로컬 IP는 연결된 네트워크에 따라 달라지며 다른 연결에서 변경될 수 있다는 점에 유의하는 것이 중요합니다.

우리가 얻을 수 있는 다른 흥미로운 값은 MAC입니다. 따라서 ESP32의 MAC 주소를 얻으려면 WiFi extern 변수에서 다시 macAddress 메서드 를 호출하기  하면 됩니다.

1 Serial.println(WiFi.macAddress());

이 값은 ESP32의 네트워크 인터페이스에서 가져온 것으로 WiFi 네트워크에 연결되지 않은 경우에도 변경되지 않으며 검색할 수 있습니다.

설정 기능을 완료하기 위해 WiFi 네트워크에서 연결을 끊습니다. 그렇게 하려면  WiFi 변수  연결 해제 메서드 를 호출하기만 하면 됩니다 . 이 메서드는 구현에서  메서드를 호출하여 스테이션 작동 모드를 비활성화할 수 있는 플래그를 입력으로 수신 합니다.

이 매개변수 값은 기본적으로 false로 설정되어 있지만 true 값을 전달하여 WiFi를 비활성화합니다. 그런 다음 IP를 다시 가져오는 메서드를 호출하여 네트워크 연결이 끊겼고 더 이상 IP가 할당되지 않았는지 확인합니다.

1
2
WiFi.disconnect(true);
Serial.println(WiFi.localIP());

설정 기능에 대한 전체 코드는 아래에서 볼 수 있습니다. WiFi 네트워크의 자격 증명 전역 변수를 변경하는 것을 잊지 마십시오. 코드를 기능으로 분할하면 훨씬 더 명확한 설정 기능을 제공하므로 기능 구현을 보지 않고도 수행 중인 작업을 쉽게 이해할 수 있습니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
void setup() {


  Serial.begin(115200);


  scanNetworks();
  connectToNetwork();


  Serial.println(WiFi.macAddress());
  Serial.println(WiFi.localIP());


  WiFi.disconnect(true);
  Serial.println(WiFi.localIP());


}


WiFi 네트워크 검색

WiFi 네트워크에 연결하기 전에 주변 네트워크를 스캔합니다. 이와 함께 네트워크 이름(SSID), 신호 강도, MAC 및 암호화 유형과 같은 네트워크에 대한 일부 매개변수를 인쇄합니다. 이전에 말했듯이 이것은 scanNetworks 라는 함수에서 구현됩니다 .

네트워크 스캔을 시작하려면  앞서 언급한 WiFi extern 변수  scanNetworks 함수 를 호출하기만 하면 됩니다 . 이 호출은 스캔을 시작하고 성공적인 실행 시 발견된 네트워크 수를 반환합니다.

이 함수는 스캔이 비동기 모드에서 수행되어야 하는지 여부와 숨겨진 네트워크가 표시되어야 하는지 여부를 나타내는 두 개의 부울 인수를 수신합니다. 그러나  함수가 구현된 클래스  헤더 파일 에서 두 인수 모두 기본값이 false 이므로 입력 매개변수를 전달하지 않고 코드에서 함수를 호출할 수 있습니다. 단순화를 위해 그것이 우리가 할 일입니다.

1 int numberOfNetworks = WiFi.scanNetworks();

변수에서 찾은 네트워크의 수를 저장했습니다. 이는 해당 네트워크에 대한 정보가 저장될 데이터 구조를 반복하는 데 필요합니다.

따라서 스캔이 수행된 후 여기에 표시된 기능을 사용하여 각 네트워크의 매개변수에 액세스할 수 있습니다 . 그들 모두는 0에서 감지된 총 네트워크 수에서 1을 뺀 값까지 네트워크 수와 함께 정수를 인수로 받습니다.

코드에서 네트워크 이름(SSID), MAC 주소, 신호 강도(RSSI) 및 암호화 유형을 가져와서 인쇄합니다. 그러나 네트워크의 채널을 검색하는 기능도 있습니다.

그러나 계속 진행하기 전에 암호화 유형이 여기 에 정의된 열거형으로 반환된다는 점을 고려해야 합니다 . 따라서 이 열거형의 값을 수신하고 암호화 유형을 나타내는 텍스트 설명을 반환하는 보조 함수를 정의합니다. 이런 식으로 정수가 아닌 사람이 읽을 수 있는 결과를 얻습니다.

따라서 이 함수는 앞에서 언급한 열거 형인 wifi_auth_mode_t 유형의 변수를 입력으로  받고 각 가능한 값의 텍스트 설명을 반환하는 스위치 케이스를 수행합니다. 아래에서 구현을 확인할 수 있습니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
String translateEncryptionType(wifi_auth_mode_t encryptionType) {


  switch (encryptionType) {
    case (WIFI_AUTH_OPEN):
      return "Open";
    case (WIFI_AUTH_WEP):
      return "WEP";
    case (WIFI_AUTH_WPA_PSK):
      return "WPA_PSK";
    case (WIFI_AUTH_WPA2_PSK):
      return "WPA2_PSK";
    case (WIFI_AUTH_WPA_WPA2_PSK):
      return "WPA_WPA2_PSK";
    case (WIFI_AUTH_WPA2_ENTERPRISE):
      return "WPA2_ENTERPRISE";
  }
}

이제 암호화 유형을 문자열로 변환할 수 있는 기능이 있으므로 데이터 반복을 계속 진행할 수 있습니다. 그래서 우리는 네트워크 수 변수를 정지 조건으로 사용하여 루프를 수행하고 스캔된 각 네트워크의 정보를 얻기 위해 앞서 언급한 함수를 호출합니다.

이것은 사용자가 출력을 더 쉽게 읽을 수 있도록 몇 가지 추가 인쇄와 함께 아래에 표시됩니다. 또한 이전에 정의된 translateEncryptionType 함수에 대한 호출에 유의하십시오 .

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (int i = 0; i < numberOfNetworks; i++) {


    Serial.print("Network name: ");
    Serial.println(WiFi.SSID(i));


    Serial.print("Signal strength: ");
    Serial.println(WiFi.RSSI(i));


    Serial.print("MAC address: ");
    Serial.println(WiFi.BSSIDstr(i));


    Serial.print("Encryption type: ");
    String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
    Serial.println(encryptionTypeDescription);


    Serial.println("-----------------------");


  }

아래에서 전체 기능을 확인하십시오. 출력을 더 완벽하게 만들기 위한 몇 가지 추가 인쇄물이 있습니다.

1
2

4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void scanNetworks() {


  int numberOfNetworks = WiFi.scanNetworks();


  Serial.print("Number of networks found: ");
  Serial.println(numberOfNetworks);


  for (int i = 0; i < numberOfNetworks; i++) {


    Serial.print("Network name: ");
    Serial.println(WiFi.SSID(i));


    Serial.print("Signal strength: ");
    Serial.println(WiFi.RSSI(i));


    Serial.print("MAC address: ");
    Serial.println(WiFi.BSSIDstr(i));


    Serial.print("Encryption type: ");
    String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
    Serial.println(encryptionTypeDescription);
    Serial.println("-----------------------");


  }
}


WiFi 네트워크에 연결

이제 우리는 지정된 네트워크에 대한 ESP32의 연결을 처리하는 connectToNetwork 함수 를 구현할  것입니다.

연결하려는 네트워크가 이전 호출에 나열되어 있을 것으로 예상되지만 이전 스캔에서 얻은 네트워크와의 코드에는 링크가 없습니다. 그렇지 않으면 ESP32 범위에 없음을 의미할 가능성이 큽니다.

따라서 연결을 시작 하고 앞에서 언급한 WiFi 클래스 에서 Begin 메서드를 호출하고 전역 변수에 정의된 네트워크 이름과 암호를 모두 입력으로 전달합니다.

단순성을 위해 전역 변수에 직접 액세스하지만 해당 값을 connectToNetwork의 입력으로 전달하는 것이 함수의 재사용성 측면에서 더 적절할 것입니다.

1 WiFi.begin(ssid, password);

연결에 시간이 걸릴 수 있으므로 다음에는 Wi-Fi 변수를 폴링하여 연결이 완료될 때 확인합니다. 그렇게 하기 위해 여기  정의된 wl_status_t 유형의 구조를 반환하는 Status 메서드를 호출합니다 . 확인하려는 값은  WL_CONNECTED 입니다.

이에 대한 코드는 아래와 같습니다. 지속적으로 변수를 확인하는 것을 피하기 위해 루프의 각 반복 사이에 지연을 추가한다는 점에 유의하십시오. 또한 이 코드는 단순함을 위해 성공할 때까지 연결에 대해 무기한 폴링합니다. 당연히 더 강력한 솔루션을 위해 일종의 최대 폴링 시도 메커니즘을 만들 수 있습니다.

1
2

4
while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Establishing connection to WiFi..");
}

전체 함수의 최종 코드는 아래에서 볼 수 있습니다.

1
2

4
5
6
7
8
9
10
11
void connectToNetwork() {
  WiFi.begin(ssid, password);


  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Establishing connection to WiFi..");
  }


  Serial.println("Connected to network");


}


최종 코드

아래에서 전체 소스 코드를 확인하여 쉽게 복사하여 붙여넣을 수 있습니다. WiFi 네트워크의 자격 증명으로 전역 변수 값을 변경하는 것을 잊지 마십시오. 또한 이전 섹션에서 말했듯이 메인 루프 기능을 사용하지 않을 것이므로 비워둘 수 있습니다.

1
2

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
#include <WiFi.h>


const char* ssid = "yourNetworkName";
const char* password =  "yourNetworkPassword";


String translateEncryptionType(wifi_auth_mode_t encryptionType) {


  switch (encryptionType) {
    case (WIFI_AUTH_OPEN):
      return "Open";
    case (WIFI_AUTH_WEP):
      return "WEP";
    case (WIFI_AUTH_WPA_PSK):
      return "WPA_PSK";
    case (WIFI_AUTH_WPA2_PSK):
      return "WPA2_PSK";
    case (WIFI_AUTH_WPA_WPA2_PSK):
      return "WPA_WPA2_PSK";
    case (WIFI_AUTH_WPA2_ENTERPRISE):
      return "WPA2_ENTERPRISE";
  }
}


void scanNetworks() {


  int numberOfNetworks = WiFi.scanNetworks();


  Serial.print("Number of networks found: ");
  Serial.println(numberOfNetworks);


  for (int i = 0; i < numberOfNetworks; i++) {


    Serial.print("Network name: ");
    Serial.println(WiFi.SSID(i));


    Serial.print("Signal strength: ");
    Serial.println(WiFi.RSSI(i));


    Serial.print("MAC address: ");
    Serial.println(WiFi.BSSIDstr(i));


    Serial.print("Encryption type: ");
    String encryptionTypeDescription = translateEncryptionType(WiFi.encryptionType(i));
    Serial.println(encryptionTypeDescription);
    Serial.println("-----------------------");


  }
}


void connectToNetwork() {
  WiFi.begin(ssid, password);


  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Establishing connection to WiFi..");
  }


  Serial.println("Connected to network");


}


void setup() {


  Serial.begin(115200);


  scanNetworks();
  connectToNetwork();


  Serial.println(WiFi.macAddress());
  Serial.println(WiFi.localIP());


  WiFi.disconnect(true);
  Serial.println(WiFi.localIP());


}


void loop() {}


코드 테스트

코드를 테스트하려면 Arduino IDE를 사용하여 코드를 컴파일하고 업로드한 다음 직렬 모니터를 열어 결과를 확인하기만 하면 됩니다. 도구 -> 보드 메뉴 에서 올바른 보드를 선택하는 것을 잊지 마십시오 . 제 경우에는 FireBeetle ESP32를 선택해야 합니다.

또한 시리얼 모니터 에서 설정 기능에 정의된 115200 의 baud rate를 사용 하여 시리얼 연결이 제대로 이루어지도록 하십시오.

직렬 콘솔에서 얻은 결과는 아래 그림 1과 같으며 귀하의 결과도 비슷해야 합니다. 내 ESP32가 3개의 WiFi 네트워크를 감지했으며 각각에 대한 매개변수(MAC 주소, 네트워크 이름, 신호 강도 및 암호화 유형)가 예상대로 표시됩니다.

그 후 연결이 성공하고 장치가 라우터에서 할당한 로컬 IP를 얻습니다. 그런 다음 WiFi 네트워크에서 ESP32의 연결을 끊으면 예상대로 이전에 할당된 로컬 IP가 손실됩니다.

또한 ESP32의 MAC 주소는 코드에 정의된 대로 인쇄됩니다. 호기심을 위해 MAC 주소에는 공급업체에 대한 정보가 포함되어 있습니다. 따라서  조회 웹사이트 에서 얻은 MAC을 입력하면 ESP32의 제작자인 Espressif 가 반환되어야 합니다 .

그림 1 - ESP32 프로그램의 출력.


로컬 IP에 대한 한마디

앞서 언급했듯이 ESP32를 WiFi 네트워크에 연결하면 로컬 IP가 제공됩니다. 이 IP는 해당 네트워크 내에서만 유효하며 네트워크 외부에서 ESP32에 도달하는 데 사용할 수 없습니다.

이렇게 하려면 라우터를 포트 포워딩하고 공용 IP와 상호 작용해야 합니다. 그런 다음 라우터는 패킷을 ESP32로 전달합니다. 그러나 포트 포워딩 절차는 간단하지 않을 수 있으며 사용되는 라우터에 따라 다릅니다.

또한 라우터의 포트 포워딩은 네트워크를 보안 문제에 노출시킬 수 있으므로 시도하려는 경우 주의해서 진행하십시오.

네트워크 외부의 엔터티가 ESP32에 도달하기 위해 라우터의 공용 IP를 사용해야 하는 것과 동일한 방식으로 ESP32에서 네트워크 외부로 전송되는 모든 데이터에는 우리가 얻은 사설 IP가 아닌 네트워크의 공용 IP가 있습니다. 이전 코드에서.

당연히 이것은 네트워크 작동 방식을 단순화한 것일 뿐이며 더 자세히 설명하는 것은 이 게시물의 범위를 벗어납니다. 그럼에도 불구하고 어떻게 작동하는지 더 잘 이해할 수 있도록 해당 주제에 대해 약간의 연구를 수행하는 것이 좋습니다. 이는 ESP32와 다른 엔터티 간의 데이터 변경과 관련된 더 복잡한 응용 프로그램을 개발할 때 유용할 것입니다. 이 게시물에서 우리는 네트워크에 연결하고 데이터를 교환하지 않는 것에 대해 다루었으므로 프로그램의 아키텍처는 매우 간단합니다.


관련된 컨텐츠


관련 게시물