ESP32

Visualize Your Sensor Readings from Anywhere in the World (ESP32/ESP8266 + MySQL + PHP)

기하 2021. 8. 16. 06:12

이 프로젝트에서는

전 세계 어디에서나 액세스할 수 있는 플롯에 센서 판독값을 표시하는 웹 페이지를 만듭니다. 

요약하면 MySQL 데이터베이스에 센서 판독값을 게시하기 위해

PHP 스크립트에 요청하는 ESP32 또는 ESP8266 클라이언트를 빌드합니다.

예를 들어 ESP 보드에 연결된 BME280 센서를 사용할 것입니다. 

제공된 코드를 수정하여 다른 센서에서 판독값을 보내거나 여러 보드를 사용할 수 있습니다.

이 프로젝트를 만들려면 다음 기술을 사용합니다.

  • Arduino IDE로 프로그래밍된 ESP32 또는 ESP8266
  • 호스팅 서버 및 도메인 이름
  • MySQL 데이터베이스에 데이터를 삽입하고 웹 페이지에 표시하는 PHP 스크립트
  • 판독값을 저장할 MySQL 데이터베이스
  • 차트의 데이터베이스에서 데이터를 플롯하는 PHP 스크립트

다음 프로젝트를 읽는 데 도움이 될 수도 있습니다.

 

1. PHP 애플리케이션 및 MySQL 데이터베이스 호스팅

이 프로젝트의 목표는 ESP32 또는 ESP8266의 센서 판독값을 저장할 수 있는

고유한 도메인 이름과 호스팅 계정을 갖는 것입니다. 

자신의 서버 도메인에 액세스하여 전 세계 어디에서나 판독값을 시각화할 수 있습니다. 

다음은 프로젝트에 대한 높은 수준의 개요입니다.

 

PHP와 MySQL을 제공하는 모든 호스팅 서비스는 이 튜토리얼에서 작동합니다. 

 

참고 : 당신은 또한 LAMP (리눅스, 아파치, MySQL은, PHP) 서버 를 라즈베리파이에 설치하여

로컬네트워크에 데이타를 엑세스할 수 있습니다.

그러나 이 자습서의 목적은 전 세계 어디에서나 액세스할 수 있는

자체 도메인 이름으로 판독값을 게시하는 것입니다. 

이를 통해 타사 IoT 플랫폼에 의존하지 않고도 ESP 판독값에 쉽게 액세스할 수 있습니다.

2. MySQL 데이터베이스 준비

호스팅 계정에 가입하고 도메인 이름을 설정 한 후 cPanel 또는 유사한 대시보드에 로그인할 수 있습니다. 

그런 다음 다음 단계에 따라 데이터베이스, 사용자 이름, 암호 및 SQL 테이블을 만듭니다.

데이터베이스 및 사용자 생성

1. 검색창에 "database"를 입력하고 "MySQL Database Wizard"를 선택합니다.

 

2. 원하는 데이터베이스 이름을 입력합니다. 

제 경우 데이터베이스 이름은esp_data. 그런 다음 "다음 단계" 버튼을 누릅니다.

 

참고: 나중에 호스트가 제공하는 접두사와 함께 데이터베이스 이름을 사용해야 합니다(위 스크린샷에서 내 데이터베이스 접두사는 흐릿함). 나는 그것을 다음과 같이 언급 할 것이다.example_esp_data 지금부터.

 

3. 데이터베이스 사용자 이름을 입력하고 암호를 설정합니다. 

나중에 PHP 코드와 데이터베이스 연결을 설정하는 데 필요하기 때문에 이러한 세부 정보를 모두 저장해야 합니다.

 

그게 다야! 새 데이터베이스와 사용자가 성공적으로 생성되었습니다. 

나중에 필요하므로 이제 모든 세부 정보를 저장하십시오.

  • 데이터베이스 이름 : example_esp_data
  • 사용자 이름 : example_esp_board
  • 비밀번호 : 귀하의 비밀번호

SQL 테이블 생성

데이터베이스와 사용자를 생성한 후 cPanel 대시보드로 돌아가 "phpMyAdmin"을 검색합니다.

왼쪽 사이드바에서 데이터베이스 이름을 선택합니다. example_esp_data "SQL" 탭을 엽니다.

 

 

중요: 열었는지 확인하십시오.example_esp_data데이터 베이스. 

그런 다음 SQL 탭을 클릭합니다. 이 정확한 단계를 따르지 않고 SQL 쿼리를 실행하지 않으면

잘못된 데이터베이스에 테이블을 생성할 수 있습니다.

다음 스니펫에서 SQL 쿼리를 복사합니다.

 

CREATE TABLE Sensor (
    id INT(6) UNSIGNED AUTO_INCREMENT PRIMARY KEY,
    value1 VARCHAR(10),
    value2 VARCHAR(10),
    value3 VARCHAR(10),
    reading_time TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
)

SQL 쿼리 필드(빨간색 사각형으로 강조 표시됨)에 붙여넣고 "이동" 버튼을 눌러 테이블을 만듭니다.

 

 

그러면 example_esp_data  데이터베이스에 Senor 이라는 테이블이 만들어지는 것을 볼 수 있습니다.

 

3. PHP 스크립트 HTTP POST – MySQL 데이터베이스에 데이터 삽입

이 섹션에서는 ESP32 또는 ESP8266에서 들어오는 요청을 수신하고

데이터를 MySQL 데이터베이스에 삽입하는 PHP 스크립트를 만들 것입니다.

 

참고: 이 자습서를 따르고 있고 PHP 또는 MySQL에 익숙하지 않은 경우

이러한 정확한 파일을 만드는 것이 좋습니다. 그렇지 않으면 다른 URL 경로와 함께

제공된 ESP 스케치를 수정해야 합니다.

정확한 이름과 확장자를 사용하여 /public_html post-data.php새 파일을 만듭니다 : 

 

새로 생성된 파일( post-data.php )을 편집하고 다음 스니펫을 복사합니다.

<?php
/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
*/

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Keep this API Key value to be compatible with the ESP32 code provided in the project page. If you change this value, the ESP32 sketch needs to match
$api_key_value = "tPmAT5Ab3j7F9";

$api_key = $value1 = $value2 = $value3 = "";

if ($_SERVER["REQUEST_METHOD"] == "POST") {
    $api_key = test_input($_POST["api_key"]);
    if($api_key == $api_key_value) {
        $value1 = test_input($_POST["value1"]);
        $value2 = test_input($_POST["value2"]);
        $value3 = test_input($_POST["value3"]);
        
        // Create connection
        $conn = new mysqli($servername, $username, $password, $dbname);
        // Check connection
        if ($conn->connect_error) {
            die("Connection failed: " . $conn->connect_error);
        } 
        
        $sql = "INSERT INTO Sensor (value1, value2, value3)
        VALUES ('" . $value1 . "', '" . $value2 . "', '" . $value3 . "')";
        
        if ($conn->query($sql) === TRUE) {
            echo "New record created successfully";
        } 
        else {
            echo "Error: " . $sql . "<br>" . $conn->error;
        }
    
        $conn->close();
    }
    else {
        echo "Wrong API Key provided.";
    }

}
else {
    echo "No data posted with HTTP POST.";
}

function test_input($data) {
    $data = trim($data);
    $data = stripslashes($data);
    $data = htmlspecialchars($data);
    return $data;
}

 

파일을 저장하기 전에 다음화일들을 수정해야 합니다. 

$dbname$username 그리고 $password 

// Your Database name
$dbname = "example_esp_data";
// Your Database user
$username = "example_esp_board";
// Your Database user password
$password = "YOUR_USER_PASSWORD";

 

데이터베이스 이름, 사용자 이름 및 암호를 추가한 후 파일을 저장하고 이 자습서를 계속합니다. 

다음 URL 경로에서 도메인 이름에 액세스하려고 하면 다음 메시지가 표시됩니다.

http://example.com/post-data.php

 

 

4. PHP 스크립트 – 차트에서 데이터베이스 콘텐츠 시각화

/public_html 디렉토리 에 다른 PHP 파일을 생성 하여

웹 페이지의 차트에 데이터베이스 콘텐츠를 표시합니다. 새 파일 이름: esp-chart.php

 

새로 생성된 파일( esp-chart.php )을 편집하고 다음 코드를 복사합니다.

 

<!--
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

-->
<?php

$servername = "localhost";

// REPLACE with your Database name
$dbname = "REPLACE_WITH_YOUR_DATABASE_NAME";
// REPLACE with Database user
$username = "REPLACE_WITH_YOUR_USERNAME";
// REPLACE with Database user password
$password = "REPLACE_WITH_YOUR_PASSWORD";

// Create connection
$conn = new mysqli($servername, $username, $password, $dbname);
// Check connection
if ($conn->connect_error) {
    die("Connection failed: " . $conn->connect_error);
} 

$sql = "SELECT id, value1, value2, value3, reading_time FROM Sensor order by reading_time desc limit 40";

$result = $conn->query($sql);

while ($data = $result->fetch_assoc()){
    $sensor_data[] = $data;
}

$readings_time = array_column($sensor_data, 'reading_time');

// ******* Uncomment to convert readings time array to your timezone ********
/*$i = 0;
foreach ($readings_time as $reading){
    // Uncomment to set timezone to - 1 hour (you can change 1 to any number)
    $readings_time[$i] = date("Y-m-d H:i:s", strtotime("$reading - 1 hours"));
    // Uncomment to set timezone to + 4 hours (you can change 4 to any number)
    //$readings_time[$i] = date("Y-m-d H:i:s", strtotime("$reading + 4 hours"));
    $i += 1;
}*/

$value1 = json_encode(array_reverse(array_column($sensor_data, 'value1')), JSON_NUMERIC_CHECK);
$value2 = json_encode(array_reverse(array_column($sensor_data, 'value2')), JSON_NUMERIC_CHECK);
$value3 = json_encode(array_reverse(array_column($sensor_data, 'value3')), JSON_NUMERIC_CHECK);
$reading_time = json_encode(array_reverse($readings_time), JSON_NUMERIC_CHECK);

/*echo $value1;
echo $value2;
echo $value3;
echo $reading_time;*/

$result->free();
$conn->close();
?>

<!DOCTYPE html>
<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
  <script src="https://code.highcharts.com/highcharts.js"></script>
  <style>
    body {
      min-width: 310px;
    	max-width: 1280px;
    	height: 500px;
      margin: 0 auto;
    }
    h2 {
      font-family: Arial;
      font-size: 2.5rem;
      text-align: center;
    }
  </style>
  <body>
    <h2>ESP Weather Station</h2>
    <div id="chart-temperature" class="container"></div>
    <div id="chart-humidity" class="container"></div>
    <div id="chart-pressure" class="container"></div>
<script>

var value1 = <?php echo $value1; ?>;
var value2 = <?php echo $value2; ?>;
var value3 = <?php echo $value3; ?>;
var reading_time = <?php echo $reading_time; ?>;

var chartT = new Highcharts.Chart({
  chart:{ renderTo : 'chart-temperature' },
  title: { text: 'BME280 Temperature' },
  series: [{
    showInLegend: false,
    data: value1
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#059e8a' }
  },
  xAxis: { 
    type: 'datetime',
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Temperature (Celsius)' }
    //title: { text: 'Temperature (Fahrenheit)' }
  },
  credits: { enabled: false }
});

var chartH = new Highcharts.Chart({
  chart:{ renderTo:'chart-humidity' },
  title: { text: 'BME280 Humidity' },
  series: [{
    showInLegend: false,
    data: value2
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    }
  },
  xAxis: {
    type: 'datetime',
    //dateTimeLabelFormats: { second: '%H:%M:%S' },
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Humidity (%)' }
  },
  credits: { enabled: false }
});


var chartP = new Highcharts.Chart({
  chart:{ renderTo:'chart-pressure' },
  title: { text: 'BME280 Pressure' },
  series: [{
    showInLegend: false,
    data: value3
  }],
  plotOptions: {
    line: { animation: false,
      dataLabels: { enabled: true }
    },
    series: { color: '#18009c' }
  },
  xAxis: {
    type: 'datetime',
    categories: reading_time
  },
  yAxis: {
    title: { text: 'Pressure (hPa)' }
  },
  credits: { enabled: false }
});

</script>
</body>
</html>

 

 

 $dbname, $username 그리고 $password 를 추가한 후 파일을 저장하고 이 프로젝트를 계속하십시오.

// Your Database name
$dbname = "example_esp_data";
// Your Database user
$username = "example_esp_board";
// Your Database user password
$password = "YOUR_USER_PASSWORD";

 

다음 URL 경로에서 도메인 이름에 액세스하려고 하면 다음이 표시됩니다.

http://example.com/esp-chart.php

 

 

브라우저에 3개의 빈 차트가 표시되면 모든 것이 준비되었음을 의미합니다. 

다음 섹션에서는 ESP32 또는 ESP8266 센서 판독값을 게시하는 방법을 배웁니다.

 

차트를 작성하기 위해 Highcharts 라이브러리를 사용합니다  . 

시간 경과에 따른 온도, 습도 및 압력의 세 가지 차트를 생성합니다. 

차트는 최대 40개의 데이터 요소를 표시하고 30초마다 새 판독값이 추가되지만

코드에서 이러한 값을 변경합니다.

5. ESP32 또는 ESP8266 준비

이 프로젝트는 ESP32 및 ESP8266 보드와 모두 호환됩니다. 

간단한 회로를 조립하고 30초마다 데이터베이스에 온도, 습도, 압력 등을 삽입하기 위해

제공된 스케치를 업로드하기만 하면 됩니다.

 

 

필요한 부품

이 예에서는 BME280 센서에서 센서 판독값을 얻습니다. 

다음은 이 프로젝트의 회로를 구축하는 데 필요한 부품 목록입니다.

 

회로도

우리가 사용하는 BME280 센서 모듈은 I2C 통신 프로토콜을 통해 통신하므로

ESP32 또는 ESP8266 I2C 핀에 연결해야 합니다.

 

ESP32에 BME280 배선

ESP32 I2C 핀은 다음과 같습니다.

  • GPIO 22:  SCL(SCK)
  • GPIO 21:  SDA(SDI)

따라서 다음 회로도( BME280이 있는 ESP32에 대한 전체 안내서 읽기 ).

 

 

권장 자료: ESP32 핀아웃 참조 가이드

ESP8266에 BME280 배선

ESP8266 I2C 핀은 다음과 같습니다.

  • GPIO 5  (D1): SCL(SCK)
  • GPIO 4  (D2): SDA(SDI)

ESP8266 보드를 사용하는 경우 다음 회로도와 같이 회로를 조립합니다

( BME280이 포함된 ESP8266에 대한 전체 가이드 읽기 ).

 

 

권장 자료: ESP8266 핀아웃 참조 가이드

ESP32/ESP8266 코드

Arduino IDE를 사용하여 ESP32/ESP8266을 프로그래밍하므로

Arduino IDE에 ESP32/ESP8266 애드온이 설치되어 있어야 합니다. 

사용 중인 보드에 따라 다음 자습서 중 하나를 따르세요.

필요한 보드 애드온을 설치한 후 다음 코드를 Arduino IDE에 복사하되

아직 업로드하지 마십시오. 작동하려면 몇 가지를 변경해야 합니다.

/*
  Rui Santos
  Complete project details at https://RandomNerdTutorials.com/visualize-esp32-esp8266-sensor-readings-from-anywhere/
  
  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files.
  
  The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.

*/

#ifdef ESP32
  #include <WiFi.h>
  #include <HTTPClient.h>
#else
  #include <ESP8266WiFi.h>
  #include <ESP8266HTTPClient.h>
  #include <WiFiClient.h>
#endif

#include <Wire.h>
#include <Adafruit_Sensor.h>
#include <Adafruit_BME280.h>

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

// REPLACE with your Domain name and URL path or IP address with path
const char* serverName = "http://example.com/post-data.php";

// Keep this API Key value to be compatible with the PHP code provided in the project page. 
// If you change the apiKeyValue value, the PHP file /post-data.php also needs to have the same key 
String apiKeyValue = "tPmAT5Ab3j7F9";

/*#include <SPI.h>
#define BME_SCK 18
#define BME_MISO 19
#define BME_MOSI 23
#define BME_CS 5*/

Adafruit_BME280 bme;  // I2C
//Adafruit_BME280 bme(BME_CS);  // hardware SPI
//Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK);  // software SPI

void setup() {
  Serial.begin(115200);
  
  WiFi.begin(ssid, password);
  Serial.println("Connecting");
  while(WiFi.status() != WL_CONNECTED) { 
    delay(500);
    Serial.print(".");
  }
  Serial.println("");
  Serial.print("Connected to WiFi network with IP Address: ");
  Serial.println(WiFi.localIP());

  // (you can also pass in a Wire library object like &Wire2)
  bool status = bme.begin(0x76);
  if (!status) {
    Serial.println("Could not find a valid BME280 sensor, check wiring or change I2C address!");
    while (1);
  }
}

void loop() {
  //Check WiFi connection status
  if(WiFi.status()== WL_CONNECTED){
    WiFiClient client;
    HTTPClient http;
    
    // Your Domain name with URL path or IP address with path
    http.begin(client, serverName);
    
    // Specify content-type header
    http.addHeader("Content-Type", "application/x-www-form-urlencoded");
    
    // Prepare your HTTP POST request data
    String httpRequestData = "api_key=" + apiKeyValue + "&value1=" + String(bme.readTemperature())
                           + "&value2=" + String(bme.readHumidity()) + "&value3=" + String(bme.readPressure()/100.0F) + "";
    Serial.print("httpRequestData: ");
    Serial.println(httpRequestData);
    
    // You can comment the httpRequestData variable above
    // then, use the httpRequestData variable below (for testing purposes without the BME280 sensor)
    //String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";

    // Send HTTP POST request
    int httpResponseCode = http.POST(httpRequestData);
     
    // If you need an HTTP request with a content type: text/plain
    //http.addHeader("Content-Type", "text/plain");
    //int httpResponseCode = http.POST("Hello, World!");
    
    // If you need an HTTP request with a content type: application/json, use the following:
    //http.addHeader("Content-Type", "application/json");
    //int httpResponseCode = http.POST("{\"value1\":\"19\",\"value2\":\"67\",\"value3\":\"78\"}");
    
    if (httpResponseCode>0) {
      Serial.print("HTTP Response code: ");
      Serial.println(httpResponseCode);
    }
    else {
      Serial.print("Error code: ");
      Serial.println(httpResponseCode);
    }
    // Free resources
    http.end();
  }
  else {
    Serial.println("WiFi Disconnected");
  }
  //Send an HTTP POST request every 30 seconds
  delay(30000);  
}

 

네트워크 자격 증명 설정

네트워크 자격 증명으로 다음 줄을 수정해야 합니다.

SSID 및 암호. 코드는 어디를 변경해야 하는지 잘 설명되어 있습니다.

// Replace with your network credentials
const char* ssid     = "REPLACE_WITH_YOUR_SSID";
const char* password = "REPLACE_WITH_YOUR_PASSWORD";

serverName 설정

ESP가 판독값을 자체 서버에 게시할 수 있도록 도메인 이름도 입력해야 합니다.

const char* serverName = "http://example.com/post-data.php";

이제 보드에 코드를 업로드할 수 있습니다. 

ESP32 또는 ESP8266 보드 모두에서 바로 작동해야 합니다. 

코드가 어떻게 작동하는지 알고 싶다면 다음 섹션을 읽어보세요.

 

코드 작동 방식

이 프로젝트는 이미 꽤 길기 때문에

코드가 어떻게 작동하는지 자세히 다루지는 않겠지만 다음은 간단한 요약입니다.

  • 작동하도록 모든 라이브러리 가져오기
     (Arduino IDE에서 선택한 보드를 기반으로 ESP32 또는 ESP8266 라이브러리를 가져옴)
  • 변경하려는 변수를 설정합니다(apiKeyValue)
  • apiKeyValue 수정할 수 있는 임의의 문자열일 뿐입니다. 보안상의 이유로 사용되므로 
        API 키를 아는 사람만 데이터베이스에 데이터를 게시할 수 있습니다.
  • 디버깅 목적으로 직렬 통신 초기화
  • 라우터와 Wi-Fi 연결 설정
  • 판독값을 얻으려면 BME280을 초기화하십시오.

그런 다음, loop() 함수에  실제로 최신 BME280 판독값으로 30초마다 HTTP POST 요청을 하는 곳입니다.

// Your Domain name with URL path or IP address with path
http.begin(serverName);

// Specify content-type header
http.addHeader("Content-Type", "application/x-www-form-urlencoded");

// Prepare your HTTP POST request data
String httpRequestData = "api_key=" + apiKeyValue + "&value1=" 
                       + String(bme.readTemperature()) 
                       + "&value2=" + String(bme.readHumidity()) 
                       + "&value3=" + String(bme.readPressure()/100.0F) + "";

int httpResponseCode = http.POST(httpRequestData);

 

모든 BME280 판독값을 httpRequestData 변수에 연결합니다.

String httpRequestData = "api_key=tPmAT5Ab3j7F9&value1=24.75&value2=49.54&value3=1005.14";

 

데모

모든 단계를 완료한 후 ESP 보드가 일부 판독값을 수집하여 서버에 게시하도록 합니다.

 

 

모든 것이 정확하면 Arduino IDE 직렬 모니터에 다음과 같이 표시됩니다.

 

 

이 URL 경로에서 도메인 이름을 여는 경우:

http://example.com/esp-chart.php

 

데이터베이스에 저장된 모든 판독값이 표시되어야 합니다. 

웹 페이지를 새로고침하여 최신 판독값을 확인하십시오.

phpMyAdmin으로 이동하여 컴퓨터에 저장된 데이터를 관리할 수도 있습니다. 

Sensor 테이블. 삭제, 수정 등을 할 수 있습니다.

마무리

이 자습서에서는 전 세계 어디에서나 액세스할 수 있는

자체 서버 도메인의 데이터베이스에 센서 데이터를 게시하는 방법을 배웠습니다. 

이를 위해서는 자체 서버와 도메인 이름 이 필요합니다

( 로컬 액세스를 위해 Raspberry Pi를 사용할 수도 있음 ).

 

이 설정으로 서버를 제어하고 필요한 경우 다른 호스트로 이동할 수 있습니다. 

판독값을 게시하는 데 사용할 수 있는 무료 및 유료 클라우드 솔루션이 많이 있지만

이러한 서비스에는 게시할 수 있는 판독값 수, 연결된 장치 수, 데이터를 볼 수 있는 사람 등에

대한 제한과 같은 몇 가지 단점이 있습니다.

또한, 클라우드 서비스는 언제든지 할인되거나 변경될 수 있습니다.

 

제공된 예제는 모든 것이 어떻게 작동하는지 이해할 수 있도록 가능한 한 간단합니다. 

이 예를 이해한 후에는 웹 페이지 모양을 변경하고,

다양한 센서 판독값을 게시하고, 여러 ESP 보드에서 게시하는 등의 작업을 수행할 수 있습니다.

 

다음을 읽을 수도 있습니다.

이 프로젝트가 마음에 드셨으면 합니다. 

질문이 있는 경우 아래에 의견을 게시해 주시면 답변을 드리겠습니다.

ESP32가 마음에 들면 " Arduino IDE로 ESP32 배우기 " 과정에 등록하는 것을 고려할 수 있습니다 . 여기에서 무료 ESP32 리소스에 액세스할 수도 있습니다 .

읽어 주셔서 감사합니다.