릴레이 모듈, 브레드보드(빵판)을 사용하여 테스트를 진행했다.

 

릴레이 모듈 ESP32
GND GND
IN1 D19
IN2 D21
IN3 D22
IN4 D23
VCC 3V3

 

#define IN1 19
#define IN2 21
#define IN3 22
#define IN4 23

void setup() {
  pinMode(IN1, OUTPUT);
  pinMode(IN2, OUTPUT);
  pinMode(IN3, OUTPUT);
  pinMode(IN4, OUTPUT);

  digitalWrite(IN1, HIGH);
  digitalWrite(IN2, HIGH);
  digitalWrite(IN3, HIGH);
  digitalWrite(IN4, HIGH);
}

void loop() {
  // LOW : ON / HIGH : OFF
  digitalWrite(IN1, LOW);
  delay(1000);

  digitalWrite(IN2, LOW);
  delay(1000);

  digitalWrite(IN3, LOW);
  delay(1000);

  digitalWrite(IN4, LOW);
  delay(1000);

  digitalWrite(IN1, HIGH);
  delay(1000);

  digitalWrite(IN2, HIGH);
  delay(1000);

  digitalWrite(IN3, HIGH);
  delay(1000);

  digitalWrite(IN4, HIGH);
  delay(1000);
}

 


참고 레퍼런스

ESP32로 만드는 IoT 월드 with 아두이노 IDE 2

온습도 센서 모듈, ESP32 확장 보드, 브레드보드(빵판)을 사용하여 테스트를 진행했다.

 

온습도 센서 모듈 ESP32 확장 보드
GND GND
DATA D18
VCC 3V3

 

 

라이브러리 다운로드

  1. DHT sensor library
  2. Adafruit Unified Sensor

 

#include <DHT.h>

#define DHT_PIN 18
#define DHT_TYPE DHT11

DHT dht(DHT_PIN, DHT_TYPE);

void setup() {
  Serial.begin(115200);
  dht.begin();
}

void loop() {
  delay(2000); // 2초마다 센서 값 읽기

  float temperature = dht.readTemperature(); // 온도
  float humidity = dht.readHumidity(); // 습도

  Serial.print("온도 : ");
  Serial.print(temperature);
  Serial.print("°C ");
  Serial.print("습도 : ");
  Serial.print(humidity);
  Serial.println("%");
}

 

 


참고 레퍼런스

ESP32로 만드는 IoT 월드 with 아두이노 IDE 2

LED 센서 모듈, ESP32 확장 보드, 브레드보드(빵판)을 사용하여 테스트를 진행했다.

 

LED 센서 모듈 ESP32 확장 보드
G D16
R D4
B D2
I GRD

 

#define RED_PIN 4
#define GREEN_PIN 16
#define BLUE_PIN 2

void setup() {
  pinMode(RED_PIN, OUTPUT);
  pinMode(GREEN_PIN, OUTPUT);
  pinMode(BLUE_PIN, OUTPUT);

  digitalWrite(RED_PIN, HIGH);
  digitalWrite(GREEN_PIN, HIGH);
  digitalWrite(BLUE_PIN, HIGH);
}

void loop() {
  // 빨강
  analogWrite(RED_PIN, 0);
  analogWrite(GREEN_PIN, 255);
  analogWrite(BLUE_PIN, 255);
  delay(1000);
  
  // 초록
  analogWrite(RED_PIN, 255);
  analogWrite(GREEN_PIN, 0);
  analogWrite(BLUE_PIN, 255);
  delay(1000);

  // 파랑
  analogWrite(RED_PIN, 255);
  analogWrite(GREEN_PIN, 255);
  analogWrite(BLUE_PIN, 0);
  delay(1000);

  analogWrite(RED_PIN, 255);
  analogWrite(GREEN_PIN, 255);
  analogWrite(BLUE_PIN, 255);
  delay(1000);
}

 

(옆에 껀 온습도 센서인데 해당 포스팅에선 사용 안하므로 무시하면 된다)


참고 레퍼런스

ESP32로 만드는 IoT 월드 with 아두이노 IDE 2

 

 

ESP32 보드에 기본 탑재된 LED를 깜빡이는 예제 프로그램을 실행해본다.

 

1. 예제 파일 로드

파일 - 예제 - 01.Basics - Blink를 클릭하여 예제 파일을 로드한다.

 

void setup() {
  pinMode(LED_BUILTIN, OUTPUT);
}

void loop() {
  digitalWrite(LED_BUILTIN, HIGH);
  delay(1000);
  digitalWrite(LED_BUILTIN, LOW);
  delay(1000);
}

2. 예제 파일 컴파일 및 업로드

상단 툴바에서 업로드 버튼을 눌러 코드를 업로드한다.

3. 결과 확인

 

 

 

 

 

P.S

계속 라즈베리파이 물고 하니까 왔다갔다 하기가 번거로워서 테스트 할 때 동안은 Windows Arduino IDE를 통해 테스트를 진행한다.


참고 레퍼런스

ESP32로 만드는 IoT 월드 with 아두이노 IDE 2

  1. Arduino IDE 다운로드
    1. https://www.arduino.cc/en/software/
  2. 추가 보드자 추가
    1. 파일 - 기본 설정 - 추가 보드 관리자 URL
    2. https://raw.githubusercontent.com/espressif/arduino-esp32/gh-pages/package_esp32_index.json
  3. 보드 매니저 설치
    1. 도구 - 보드 - 보드 매니저 - ‘esp32’ 검색 - ‘esp32’ 다운로드
  4. 보드 선택
    1. 상단 디버깅 아이콘 옆 모듈 Select Box 클릭 - 보드 및 포트 선택 클릭
    2. ‘doit’ 검색
    3. ‘DOIT ESP32 DEVKIT V1’ 선택
    4. USB 포트 선택(’COM6 Serial Port (USB)’)
    5. 확인 클릭
  5. 시리얼 드라이버 설치
    1. 보드 선택 시 포트가 안잡히면 아래 경로로 드라이버를 설치한다.
    2. https://www.silabs.com/developers/usb-to-uart-bridge-vcp-drivers?tab=download
    3. DOWNLOADS - ‘CP210x Universal Windows Driver’
    4. 장치 관리자 - 포트(COM & LPT) - USB-SERIAL CH340(COM6) - 드라이버 업데이트 - 내 컴퓨터에서 드라이버 찾아보기(R)
    5. 설치한 드라이버 압축을 풀고 해당 폴더를 선택하여 설치한다.
    6. 설치된 것을 확인한다.

1. ino

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include "include/wifi.h"
#include "include/mqtt.h"

WiFiUDP      ntpUDP;

unsigned long lastTime             = 0;
const long interval                = 5000;
const char* relayOnTopic           = "/relay/on";
const char* relayOffTopic          = "/relay/off";
int relayPin                       = 26;

void setup() {
    Serial.begin(115200);

    setupWifi();
    setupMqtt();

    client.setServer(MQTT_SERVER, 1883);
    client.setCallback(callback);

    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("ESP32 연결 성공");

            client.subscribe(relayOnTopic);
            client.subscribe(relayOffTopic);

            Serial.println("mqtt 토픽 발행 성공");
        } else {
            Serial.println("ESP32 연결 실패");
            Serial.println("mqtt 토픽 발행 실패");

            delay(2000);
        }
    }

    timeClient.begin();

    pinMode(relayPin, OUTPUT);
    digitalWrite(relayPin, HIGH);
}

void callback(char* topic, byte* payload, unsigned int length) {
    String message = "";

    Serial.print("topic = ");
    Serial.println(topic);

    for (unsigned int i = 0; i < length; i++) {
        message += (char)payload[i];
    }

    Serial.print("message = ");
    Serial.println(message);

     if(strcmp(topic, relayOnTopic) == 0) {
         digitalWrite(relayPin, LOW);
     } else if(strcmp(topic, relayOffTopic) == 0) {
         digitalWrite(relayPin, HIGH);
     }
}

void loop() {
    // ... 관련없는 코드이므로 생략
}

void reconnectSetup() {
    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("mqtt 연결 성공");
        } else {
            Serial.println("mqtt 연결 실패 & 5초 후 재시도");

            delay(5000);
        }
    }
}

2. HTML

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/layout-admin}" layout:fragment="body">
<body>
    <section>
        <div id="control-wrap" style="display: block">
            <p class=l>Relay Module OFF</p>
                <div class="round">
                <input type=checkbox id="relay-module" name="relay-module" />
                <div class="back">
                    <label class=but for="relay-module">
                        <span class="on">I</span>
                        <span class="off">0</span>
                    </label>
                </div>
            </div>
            <p class=r>Relay Module ON</p>
        </div>
    </section>
</body>

<script src="https://cdn.jsdelivr.net/npm/mqtt@4.3.7/dist/mqtt.min.js"></script>
<script th:src="@{/js/admin_relay_test.js}"></script>
</html>

3. Javascript

let client;
const brokerUrl     = '';
const relayOnTopic  = '/relay/on';
const relayOffTopic = '/relay/off';

$(document).ready(() => {
    client = mqtt.connect(brokerUrl);

    client.on('connect', () => {
        console.log('mqtt 연결 성공');
    });

    $('#relay-module').change(function() {
        if($(this).is(':checked')) {
            client.publish(relayOnTopic, 'ON');
        } else {
            client.publish(relayOffTopic, 'OFF');
        }
    });
});

 

 

 

버튼 클릭할 때 마다 모니터링 화면에 토픽이랑 메세지가 표출되고 해당 토픽에 따라 릴레이 모듈을 제어한다.

 

참고로 스위치 CSS는 여기서 가져왔다.

 

 

Toggle switch with checkbox:checked

Round switch button in css with animation cleaned up. Inspired on the design of Paul Flavius, see: http://psd.tutsplus.com/tutorials/interface-tutoria...

codepen.io

  • 준비물
    • 점퍼 케이블
    • ESP32 보드
    • 4채널 릴레이 모듈

 

릴레이 모듈 ESP32 설명
VCC 3.3V 전원 공급
GND GND 접지 연결
IN1 GPON26(혹은 D6) 릴레이 1 제어

 

 

위에 꺼 참고해서 점퍼 케이블로 갖다 꽂으면 된다.

 

맞물리는 소리나면 연결 된거다.

 

이제 ino 파일 작성해서 릴레이 모듈 연결이 됐는지 테스트해보자.

 

int relayPin = 26;

void setup() {
    pinMode(relayPin, OUTPUT);
}

void loop() {
    digitalWrite(relayPin, LOW);
    delay(2000);
    digitalWrite(relayPin, HIGH);
    delay(2000);
}

 

# ino 컴파일
$ arduino-cli compile --fqbn esp32:esp32:esp32 {ino 파일명}

# ino 업로드
$ arduino-cli upload -p /dev/ttyUSB0 --fqbn esp32:esp32:esp32 {ino 파일명}

 

이제 2초마다 루프 돌면서 릴레이 모듈 전원을 켰다 껐다한다.

 

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <NTPClient.h>
#include "include/wifi.h"
#include "include/mqtt.h"
#include "include/led.h"

WiFiUDP      ntpUDP;
NTPClient    timeClient(ntpUDP, "pool.ntp.org", 32400, 60000);

unsigned long lastTime             = 0;
const long interval                = 5000;
bool ledState                      = false;
const char* currentTopic           = nullptr;
const char* mqttTestTopic          = "/mqtt/mqtt_test";
const char* defaultSensorTestTopic = "/mqtt/default_sensor_test";

void setup() {
    Serial.begin(115200);

    setupWifi();
    setupMqtt();

    client.setServer(MQTT_SERVER, 1883);
    client.setCallback(mqttCallback);

    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("ESP32 연결 성공");

            client.subscribe(mqttTestTopic);
            client.subscribe(defaultSensorTestTopic);

            Serial.println("mqtt 토픽 발행 성공");
        } else {
            Serial.println("ESP32 연결 실패");
            Serial.println("mqtt 토픽 발행 실패");

            delay(2000);
        }
    }

    timeClient.begin();
}

void mqttCallback(char* topic, byte* payload, unsigned int length) {
    String message = "";

    for (unsigned int i = 0; i < length; i++) {
        message += (char)payload[i];
    }
}

void loop() {
    if(!client.connected()) {
        Serial.println("mqtt 연결 실패 & 재연결 시도");

        reconnectSetup();
    }

    unsigned long currentMillis = millis();

    if(currentMillis - lastTime >= interval) {
        lastTime = currentMillis;

        // => mqtt connect test
        timeClient.update();

        String formattedTime   = timeClient.getFormattedTime();
        time_t rawTime         = timeClient.getEpochTime();
        String responseMessage = "mqtt 통신 성공";

        StaticJsonDocument<128> doc;

        doc["message"]   = responseMessage;
        doc["timestamp"] = formattedTime.c_str(); // HH:MM:SS
        doc["epoch"]     = rawTime;               // UNIX timestamp

        char buffer[128];
        serializeJson(doc, buffer);

        client.publish(mqttTestTopic, buffer);

        // => default sensor test
        // 1. CPU 클럭 속도
        int voltage = getCpuFrequencyMhz();

        // 2. WiFi 신호 강도
        long rssi = WiFi.RSSI();

        // 3. RAM 메모리
        int heapMemory = esp_get_free_heap_size();

        StaticJsonDocument<128> doc2;

        doc2["voltage"]      = voltage;
        doc2["rssi"]         = rssi;
        doc2["timestamp"]    = formattedTime.c_str();
        doc2["heapMemory"]   = heapMemory;

        char buffer2[128];
        serializeJson(doc2, buffer2);

        client.publish(defaultSensorTestTopic, buffer2);
    }

    client.loop();
}

void reconnectSetup() {
    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            Serial.println("mqtt 연결 성공");
        } else {
            Serial.println("mqtt 연결 실패 & 5초 후 재시도");

            delay(5000);
        }
    }
}

 

① WiFi 연결

② mqtt 연결

③ mqtt topic 발행

④ mqtt topic 구독 시 루프 돌면서 5초마다 센서 값 보내기

 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/layout-admin}" layout:fragment="body">
<style>
    th:first-child {width: 30%;}
    th:nth-child(2), td:nth-child(2) {width: 30%;}
    th:nth-child(3), td:nth-child(3) {width: 30%;}
</style>
<body>
    <section>
        <div id="home-wrap">
            <!-- 현재 시간 표출 -->
            <p id="menu-name">기본 센서 테스트</p>
        </div>

        <div class="data-result-info-box">
            <span>마지막 업데이트 시간 : </span>
            <span id="response-time"></span>

            <p></p>

            <span>응답 메세지 값 : </span>
            <span id="response-data"></span>
        </div>

        <div class="data-box-wrap">
            <div class="data-box">
                <p class="data-box-title">CPU 클럭 속도</p>
                <p id="voltage">0</p>
            </div>
            <div class="data-box">
                <p class="data-box-title">RAM 메모리</p>
                <p id="heap-memory">0</p>
            </div>
            <div class="data-box">
                <p class="data-box-title">WiFi 강도</p>
                <p id="rssi">0</p>
            </div>
        </div>        
    </section>
</body>

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script th:src="@{/js/admin_default_sensor_test.js}"></script>
</html>

 

HTML 특정 요소에 mqtt 구독 후 받은 메세지를 표출해야하기 때문에 id로 지정해서 작업을 진행했다.

script는 mqtt 라이브러리 및 아래 js 코드를 import 하는 부분이다.

 

$(document).ready(() => {
    const topic   = '/mqtt/default_sensor_test';
    const client  = mqtt.connect('ws://ljy.myddns.me:8081');
    const message = 'MESSAGE';

    client.on('connect', () => {
        console.log('mqtt 연결 성공');

        client.subscribe(topic, (e) => {
            if(e) {
                console.log(`mqtt 토픽 발행 실패 = ${e}`);
            } else {
                console.log(`mqtt 토픽 발행 성공 = ${topic}`);
            }
        });
    });

    client.publish(topic, message);

    client.on('message', (topic, message) => {
        const json           = JSON.parse(message);
        const responseData   = message;
        const timestamp      = json.timestamp;
        const voltage        = json.voltage;
        const battery        = json.battery;
        const rssi           = json.rssi;
        const heapMemory     = json.heapMemory;
        const responseTimeEl = $('#response-time');
        const responseDataEl = $('#response-data');
        const voltageEl      = $('#voltage');
        const batteryEl      = $('#battery');
        const rssiEl         = $('#rssi');
        const heapMemoryEl   = $('#heap-memory');

        responseTimeEl.text(timestamp);
        responseDataEl.text(responseData);
        voltageEl.text(voltage);
        batteryEl.text(battery);
        rssiEl.text(rssi);
        heapMemoryEl.text(heapMemory);
    });
});

 

작업 전에 필요한 라이브러리를 다운로드 받는다.

 

테스트 용으로 여러 데이터를 담아 보내기 위해 JSON 라이브러리, 현재 시간을 받을 수 있는 NTPClient를 다운로드 받았다.

 

$ arduino-cli lib install "ArduinoJson"

$ arduino-cli lib install "NTPClient"

 

#include <WiFi.h>
#include <PubSubClient.h>
#include <ArduinoJson.h>
#include <NTPClient.h>

const char* ssid       = "WIFI";
const char* pwd        = "PASSWORD";
const char* mqttServer = "MQTT INSTALL SERVER";

WiFiClient   esbClient;
PubSubClient client(esbClient);
WiFiUDP      ntpUDP;
NTPClient    timeClient(ntpUDP, "pool.ntp.org", 32400, 60000);

void setup() {
    Serial.begin(115200);

    WiFi.begin(ssid, pwd);

    while(WiFi.status() != WL_CONNECTED) {
        delay(500);
    }

    client.setServer(mqttServer, 1883);

    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            client.subscribe("/mqtt/mqtt_test");
        } else {
            delay(2000);
        }
    }

    timeClient.begin();
}

void loop() {
    timeClient.update();
    String formattedTime = timeClient.getFormattedTime();
    time_t rawTime       = timeClient.getEpochTime();
    String message       = "MQTT CONNECTION SUCCESS!";

    StaticJsonDocument<128> doc;

    doc["message"]   = message;
    doc["timestamp"] = formattedTime.c_str(); // HH:MM:SS
    doc["epoch"]     = rawTime;               // UNIX timestamp

    char buffer[128];
    serializeJson(doc, buffer);

    client.publish("/mqtt/mqtt_test", buffer);
    client.loop();

    delay(5000);
}

 

# 컴파일
$ arduino-cli compile --fqbn esp32:esp32:esp32 {파일명}

# 업로드
$ arduino-cli upload --fqbn esp32:esp32:esp32 --port /dev/ttyUSB0 {파일명}

 

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/layout-admin}" layout:fragment="body">
<body>
    <section>
        <div id="home-wrap">
            <!-- 현재 시간 표출 -->
            <p id="menu-name">MQTT 테스트</p>
        </div>

        <div class="table-wrap">
            <table>
                <thead>
                    <tr style="cursor: default">
                        <th>메세지 내용</th>
                        <th>수신 시간</th>
                        <th>UNIX 시간</th>
                    </tr>
                </thead>
                <tbody>
                </tbody>
            </table>
        </div>
    </section>
</body>

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script th:src="@{/js/admin_mqtt_test.js}"></script>
</html>

 

    client.on('message', (topic, message) => {
        // console.log(`MQTT CONNECTION SUCCESS..`);
        // console.log(`⇒ ${message}`);

        const json          = JSON.parse(message);
        const jsonMessage   = json.message;
        const jsonTimestamp = json.timestamp;
        const jsonEpoch     = json.epoch;

        const el = `<tr>
                        <td>${jsonMessage}</td>
                        <td>${jsonTimestamp}</td>
                        <td>${jsonEpoch}</td>
                    </tr>`;

        $('table tbody').append(el);    
    });

 

 

데이터 겁나 잘쌓인다.

0. 라이브러리 설치

$ arduino-cli lib install "WiFi"
Downloading WiFi@1.2.7...
WiFi@1.2.7 downloaded
Installing WiFi@1.2.7...
Installed WiFi@1.2.7

$ arduino-cli lib install "PubSubClient"
Downloading PubSubClient@2.8.0...
PubSubClient@2.8.0 downloaded
Installing PubSubClient@2.8.0...
Installed PubSubClient@2.8.0

1. mqtt_test.ino 작성

#include <WiFi.h>
#include <PubSubClient.h>

const char* ssid       = "WIFI";
const char* pwd        = "PASSWORD";
const char* mqttServer = "MQTT INSTALL SERVER";

WiFiClient   esbClient;
PubSubClient client(esbClient);

void setup() {
    Serial.begin(115200);

    WiFi.begin(ssid, pwd);

    while(WiFi.status() != WL_CONNECTED) {
        delay(500);
    }

    client.setServer(mqttServer, 1883);

    while(!client.connected()) {
        if(client.connect("ESP32Client")) {
            client.subscribe("/mqtt/mqtt_test");
        } else {
            delay(2000);
        }
    }
}

void loop() {
    String message = "HELLO WORLD!";

    client.publish("/mqtt/mqtt_test", message.c_str());
    client.loop();

    delay(5000);
}

2. mqtt_test.ino 컴파일 및 업로드

이전에 테스트용으로 ‘/arduino/test/’ 경로에 ino 파일을 하나 뒀었는데 공부하다보니 ino 파일 자체가 아두이노 하나에 하나 씩만 존재하는거라 디렉토리 정리하면서 ‘/arduino/’ 경로에 ino 파일을 두었다.

 

root@WAS-1:/arduino# tree
.
└── arduino.ino

1 directory, 1 file

 

[참고] ino 파일은 상위 디렉토리명과 같아야 한다.

 

# 컴파일
$ arduino-cli compile --fqbn esp32:esp32:esp32 {파일명}

# 업로드
$ arduino-cli upload --fqbn esp32:esp32:esp32 --port /dev/ttyUSB0 {파일명}

3. HTML/Javascript 코드 작성

<!DOCTYPE html>
<html lang="en" xmlns:th="http://www.thymeleaf.org" xmlns:layout="http://www.ultraq.net.nz/thymeleaf/layout" layout:decorate="~{fragments/layout-admin}" layout:fragment="body">
<body>
    <section>
        <div id="home-wrap">
            <!-- 현재 시간 표출 -->
            <p id="time"></p>
        </div>

        <div id="control-wrap">
            <button id="tqtt_test" onclick="mqttTestControl()">MQTT TEST</button>
            <button id="bluetooth-speaker" onclick="bluetoothSpeakerControl()">BLUETOOTH SPEAKER</button>
            <button id="lighting" onclick="lightingControl()">LIGHTING</button>
        </div>
    </section>
</body>

<script src="https://unpkg.com/mqtt/dist/mqtt.min.js"></script>
<script th:src="@{/js/mqtt.js}"></script>
</html>

 

function mqttTestControl() {
    const brokerUrl = 'ws://192.168.0.48:8081';
    const topic     = '/mqtt/mqtt_test';
    const client    = mqtt.connect(brokerUrl);

    client.on('connect', () => {
        console.log(`TOPIC CONNECT SUCCESS..`);

        client.subscribe(topic, (e) => {
            if(e) {
                console.log(`TOPIC SUBSCRIPTION FAIL..`);
                console.log(`⇒ ${e}`);
            } else {
                console.log(`TOPIC SUBSCRIPTION SUCCESS..`);
                console.log(`⇒ ${topic}`);
            }
        });
    });

    client.on('message', (topic, message) => {
        console.log(`MQTT CONNECTION SUCCESS..`);
        console.log(`⇒ ${message}`);
    });
}

 

 

  1. WIFI, WIFI PASSWORD 잘 적자..
  2. ino 파일 작성 ⇒ compile ⇒ upload ⇒ 코드 파일 적용 완료!
  3. 아두이노 보드 하나에 ino 파일은 하나 씩 존재한다.(Spring Boot 치면 ProjectApplication.java)

 

P.S 졌잘싸..

+ Recent posts