board1_wifi
**────────────────────────────────**
**시스템 개요**
**Arduino Uno + HC-SR04 4개 + RGB LED + ESP8266(AT 펌웨어) 구성**
**전·후·좌·우 거리 측정 후 최소 거리 기준으로 위험 등급 판별 구조**
**판별 결과를 RGB LED로 시각화하고 UDP로 PC에 전송하는 IoT 노드 구조**
**전체 흐름 구조:**
**센서 측정**
**→ 최소 거리 계산**
**→ 위험 등급 분류**
**→ RGB 상태 표시**
**→ UDP 패킷 전송**
**→ Python 수신**
**────────────────────────────────**
**전체 동작 구조**
**setup()**
* **시리얼 통신 초기화**
* **초음파 및 RGB 핀 모드 설정**
* **RGB 점등 테스트**
* **WiFi 초기화 및 UDP 소켓 오픈**
**loop()**
* **4방향 거리 측정**
* **최소 거리 계산**
* **위험 등급 판별**
* **RGB 업데이트**
* **등급 변경 시 즉시 전송**
* **500ms 주기 전송**
* **디버그 출력**
**────────────────────────────────**
**통신 구조**
**ESP8266 AT 명령 기반 WiFi 연결 구조임**
**UDP 단방향 송신 구조임**
**PC에서 socket.bind(5000)로 수신 구조임**
**전송 데이터 형식:**
**B1,F:152,B:153,L:153,R:118,MIN:118,LV:SAFE**
**문자열 기반 CSV 구조**
**Python에서 split(",") 후 파싱 가능**
**────────────────────────────────**
**변수 역할 정리**
**WiFi 관련**
**WIFI\_SSID**
**접속할 무선 네트워크 이름 저장 변수임**
**WIFI\_PASS**
**무선 네트워크 비밀번호 저장 변수임**
**DEST\_IP**
**UDP 수신 PC의 IPv4 주소 저장 변수임**
**DEST\_PORT**
**UDP 수신 포트 번호 저장 변수임**
**센서 관련**
**TRIG\[4]**
**초음파 트리거 핀 배열**
**0=Front, 1=Back, 2=Left, 3=Right 구조**
**ECHO\[4]**
**초음파 에코 핀 배열**
**DIR\[4]**
**각 방향 문자열 저장 배열**
**디버그 출력용**
**RGB 관련**
**RGB\_R, RGB\_G, RGB\_B**
**RGB LED PWM 제어 핀 번호 저장 변수임**
**거리 기준 값**
**D\_DANGER**
**위험 거리 기준 10cm**
**D\_CLOSE**
**근접 거리 기준 30cm**
**D\_MID**
**중간 거리 기준 60cm**
**상태 관련**
**enum Level**
**위험 등급 열거형 구조**
**SAFE, MID\_LV, CLOSE\_LV, DANGER\_LV 정의**
**currentLevel**
**현재 위험 등급 저장 변수**
**dist\[4]**
**각 방향 거리값 저장 배열**
**lastSend**
**마지막 UDP 전송 시각 저장 변수**
**SEND\_MS**
**UDP 전송 주기(500ms) 저장 상수**
**wifiReady**
**WiFi 연결 성공 여부 저장 변수**
**────────────────────────────────**
**함수 역할 정리**
**measureDist(int trig, int echo)**
**초음파 거리 측정 함수**
**TRIG에 10µs 펄스 출력 후 pulseIn으로 echo 시간 측정**
**거리 = 시간 × 0.034 / 2 계산 구조**
**측정 실패 시 999 반환 구조**
**classify(float d)**
**거리값을 위험 등급으로 변환하는 함수**
**임계값 비교 기반 분기 구조**
**setRGB(int r, int g, int b)**
**RGB LED PWM 출력 제어 함수**
**updateRGB(float d)**
**거리 기반 색상 및 밝기 자동 제어 함수**
**DANGER: 빨강 점멸 구조**
**CLOSE: 빨강→주황 그라데이션 구조**
**MID: 파랑 밝기 변화 구조**
**SAFE: 약한 초록 점등 구조**
**sendUDP(float minD, Level lv)**
**UDP 전송용 문자열 생성 함수**
**CSV 포맷 구성 후 udpSend 호출 구조**
**lvStr(Level lv)**
**enum 값을 문자열로 변환하는 함수**
**UDP 패킷에 등급 텍스트 포함 목적**
**espFlush()**
**ESP 수신 버퍼 초기화 함수**
**이전 응답 제거 목적**
**atCmd(const char\* cmd, const char\* expect, unsigned long timeout)**
**AT 명령 전송 및 응답 대기 함수**
**특정 문자열 포함 여부로 성공 판별 구조**
**wifiInit()**
**WiFi 연결 및 UDP 소켓 오픈 함수**
**AT → ATE0 → CWMODE → CWJAP → CIFSR → CIPSTART 순서 구조**
**udpSend(const char\* data)**
**AT+CIPSEND 수행 함수**
**데이터 길이 전송 → '>' 프롬프트 대기 → 실제 데이터 전송 → SEND OK 확인 구조**
**────────────────────────────────**
**알고리즘 구조 요약**
**거리 측정 구조**
**각 센서를 순차 측정 후 배열에 저장 구조**
**최소값 탐색 구조**
**for문으로 dist 배열 중 최소값 선택 구조**
**위험 판단 구조**
**임계값 기반 if 분기 구조**
**이벤트 기반 전송 구조**
**등급 변경 시 즉시 전송**
**주기 기반 전송 병행 구조**
**────────────────────────────────**
**네트워크 동작 구조**
**ESP 부팅**
**→ AT 통신 확인**
**→ WiFi 접속**
**→ IP 할당**
**→ UDP 소켓 오픈**
**→ AT+CIPSEND 반복 수행**
**PC는 UDP 5000 포트에서 대기**
**패킷 수신 후 파싱 가능 구조**
**────────────────────────────────**
**시스템 특징**
**배열 기반 센서 확장 가능 구조**
**enum 기반 가독성 향상 구조**
**비차단 네트워크 처리 구조**
**실시간 LED 피드백 구조**
**UDP 사용으로 지연 최소화 가능 구조**
**────────────────────────────────**
**최종 구조 정의**
**본 코드는**
* **실시간 거리 센싱**
* **위험 판단 알고리즘**
* **RGB 시각화**
* **WiFi 네트워크 통신**
* **UDP 기반 IoT 데이터 전송**
*
**을 통합한 임베디드 센싱 노드 구조임.**
/* BOARD 1 — 사물 인식 모듈 (WiFi 버전)
* Arduino Uno R3 + ESP8266 (AT 펌웨어)
*
* ─────────────────────────────────────────────────────
* 핀 배치
* ─────────────────────────────────────────────────────
* HC-SR04 전방 TRIG=A0 ECHO=A1
* HC-SR04 후방 TRIG=A2 ECHO=A3
* HC-SR04 좌측 TRIG=2 ECHO=4
* HC-SR04 우측 TRIG=7 ECHO=8
*
* RGB LED R D11 (PWM~)
* RGB LED G D10 (PWM~)
* RGB LED B D6 (PWM~)
* RGB LED GND GND
*
* ESP8266 TX D3 (SoftSerial RX ← ESP8266 TXD)
* ESP8266 RX D5 (SoftSerial TX → ESP8266 RXD)=
* ESP8266 VCC 3.3V
* ESP8266 GND GND
* ESP8266 CH_PD 3.3V
* ESP8266 RST 3.3V (또는 미연결)
*
* ─────────────────────────────────────────────────────
* 동작
* - 4방향 거리 100ms마다 측정
* - RGB LED : 최솟값 기준 색상+밝기 변화
* < 10cm : 빨강 깜빡임 (DANGER)
* 10~30cm : 주황 (CLOSE)
* 30~60cm : 파랑 dim (MID)
* > 60cm : 초록 희미 (SAFE)
* - 500ms마다 (또는 등급 변화 시 즉시) UDP로 전송
* 형식: B1,F:23,B:45,L:12,R:67,MIN:12,LV:CLOSE
*
* 전송 방식: UDP (목적지 IP: DEST_IP, 포트: DEST_PORT)
* 라이브러리: SoftwareSerial (내장)
* ─────────────────────────────────────────────────────
*/
#include <SoftwareSerial.h>
// ── WiFi 설정 ──────────────────────────────────────────
const char* WIFI_SSID = "3F_302"; // ESP8266이 접속할 WiFi 정보
const char* WIFI_PASS = "0424719222!!";
const char* DEST_IP = "192.168.0.204"; // UDP 목적지 (Python이 실행 중인 PC의 IPv4 주소)
const int DEST_PORT = 5000; // UDP 수신 포트(Python에서 bind한 포트와 동일해야 함)
// 윈도우 방화벽 -> 고급 설정 -> 인바운드 규칙(새규칙) -> 포트 -> UDP -> 5000 -> 연결 허용 -> 모든 프로필 허용
// 제어판에서 윈도우 방화벽 끄기
// ── 핀 정의 ───────────────────────────────────────────
// 4방향 초음파 센서 TRIG / ECHO 핀 배열
// 인덱스 0=Front, 1=Back, 2=Left, 3=Right
const int TRIG[4] = {A0, A2, 2, 7};
const int ECHO[4] = {A1, A3, 4, 8};
// 방향 표시용 문자열 배열
const char* DIR[4] = {"F", "B", "L", "R"};
// RGB LED 핀 (PWM 출력 가능 핀)
const int RGB_R = 11;
const int RGB_G = 10;
const int RGB_B = 6;
// ESP8266 SoftwareSerial (RX, TX)
// D3 <- ESP TX
// D5 -> ESP RX
SoftwareSerial espSerial(3, 5);
// ── 거리 임계값 정의 (단위: cm) ─────────────────────────
const float D_DANGER = 10.0; // 10cm 미만 -> 위험
const float D_CLOSE = 30.0; // 10~30cm -> 근접
const float D_MID = 60.0; // 30~60cm -> 중간
// ── 위험 등급 열거형(enum) ──────────────────────────────
enum Level {
SAFE, // 안전
MID_LV, // 중간
CLOSE_LV, // 근접
DANGER_LV // 위험
};
Level currentLevel = SAFE; // 현재 등급 저장
// ── 전역 변수 ──────────────────────────────────────────
float dist[4] = {999, 999, 999, 999}; // 각 방향 거리 저장 배열
unsigned long lastSend = 0; // UDP 전송 주기 관리용
const unsigned long SEND_MS = 500; // 500ms마다 전송
bool wifiReady = false; // WiFi 연결 성공 여부
// ── 함수 선언 ──────────────────────────────────────────
float measureDist(int trig, int echo); // 거리 측정
Level classify(float d); // 거리 -> 등급
void setRGB(int r, int g, int b); // RGB 직접 설정
void updateRGB(float d); // 거리 기반 RGB 제어
void sendUDP(float minD, Level lv); // UDP 전송
const char* lvStr(Level lv); // enum -> 문자열
// ESP8266 AT 명령 관련
bool atCmd(const char* cmd, const char* expect, unsigned long timeout = 3000);
void espFlush();
bool wifiInit();
bool udpSend(const char* data);
// ══════════════════════════════════════════════════════
void setup() {
// USB 시리얼 모니터용
Serial.begin(9600);
// ESP8266 통신용 시리얼
espSerial.begin(9600);
// 초음파 핀 설정
for (int i = 0; i < 4; i++) {
pinMode(TRIG[i], OUTPUT);
pinMode(ECHO[i], INPUT);
}
// RGB 핀 설정
pinMode(RGB_R, OUTPUT);
pinMode(RGB_G, OUTPUT);
pinMode(RGB_B, OUTPUT);
// 시작 점등 확인 (R->G->B)
setRGB(255, 0, 0); delay(300);
setRGB(0, 255, 0); delay(300);
setRGB(0, 0, 255); delay(300);
setRGB(0, 0, 0);
Serial.println("[BOARD1] Setup start");
// WiFi 초기화
wifiReady = wifiInit();
if (wifiReady) {
Serial.println("[WiFi] Connected!");
setRGB(0, 50, 0); // 초록 — 연결 성공 표시
delay(500);
setRGB(0, 0, 0);
} else {
Serial.println("[WiFi] FAILED — check wiring/SSID/PW");
// 빨강 천천히 점멸 -> 연결 실패 표시
for (int i = 0; i < 5; i++) {
setRGB(200, 0, 0); delay(400);
setRGB(0, 0, 0); delay(400);
}
}
Serial.println("[BOARD1] Ready");
}
// ══════════════════════════════════════════════════════
void loop() {
unsigned long now = millis();
// 4방향 거리 측정
for (int i = 0; i < 4; i++) {
dist[i] = measureDist(TRIG[i], ECHO[i]);
}
// 최솟 거리 계산
float minD = dist[0];
for (int i = 1; i < 4; i++) {
if (dist[i] < minD) minD = dist[i];
}
// 등급 판별
Level prev = currentLevel;
currentLevel = classify(minD);
// RGB 업데이트
updateRGB(minD);
// 등급 변화 시 즉시 전송
if (currentLevel != prev) {
sendUDP(minD, currentLevel);
lastSend = now;
}
// 정기 전송 500ms
if (now - lastSend >= SEND_MS) {
lastSend = now;
sendUDP(minD, currentLevel);
}
// 시리얼 디버그
for (int i = 0; i < 4; i++) {
Serial.print(DIR[i]); Serial.print(":"); Serial.print((int)dist[i]); Serial.print(" ");
}
Serial.print("LV:"); Serial.println(lvStr(currentLevel));
delay(100);
}
// ══════════════════════════════════════════════════════
// 초음파 거리 측정 (cm)
float measureDist(int trig, int echo) {
// 트리거 신호 생성
digitalWrite(trig, LOW);
delayMicroseconds(2);
digitalWrite(trig, HIGH);
delayMicroseconds(10);
digitalWrite(trig, LOW);
//echo가 HIGH인 시간 측정
long dur = pulseIn(echo, HIGH, 30000UL);
if (dur == 0) return 999.0;
// 음속 0.034cm/us 이용
return dur * 0.034f / 2.0f;
}
// ── 거리 -> 등급 ────────────────────────────────────────
Level classify(float d) {
if (d < D_DANGER) return DANGER_LV;
if (d < D_CLOSE) return CLOSE_LV;
if (d < D_MID) return MID_LV;
return SAFE;
}
// ── RGB 직접 출력 ──────────────────────────────────────
void setRGB(int r, int g, int b) {
analogWrite(RGB_R, r);
analogWrite(RGB_G, g);
analogWrite(RGB_B, b);
}
// ── 거리에 따른 RGB 자동 제어 ──────────────────────────
void updateRGB(float d) {
if (d >= 400) { setRGB(0, 3, 0); return; }
if (d < D_DANGER) {
bool on = (millis() % 300) < 150;
setRGB(on ? 255 : 60, 0, 0);
} else if (d < D_CLOSE) {
float t = (d - D_DANGER) / (D_CLOSE - D_DANGER);
setRGB(255, (int)(100 * t), 0);
} else if (d < D_MID) {
float t = 1.0 - (d - D_CLOSE) / (D_MID - D_CLOSE);
setRGB(0, 0, (int)(30 + 150 * t));
} else {
float t = 1.0 - min((d - D_MID) / 100.0f, 1.0f);
setRGB(0, (int)(5 + 35 * t), 0);
}
}
// ── UDP 전송 (WiFi 준비 안 됐으면 Serial만 출력) ────────
void sendUDP(float minD, Level lv) {
char buf[80];
snprintf(buf, sizeof(buf),
"B1,F:%d,B:%d,L:%d,R:%d,MIN:%d,LV:%s",
(int)dist[0], (int)dist[1],
(int)dist[2], (int)dist[3],
(int)minD, lvStr(lv)
);
Serial.print("[UDP] "); Serial.println(buf);
if (wifiReady) {
if (!udpSend(buf)) {
Serial.println("[UDP] Send failed");
}
}
}
// ── enum -> 문자열 ─────────────────────────────────────
const char* lvStr(Level lv) {
switch (lv) {
case DANGER_LV: return "DANGER";
case CLOSE_LV: return "CLOSE";
case MID_LV: return "MID";
default: return "SAFE";
}
}
// ══════════════════════════════════════════════════════
// ESP8266 AT 명령 처리
// ══════════════════════════════════════════════════════
// ESP8266 수신 버퍼 비우기
void espFlush() {
unsigned long t = millis();
while (millis() - t < 200) {
while (espSerial.available()) espSerial.read();
}
}
// AT 명령 전송 후 기대 문자열 포함 여부 확인
bool atCmd(const char* cmd, const char* expect, unsigned long timeout) {
espFlush();
espSerial.println(cmd);
Serial.print("[AT] >> "); Serial.println(cmd);
String resp = "";
unsigned long start = millis();
while (millis() - start < timeout) {
while (espSerial.available()) {
char c = espSerial.read();
resp += c;
}
if (resp.indexOf(expect) != -1) {
Serial.print("[AT] << "); Serial.println(resp);
return true;
}
}
Serial.print("[AT] TIMEOUT — got: "); Serial.println(resp);
return false;
}
// WiFi 연결 + UDP 소켓 열기
bool wifiInit() {
delay(3000); // ESP8266 부팅 대기
// 1) 모듈 응답 확인
if (!atCmd("AT", "OK", 3000)) return false;
// 2) Echo off
atCmd("ATE0", "OK", 2000);
// 3) Station 모드
if (!atCmd("AT+CWMODE=1", "OK", 2000) &&
!atCmd("AT+CWMODE=1", "no change", 2000))
return false;
// 4) WiFi 연결 (최대 15초)
char joinCmd[80];
snprintf(joinCmd, sizeof(joinCmd), "AT+CWJAP=\"%s\",\"%s\"", WIFI_SSID, WIFI_PASS);
if (!atCmd(joinCmd, "OK", 15000)) return false;
atCmd("AT+CIFSR", "OK", 3000);
// 5) UDP 소켓 열기 (링크 ID=0, 로컬포트=임의)
char udpCmd[80];
snprintf(udpCmd, sizeof(udpCmd),
"AT+CIPSTART=\"UDP\",\"%s\",%d", DEST_IP, DEST_PORT);
if (!atCmd(udpCmd, "OK", 5000) && !atCmd(udpCmd, "ALREADY CONNECT", 2000)) return false;
return true;
}
// UDP 데이터 전송 (AT+CIPSEND)
bool udpSend(const char* data) {
int len = strlen(data) + 2; // \r\n 포함
char sendCmd[30];
snprintf(sendCmd, sizeof(sendCmd), "AT+CIPSEND=%d", len);
espSerial.println(sendCmd);
Serial.print("[AT] >> "); Serial.println(sendCmd);
// '>' 프롬프트 대기
unsigned long start = millis();
bool gotPrompt = false;
String resp = "";
while (millis() - start < 3000) {
while (espSerial.available()) {
char c = espSerial.read();
resp += c;
if (c == '>') { gotPrompt = true; break; }
}
if (gotPrompt) break;
}
if (!gotPrompt) {
Serial.println("[AT] No '>' prompt");
return false;
}
// 실제 데이터 전송
espSerial.println(data);
// SEND OK 대기
return atCmd("", "SEND OK", 3000);
}
import socket
UDP_IP = "0.0.0.0"
UDP_PORT = 5000
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))
#sock.settimeout(2.0)
print(f"Listening on UDP {UDP_IP}:{UDP_PORT} ...")
while True:
try:
data, addr = sock.recvfrom(2048)
msg = data.decode(errors="replace").strip()
print(f"[FROM {addr}] {msg}")
except socket.timeout:
print("...no packet")
board2_wifi
(조도, 습도, 소리)
/*
* ============================================================
* BOARD2 — 위험 감지 시스템
*
* [사용 센서 & 실제 핀 구성]
* DHT11 모듈 : VCC / DATA / GND (모듈형, 3핀)
* Sound 센서 모듈: + / G / A0 / D0
* 포토센서(LDR) : 단독 소자, 10kΩ 분압 회로 구성
* ESP8266 ESP-01 : VCC / GND / CH_PD / RST / IO0 / IO2 / TXD / RXD
*
* [Arduino 핀 할당]
* D2 ← ESP TXD (직결, 3.3V→5V 허용)
* D3 → ESP RXD (10kΩ+10kΩ 분압 경유, 5V→2.5V)
* D4 ← DHT11 DATA
* A0 ← LDR 신호 (10kΩ 분압 회로)
* A1 ← Sound AO
*
* [임계값 초과 시에만 UDP WiFi 전송]
* ============================================================
*/
#include <SoftwareSerial.h>
#include <DHT.h>
// ── WiFi 설정 ──────────────────────────────────────────
const char* WIFI_SSID = "3F_302";
const char* WIFI_PASS = "0424719222!!";
const char* DEST_IP = "192.168.0.133";
const int DEST_PORT = 5000;
// ── 핀 정의 ───────────────────────────────────────────
#define DHT_PIN 4
#define DHT_TYPE DHT11
#define LDR_PIN A0
#define SOUND_PIN A1
// ESP8266 SoftwareSerial (RX=D2 ← ESP TXD, TX=D3 → ESP RXD)
SoftwareSerial espSerial(2, 3);
// ── 임계값 ────────────────────────────────────────────
#define THRESH_TEMP 30.0f
#define THRESH_HUMID 70.0f
#define THRESH_DARK 300
#define THRESH_SOUND 550
// ── 전역 변수 ─────────────────────────────────────────
DHT dht(DHT_PIN, DHT_TYPE);
bool wifiReady = false;
unsigned long lastMs = 0;
const unsigned long INTERVAL = 2000;
// ── 함수 선언 ─────────────────────────────────────────
bool atCmd(const char* cmd, const char* expect, unsigned long timeout = 3000);
void espFlush();
bool wifiInit();
bool udpSend(const char* data);
void printSerial(float t, float h, int ldr, int snd, bool* alr);
// ══════════════════════════════════════════════════════
void setup() {
Serial.begin(9600);
espSerial.begin(9600);
dht.begin();
Serial.println(F("================================"));
Serial.println(F(" BOARD2 위험 감지 시스템 v1.0 "));
Serial.println(F("================================"));
Serial.println(F("[INIT] 센서 초기화 완료"));
// Board1과 동일한 WiFi 초기화 함수 호출
wifiReady = wifiInit();
if (wifiReady) {
Serial.println(F("[WiFi] Connected!"));
} else {
Serial.println(F("[WiFi] FAILED — check wiring/SSID/PW"));
}
Serial.println(F("--- 임계값 ---"));
Serial.print(F(" 온도 > ")); Serial.print(THRESH_TEMP); Serial.println(F(" C"));
Serial.print(F(" 습도 > ")); Serial.print(THRESH_HUMID); Serial.println(F(" %"));
Serial.print(F(" 조도 < ")); Serial.print(THRESH_DARK); Serial.println(F(" /1023"));
Serial.print(F(" 소음 > ")); Serial.print(THRESH_SOUND); Serial.println(F(" /1023"));
Serial.println(F("================================\n"));
}
// ══════════════════════════════════════════════════════
void loop() {
if (millis() - lastMs < INTERVAL) return;
lastMs = millis();
float temp = dht.readTemperature();
float humid = dht.readHumidity();
int ldr = analogRead(LDR_PIN);
int snd = analogRead(SOUND_PIN);
if (isnan(temp) || isnan(humid)) {
Serial.println(F("[ERR] DHT11 읽기 실패"));
return;
}
bool alert =
(temp > THRESH_TEMP) ||
(humid > THRESH_HUMID) ||
(ldr < THRESH_DARK) ||
(snd > THRESH_SOUND);
// 한 줄 출력
Serial.print("B2,");
Serial.print("T:");
Serial.print(temp, 1);
Serial.print(" H:");
Serial.print(humid, 1);
Serial.print(" L:");
Serial.print(ldr);
Serial.print(" S:");
Serial.print(snd);
Serial.print(" LV:");
Serial.println(alert ? "ALERT" : "SAFE");
// UDP로 항상 전송
if (wifiReady) {
char buf[80];
snprintf(buf, sizeof(buf),
"B2,T:%.1f H:%.1f L:%d S:%d LV:%s", //Temp온도 Humid습도 ldr포토센서 snd사운드
temp, humid, ldr, snd,
alert ? "ALERT" : "SAFE"
);
udpSend(buf);
}
}
// ══════════════════════════════════════════════════════
// ESP8266 AT 명령 처리 — Board1과 완전 동일
// ══════════════════════════════════════════════════════
void espFlush() {
unsigned long t = millis();
while (millis() - t < 200) {
while (espSerial.available()) espSerial.read();
}
}
bool atCmd(const char* cmd, const char* expect, unsigned long timeout) {
espFlush();
espSerial.println(cmd);
Serial.print("[AT] >> "); Serial.println(cmd);
String resp = "";
unsigned long start = millis();
while (millis() - start < timeout) {
while (espSerial.available()) {
char c = espSerial.read();
resp += c;
}
if (resp.indexOf(expect) != -1) {
Serial.print("[AT] << "); Serial.println(resp);
return true;
}
}
Serial.print("[AT] TIMEOUT — got: "); Serial.println(resp);
return false;
}
bool wifiInit() {
delay(3000); // ESP8266 부팅 대기
// 1) 모듈 응답 확인
if (!atCmd("AT", "OK", 3000)) return false;
// 2) Echo off
atCmd("ATE0", "OK", 2000);
// 3) Station 모드
if (!atCmd("AT+CWMODE=1", "OK", 2000) &&
!atCmd("AT+CWMODE=1", "no change", 2000))
return false;
// 4) WiFi 연결 (최대 15초)
char joinCmd[80];
snprintf(joinCmd, sizeof(joinCmd), "AT+CWJAP=\"%s\",\"%s\"", WIFI_SSID, WIFI_PASS);
if (!atCmd(joinCmd, "OK", 15000)) return false;
atCmd("AT+CIFSR", "OK", 3000);
// 5) UDP 소켓 열기
char udpCmd[80];
snprintf(udpCmd, sizeof(udpCmd),
"AT+CIPSTART=\"UDP\",\"%s\",%d", DEST_IP, DEST_PORT);
if (!atCmd(udpCmd, "OK", 5000) &&
!atCmd(udpCmd, "ALREADY CONNECT", 2000) &&
!atCmd(udpCmd, "CONNECT", 2000)) return false;
return true;
}
bool udpSend(const char* data) {
int len = strlen(data) + 2; // \r\n 포함
char sendCmd[30];
snprintf(sendCmd, sizeof(sendCmd), "AT+CIPSEND=%d", len);
espSerial.println(sendCmd);
Serial.print("[AT] >> "); Serial.println(sendCmd);
// '>' 프롬프트 대기
unsigned long start = millis();
bool gotPrompt = false;
String resp = "";
while (millis() - start < 3000) {
while (espSerial.available()) {
char c = espSerial.read();
resp += c;
if (c == '>') {
gotPrompt = true;
break;
}
}
if (gotPrompt) break;
}
if (!gotPrompt) {
Serial.println("[AT] No '>' prompt");
return false;
}
// 데이터 전송
espSerial.println(data);
// SEND OK 대기 (추가 AT 명령 보내지 않음)
resp = "";
start = millis();
while (millis() - start < 3000) {
while (espSerial.available()) {
char c = espSerial.read();
resp += c;
}
if (resp.indexOf("SEND OK") != -1) {
Serial.println("[AT] SEND OK");
return true;
}
if (resp.indexOf("ERROR") != -1) {
Serial.println("[AT] SEND ERROR");
return false;
}
}
Serial.print("[AT] SEND TIMEOUT — got: ");
Serial.println(resp);
return false;
}
// ══════════════════════════════════════════════════════
// 시리얼 모니터 출력
// ══════════════════════════════════════════════════════
void printSerial(float t, float h, int ldr, int snd, bool* alr) {
// 전체 위험 여부 판단
bool anyAlert = alr[0] || alr[1] || alr[2] || alr[3];
Serial.print(F("T:"));
Serial.print(t, 1);
Serial.print(F(" H:"));
Serial.print(h, 1);
Serial.print(F(" L:"));
Serial.print(ldr);
Serial.print(F(" S:"));
Serial.print(snd);
Serial.print(F(" | LV: "));
if (anyAlert) {
Serial.println(F("ALERT"));
} else {
Serial.println(F("SAFE"));
}
}
'로보테크AI' 카테고리의 다른 글
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/03/05 (0) | 2026.03.05 |
|---|---|
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/03/04 (0) | 2026.03.04 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/27 (0) | 2026.02.27 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/26[조별과제1] (0) | 2026.02.26 |
| 융합_로보테크 AI 자율주행 로봇 개발자 과정-26/02/25 (0) | 2026.02.25 |