week__12 (ArduinoCloud&NTP) - JINEEH/SmartDevice_JinHee GitHub Wiki

ArduinoCloud와 NTP ν™œμš© μ‹€μŠ΅

1. ν•™μŠ΅ λͺ©ν‘œ

1-1. ArduinoCloudλ₯Ό ν™œμš©ν•œ μ˜¨μŠ΅λ„&LED μ„Όμ„œ μ‹€μŠ΅ 및 NTP μ„œλ²„λ‘œ μ‹œκ°„ 정보 확인

2. ArduinoCloud

2-1. Arduinoμ—μ„œ μ œκ³΅ν•˜λŠ” IoT ν΄λΌμš°λ“œλ‘œ μ˜¨μŠ΅λ„ 데이터λ₯Ό μ‹€μ‹œκ°„ λͺ¨λ‚˜ν„°λ§κ³Ό μ™ΈλΆ€ LED μ œμ–΄ν•˜λŠ” μ‹€μŠ΅μ—μ„œ μ‚¬μš©
2-2. μ‹€μŠ΅ μ€€λΉ„λ¬Ό: ESP32, ESP32 ν™•μž₯ μ‹€λ“œ, DH11 μ˜¨μŠ΅λ„ μ„Όμ„œ, LED λͺ¨λ“ˆ, 점퍼 케이블
2-3. ArduinoCloud μ„€μ • 및 μ‹€ν–‰μ½”λ“œ
  • Arduino νšŒμ›κ°€μž… 및 ArduinoCloud 이동

12μ£Όμ°¨ 8-1(1)

  • Things -> CREATE THING

12μ£Όμ°¨ 8-1(2)

  • ν”„λ‘œμ νŠΈ 이름 λ³€κ²½(ESP32)
  • led_state와 temperature μΆ”κ°€ν•˜κΈ°(ADD)
  • λ””λ°”μ΄μŠ€μ™€ λ„€νŠΈμ›Œν¬ μ„€μ •
  • Secret Key copy ν›„ λ„€νŠΈμ›Œν¬ μ—°κ²° 섀정에 μž…λ ₯
  • Sketch νƒ­μ—μ„œ ".ino" νŒŒμΌμ— μ‹€ν–‰μ½”λ“œ μ—…λ‘œλ“œ ν›„ Dashboard에 μ•‘μ„ΈμŠ€ν•˜κΈ°

12μ£Όμ°¨ 8-1(μΆ”κ°€)

  • μ™ΈλΆ€ LED 쑰절 κ°€λŠ₯ν•œ Switch μΆ”κ°€ν•˜κΈ°

12μ£Όμ°¨ 8-1(12) 12μ£Όμ°¨ 8-1(13)

  • μ˜¨μŠ΅λ„ μ„Όμ„œμ˜ 데이터λ₯Ό κ·Έλž˜ν”„λ‘œ λ‚˜νƒ€λ‚΄λŠ” Chart μΆ”κ°€ν•˜κΈ°

12μ£Όμ°¨ 8-1(14) 12μ£Όμ°¨ 8-1(15

  • μ‹€ν–‰ μ½”λ“œ(8-1)
#include "thingProperties.h"
#include "DHT.h"

int led_pin = 23;
int dh11_pin = 13;

DHT dht(dh11_pin, DHT11);

void setup() {
  pinMode(led_pin, OUTPUT);
  dht.begin();
  // Initialize serial and wait for port to open:
  Serial.begin(9600);
  // This delay gives the chance to wait for a Serial Monitor without blocking if none is found
  delay(1500);

  // Defined in thingProperties.h
  initProperties();

  // Connect to Arduino IoT Cloud
  ArduinoCloud.begin(ArduinoIoTPreferredConnection);

  setDebugMessageLevel(2);
  ArduinoCloud.printDebugInfo();
}

void loop() {
  ArduinoCloud.update();
  // Your code here
  // Read temperature as Celsius (the default)
  temperature = dht.readTemperature();

  // Check if any reads failed and exit early (to try again).
  if (isnan(temperature)) {
    Serial.println(F("Failed to read from DHT sensor!"));
    return;
  }

  Serial.print(F("Temperature: "));
  Serial.println(temperature);

  delay(1000);
}

void onLedStateChange() {
  // Add your code here to act upon LedState change
  Serial.print("LED state is changed : ");
  Serial.println(led_state);
  if (led_state) {
    digitalWrite(led_pin, HIGH);
  } else {
    digitalWrite(led_pin, LOW);
  }
}
  • μ‹€μŠ¬ κ²°κ³Ό
  • μ™ΈλΆ€ LED ON/OFF μ œμ–΄μ™€ μ˜¨μŠ΅λ„ μ œμ–΄ Chart 확인
12.8-1.2.mp4

3. NTP

3-1. 의미: λ„€νŠΈμ›Œν¬λ₯Ό 톡해 컴퓨터 μ‹œμŠ€ν…œ κ°„μ˜ μ‹œκ°„μ„ λ™κΈ°ν™”ν•˜λŠ” ν”„λ‘œν† μ½œλ‘œ 인터넷과 둜컬 λ„€νŠΈμ›Œν¬μ—μ„œ μ‚¬μš©
     - μ„œλ²„μ™€ ν΄λΌμ΄μ–ΈνŠΈ κ°„μ˜ μ‹œκ°„ 정보λ₯Ό μ£Όκ³  λ°›μ•„ μ‹œκ°„μ„ λ™κΈ°ν™”μ‹œν‚΄
     - μ •λ°€ν•œ μ›μž μ‹œκ³„ λ˜λŠ” GPSλ₯Ό 톡해 μ •ν™•ν•œ μ‹œκ°„μ„ μœ μ§€ν•¨
     - ν΄λΌμ΄μ–ΈνŠΈλŠ” 주기적으둜 NTP μ„œλ²„μ— μ ‘μ†ν•˜μ—¬ μ‹œκ°„ 정보λ₯Ό 갱신함
3-2. NTP 계측 ꡬ쑰
     - Stratum 0: μ›μž μ‹œκ³„, GPS λ“± μ ˆλŒ€ μ‹œκ°„μ„ μ œκ³΅ν•˜λŠ” μž₯치
     - Stratum 1: Stratum 0 μž₯μΉ˜μ™€ 직접 μ—°κ²°λœ NTP μ„œλ²„
     - Stratum 2: Stratum 1 μ„œλ²„μ™€ λ™κΈ°ν™”λœ μ„œλ²„λ“€
     - Stratum 2~15: NTP μ„œλ²„λ₯Ό κ²½μœ ν•  λ•Œ λ§ˆλ‹€ Stratum 1μ”© μ¦κ°€ν•˜λ©° Stratum 2λΆ€ν„°λŠ” 계측적 트리 ꡬ쑰λ₯Ό ν˜•μ„±ν•¨
  • 1이 μ΅œμƒμœ„ μ„œλ²„μ΄λ©° NTP μ„œλ²„λ“€μ΄ μ—°κ²°λ μˆ˜λ‘ μˆ«μžκ°€ 증가함
3-3. NTP μ„œλ²„μ—μ„œ μ‹œκ°„μ„ 가져와 OLED λ””μŠ€ν”Œλ ˆμ΄μ— ν‘œμ‹œν•˜λŠ” μ‹€μŠ΅
     - μ‹€μŠ΅ μ€€λΉ„λ¬Ό: ESP32, ESP32 ν™•μž₯ μ‹€λ“œ, OLED λ””μŠ€ν”Œλ ˆμ΄, 점퍼 케이블
     - Adafruit SSD1306 라이브러리 μ„€μΉ˜(Adafruit GFX 라이브러리 ν¬ν•¨ν•˜μ—¬ 전체 μ„€μΉ˜)
  • ESP32 회둜 μ—°κ²°
  • μ‹€ν–‰ μ½”λ“œ(9-1)
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>

#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 32

Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);

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

    // OLED λ””μŠ€ν”Œλ ˆμ΄ μ΄ˆκΈ°ν™”
    if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
        Serial.println("SSD1306 였λ₯˜");
        while (true);
    }

    // OLED λ””μŠ€ν”Œλ ˆμ΄ 클리어
    display.clearDisplay();
}

void loop() {
    // "Hello, World!"λ₯Ό 크기가 λ‹€λ₯Έ 두 개의 ν…μŠ€νŠΈλ‘œ ν‘œμ‹œ
    display.clearDisplay();
    
    // 크기 6의 폰트둜 ν…μŠ€νŠΈ ν‘œμ‹œ
    display.setTextSize(1);
    display.setTextColor(WHITE);
    display.setCursor(0, 0);
    display.println("Hello, World!");

    // 크기 8의 폰트둜 ν…μŠ€νŠΈ ν‘œμ‹œ
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(0, 15);
    display.println("Hello, World");

    display.display();
    delay(2000);
}
  • μ‹€μŠ΅ κ²°κ³Ό
  • display.println(" "); 에 λ³€ν™”λ₯Ό μ€€ λ‹€λ₯Έ κ²°κ³Ό
  • μ‹œκ°„ λ™κΈ°ν™”ν•˜μ—¬ λ””μ§€ν„Έ μ‹œκ³„ κ΅¬ν˜„(λ„€νŠΈμ›Œν¬ μ„€μ • ν•„μš”)
  • μ‹€ν–‰ μ½”λ“œ(9-2)
#include <WiFi.h>  // WiFi 톡신을 μœ„ν•œ 라이브러리
#include <time.h>  // μ‹œκ°„κ³Ό κ΄€λ ¨λœ ν•¨μˆ˜λ₯Ό μœ„ν•œ 라이브러리

#include <Adafruit_GFX.h>      // λ””μŠ€ν”Œλ ˆμ΄λ₯Ό μœ„ν•œ κ·Έλž˜ν”½ 라이브러리
#include <Adafruit_SSD1306.h>  // SSD1306 OLED λ””μŠ€ν”Œλ ˆμ΄λ₯Ό μœ„ν•œ 라이브러리
// SSD1306 λ””μŠ€ν”Œλ ˆμ΄ 객체 μ΄ˆκΈ°ν™”
Adafruit_SSD1306 display = Adafruit_SSD1306(128, 32, &Wire, -1);

const char* ssid = "zineeh";          // 여기에 μ‚¬μš©ν•˜λŠ” WiFi λ„€νŠΈμ›Œν¬ 이름 (SSID)을 μž…λ ₯ν•˜μ„Έμš”
const char* password = "SMARTDEVICE0527";  // 여기에 μ‚¬μš©ν•˜λŠ” WiFi λ„€νŠΈμ›Œν¬ λΉ„λ°€λ²ˆν˜Έλ₯Ό μž…λ ₯ν•˜μ„Έμš”

int GMTOffset = 60 * 60 * 9;  // μ‹œκ°„ μ˜€ν”„μ…‹ μ„€μ •, ν•œκ΅­μ€ UTC/GMT +9μž…λ‹ˆλ‹€.
int daylightOffset = 0;       // κ΅­κ°€μ—μ„œ μ„œλ¨Ένƒ€μž„μ„ μ‚¬μš©ν•˜λŠ” 경우 μ˜€ν”„μ…‹ 값을 μ„€μ •ν•˜μ„Έμš”.

const String weekDays[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };  // μš”μΌ 이름 λ°°μ—΄

void setup() {
  Serial.begin(115200);  // 디버깅을 μœ„ν•œ μ‹œλ¦¬μ–Ό 톡신 μ‹œμž‘

  // SSD1306 λ””μŠ€ν”Œλ ˆμ΄ μ΄ˆκΈ°ν™”
  if (!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
    Serial.println(F("SSD1306 μ΄ˆκΈ°ν™” μ‹€νŒ¨"));
    while (1)
      ;  // λ””μŠ€ν”Œλ ˆμ΄ μ΄ˆκΈ°ν™”μ— μ‹€νŒ¨ν•˜λ©΄ ν”„λ‘œκ·Έλž¨ μ‹€ν–‰ 쀑지
  }

  delay(2000);                  // 2초 λ™μ•ˆ λŒ€κΈ°
  display.clearDisplay();       // λ””μŠ€ν”Œλ ˆμ΄ μ§€μš°κΈ°
  display.setTextSize(1);       // ν…μŠ€νŠΈ 크기λ₯Ό 1둜 μ„€μ •
  display.setCursor(0, 0);      // μ»€μ„œ μœ„μΉ˜λ₯Ό λ””μŠ€ν”Œλ ˆμ΄ μ™Όμͺ½ μœ„ λͺ¨μ„œλ¦¬λ‘œ μ„€μ •
  display.setTextColor(WHITE);  // ν…μŠ€νŠΈ 색상을 ν°μƒ‰μœΌλ‘œ μ„€μ •

  WiFi.begin(ssid, password);  // 제곡된 SSID와 λΉ„λ°€λ²ˆν˜Έλ₯Ό μ‚¬μš©ν•˜μ—¬ WiFi λ„€νŠΈμ›Œν¬μ— μ—°κ²°
  while (WiFi.status() != WL_CONNECTED) {
    delay(1000);
    Serial.println("Connecting...");
  }

  Serial.println("Connected to Wi-Fi!");
  // μ‹œκ°„ 섀정을 μœ„ν•œ NTP μ„œλ²„ μ„€μ •
  configTime(GMTOffset, daylightOffset, "pool.ntp.org", "time.nist.gov");
}


void loop() {

  // ν˜„μž¬ μ‹œκ°„ κ°€μ Έμ˜€κΈ°
  time_t rawtime = time(nullptr);
  struct tm* timeinfo = localtime(&rawtime);

  // μ‹œλ¦¬μ–Ό λͺ¨λ‹ˆν„°μ— λ‚ μ§œ 좜λ ₯
  Serial.print(timeinfo->tm_mday);
  Serial.print("/");
  Serial.print(timeinfo->tm_mon + 1);
  Serial.print("/");
  Serial.print(timeinfo->tm_year + 1900);

  Serial.print(" ");

  // μ‹œλ¦¬μ–Ό λͺ¨λ‹ˆν„°μ— μ‹œκ°„ 좜λ ₯
  Serial.print("Time: ");
  Serial.print(timeinfo->tm_hour);
  Serial.print(":");
  Serial.print(timeinfo->tm_min);
  Serial.print(":");
  Serial.println(timeinfo->tm_sec);

  // OLED λ””μŠ€ν”Œλ ˆμ΄ μ΄ˆκΈ°ν™”
  display.clearDisplay();
  display.setTextSize(3);
  display.setTextColor(WHITE);
  display.setCursor(0, 0);

  // μ‹œκ°„ 좜λ ₯
  if (timeinfo->tm_hour < 10)
    display.print("0");
  display.print(timeinfo->tm_hour);

  display.print(":");

  if (timeinfo->tm_min < 10)
    display.print("0");
  display.print(timeinfo->tm_min);

  display.print(":");

  // 초 좜λ ₯
  display.setTextSize(2);
  display.setCursor(102, 5);

  if (timeinfo->tm_sec < 10)
    display.print("0");
  display.print(timeinfo->tm_sec);

  // λ‚ μ§œ 좜λ ₯
  display.setTextSize(1);
  display.setCursor(0, 25);
  display.print(timeinfo->tm_mday);
  display.print("/");
  display.print(timeinfo->tm_mon + 1);
  display.print("/");
  display.print(timeinfo->tm_year + 1900);

  display.print(" ");
  display.print(weekDays[timeinfo->tm_wday]);

  // λ””μŠ€ν”Œλ ˆμ΄μ— ν‘œμ‹œ
  display.display();

  delay(1000);
}
  • μ‹€μŠ΅ κ²°κ³Ό
12.9-2.mp4

4. IΒ²C

4-1. μ§λ ¬λ²„μŠ€μ΄λ©° λ§ˆλ”λ³΄λ“œ, μž„λ² λ””λ“œ μ‹œμŠ€ν…œ, νœ΄λŒ€ μ „ν™” 등에 저속 κΈ°κΈ°λ₯Ό μ—°κ²°ν•  λ•Œ μ‚¬μš©λ¨
     - ν’€μ—… 저항이 μ—°κ²°λœ 직렬 데이터와 직렬 ν΄λŸ­μ΄λΌλŠ” λ‘κ°œμ˜ μ–‘λ°©ν–₯ μ˜€ν”ˆ 컬렉터 라인 μ‚¬μš©
     - μ΅œλŒ€ 전압은 +5Vμ΄μ§€λ§Œ 일반적으둜 +3.3V μ‹œμŠ€ν…œ μ‚¬μš©
     - IΒ²C 레퍼런슀 λ””μžμΈμ€ 7λΉ„νŠΈμ˜ μ£Όμ†Œ 곡간을 κ°€μ§€λ©° λ™μΌν•œ λ²„μŠ€μ— μ΅œλŒ€ 112개의 λ…Έλ“œκ°€ μ—°κ²° κ°€λŠ₯함
     - λΉ λ₯Έ 속도λ₯Ό ν•„μš”λ‘œ ν•˜μ§€ μ•ŠλŠ” κ°„λ‹¨ν•œ μ €λΉ„μš© μž₯μΉ˜μ— 적합
     - νœ΄λŒ€μ „ν™” 같은 μž₯μΉ˜μ— ν¬ν•¨λœ λ°œκ΄‘ λ‹€μ΄μ˜€λ“œλ₯Ό μ œμ–΄ν•˜λŠ” 경우, ν•˜λ“œμ›¨μ–΄ λͺ¨λ‹ˆν„°λ§κ³Ό 진단 μ„Όμ„œ 정보λ₯Ό μ½λŠ” 경우, μ‹€μ‹œκ°„ ν΄λŸ­μ„ μ½λŠ” 경우, μ‹œμŠ€ν…œ μš”μ†Œμ˜ 전원을 μ œμ–΄ν•˜λŠ” 경우
4-2. μž₯점
     - SDA와 SCL 두가λ‹₯의 μ„ λ§ŒμœΌλ‘œ 데이터 μ†‘μˆ˜μ‹ μ΄ κ°€λŠ₯함
     - 동기식 ν†΅μ‹ μ΄λ―€λ‘œ 비동기식 톡신(UART)에 λΉ„ν•΄ λ‹€μ†Œ μ•ˆμ •μ μž„
     - λ²„μŠ€ ν˜•νƒœλ‘œ ν•œκ°œμ˜ IΒ²C λ§ˆμŠ€ν„°μ— λ‹€μˆ˜μ˜ 슬레이브 μž₯치 μ—°κ²° κ°€λŠ₯
     - 데이터λ₯Ό 전솑/μˆ˜μ‹  ν™œλ™μ€ λ§ˆμŠ€ν„°μ—μ„œ μ£Όλ„ν•˜λ©° 데이터 μ†‘μˆ˜μ‹ μ‹œ 슬레이브 μ£Όμ†Œλ₯Ό λ§ˆμŠ€ν„°μ— λͺ…μ‹œν•΄μ•Ό 톡신이 κ°€λŠ₯
4-3. 단점
     - 비동기식 톡신(UART)보닀 λΉ λ₯΄μ§€λ§Œ SPI에 λΉ„κ΅ν•˜λ©΄ 느림
     - λ°˜μ΄μ€‘ ν†΅μ‹ μœΌλ‘œ ν•œμͺ½μ—μ„œ 데이터λ₯Ό 보낼 λ•Œ λ°˜λŒ€νŽΈμ—μ„œ 데이터 전솑 λΆˆκ°€
     - ꡬ쑰상 λ³΅μž‘ν•˜μ—¬ μ‚¬μš©ν•˜κΈ° μ–΄λ ΅κ³  전솑을 μœ„ν•œ λ³„λ„μ˜ 회둜λ₯Ό ꡬ성해야 함

5. λΆ€κ°€ μ„€λͺ…

5-1. Floating Point Number(뢀동 μ†Œμˆ˜μ  수): 맀우 ν¬κ±°λ‚˜ μž‘μ€ 수치λ₯Ό μ§€μˆ˜μ™€ κ°€μˆ˜ λΆ€λΆ„μœΌλ‘œ λ‚˜λˆ„μ–΄ ν‘œν˜„
     - μ†Œμˆ˜μ  ν‘œν˜„, μ•„μ£Ό μž‘μ€ 수 ν‘œν˜„, μ•„μ£Ό 큰 수 ν‘œν˜„
5-2. Adafruit: μ˜€ν”ˆμ†ŒμŠ€ν˜• μ „μž ν•˜λ“œμ›¨μ–΄μ˜ 섀계 및 생산을 μ „λ¬ΈμœΌλ‘œ ν•˜λŠ” λΉ„κ³΅κ°œκΈ°μ—…μœΌλ‘œ λ―Έκ΅­ λ³Έμ‚¬μ—μ„œ μ œν’ˆμ„ 섀계 및 생산
     - OLED λ””μŠ€ν”Œλ ˆμ΄ μ‹€μŠ΅μ—μ„œ μ‚¬μš©ν•˜λ©° OLED μ œμ–΄λ₯Ό μœ„ν•΄ Adafruit_SSD1306 라이브러리 μ„€μΉ˜μ™€ 객체 μ„ μ–Έ ν•„μš”
5-3. OLED λ””μŠ€ν”Œλ ˆμ΄ μ‹€μŠ΅μ—μ„œ λ°œμƒν•˜λŠ” λ„€νŠΈμ›Œν¬ μ—°κ²° 였λ₯˜(아이폰): 개인 ν•«μŠ€νŒŸ μ—°κ²° ν›„ ν˜Έν™˜μ„± μ΅œλŒ€ν™”κ°€ ν™œμ„±ν™”λ˜μ–΄ μžˆλŠ”μ§€ 확인
     - ν˜Έν™˜μ„± μ΅œλŒ€ν™”λ₯Ό ν™œμ„±ν™”μ‹œν‚¨ ν›„ 였λ₯˜κ°€ ν•΄κ²°λ˜μ–΄ μ‹œκ°„μ΄ λ””μŠ€ν”Œλ ˆμ΄μ— ν‘œμ‹œλ˜μ—ˆμ§€λ§Œ μ •ν™•ν•œ ν•΄κ²°λ°©μ•ˆμΈμ§€ λͺ¨λ¦„
⚠️ **GitHub.com Fallback** ⚠️