์นดํ…Œ๊ณ ๋ฆฌ ์—†์Œ

ESP32-S3์™€ ESP-NOW ๊ธฐ๋ฐ˜ ๋Œ€๊ทœ๋ชจ ์„ผ์„œ ๋„คํŠธ์›Œํฌ์˜ ํŒจํ‚ท ์œ ์‹ค ํ•ด๊ฒฐ: ๋™์  ์ฑ„๋„ ์Šค์œ„์นญ๊ณผ FreeRTOS ๋ง๋ฒ„ํผ ์ตœ์ ํ™”

๊ฒŒ์ž„๊ต์ˆ˜ 2026. 10. 17. 16:01
๋ฐ˜์‘ํ˜•

๐ŸŒ English Abstract

This article provides a comprehensive technical guide on resolving packet loss in large-scale multi-point sensor networks using ESP32-S3 and ESP-NOW protocol. We explore how RF interference in the 2.4GHz ISM band degrades network reliability and introduce an automated Dynamic Channel Switching (DCS) mechanism paired with FreeRTOS Ring Buffer optimization. By decoupling interrupt service routines from packet processing and implementing adaptive channel hopping, engineers can achieve ultra-low latency and near-zero frame loss even in noisy wireless environments.

1. ์„œ๋ก : ๋Œ€๊ทœ๋ชจ ESP-NOW ๋„คํŠธ์›Œํฌ์˜ ํ•œ๊ณ„์™€ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…์˜ ํ•„์š”์„ฑ

Espressif์˜ ESP-NOW ํ”„๋กœํ† ์ฝœ์€ Wi-Fi ์—ฐ๊ฒฐ ์ƒ์„ฑ ๊ณผ์ •(Handshake) ์—†์ด 2.4GHz ISM ๋Œ€์—ญ์„ ์ด์šฉํ•ด ์†Œ๊ทœ๋ชจ ๋ฐ์ดํ„ฐ๋ฅผ ๊ณ ์†์œผ๋กœ ์ฃผ๊ณ ๋ฐ›์„ ์ˆ˜ ์žˆ๋Š” ๋›ฐ์–ด๋‚œ ๋น„๋™๊ธฐ ํ†ต์‹ (Asynchronous Communication) ์†”๋ฃจ์…˜์ž…๋‹ˆ๋‹ค. ํŠนํžˆ ESP32-S3 ์นฉ์…‹์˜ ๊ฐ•๋ ฅํ•œ ๋“€์–ผ์ฝ”์–ด ์„ฑ๋Šฅ๊ณผ Vector Instruction ์ง€์›์€ ๋‹ค์ˆ˜์˜ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์ „๋‹ฌ๋˜๋Š” ์„ผ์„œ ๋ฐ์ดํ„ฐ๋ฅผ ์ง‘๊ณ„ํ•˜๋Š” ๊ฒŒ์ดํŠธ์›จ์ด(Gateway) ๋ฐ ๊ณ ์„ฑ๋Šฅ ์—ฃ์ง€ ๋…ธ๋“œ ๊ตฌ์ถ•์— ์ตœ์ ์˜ ํ™˜๊ฒฝ์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

ํ•˜์ง€๋งŒ ์‚ฐ์—… ํ˜„์žฅ์ด๋‚˜ ๋ฐ€์ง‘๋œ ์ฃผ๊ฑฐ ๊ณต๊ฐ„์— ์ˆ˜์‹ญ ~ ์ˆ˜๋ฐฑ ๋Œ€์˜ ๋…ธ๋“œ๋ฅผ ๋ฐฐ์น˜ํ•˜๋Š” ๋Œ€๊ทœ๋ชจ ๋‹ค์  ์„ผ์„œ ๋„คํŠธ์›Œํฌ(Large-scale Multi-point Sensor Network)๋ฅผ ๊ตฌ์ถ•ํ•  ๋•Œ ์น˜๋ช…์ ์ธ ๋ฌธ์ œ์— ์ง๋ฉดํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๊ธฐ์กด Wi-Fi ์‹ ํ˜ธ, ๋ธ”๋ฃจํˆฌ์Šค(Bluetooth) ๊ธฐ๊ธฐ, ๊ทธ๋ฆฌ๊ณ  ์ธ์ ‘ ESP-NOW ๋…ธ๋“œ ๊ฐ„์˜ ๋™์‹œ ์†ก์‹ ์œผ๋กœ ์ธํ•œ RF ์ฑ„๋„ ๊ฐ„์„ญ(Radio Frequency Channel Interference) ๋ฐ ๋™์‹œ ์ถฉ๋Œ(Collision)์ž…๋‹ˆ๋‹ค.

์ด ๊ธ€์—์„œ๋Š” RF ๊ฐ„์„ญ ํ™˜๊ฒฝ์—์„œ ๋ฐœ์ƒํ•˜ ํŒจํ‚ท ์ˆ˜์‹ ์œจ(Packet Delivery Ratio, PDR) ์ €ํ•˜ ๋ฌธ์ œ๋ฅผ ํ•ด๊ฒฐํ•˜๊ธฐ ์œ„ํ•ด ๋™์  ์ฑ„๋„ ์Šค์œ„์นญ(Dynamic Channel Switching, DCS) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ์„ค๊ณ„ํ•˜๊ณ , ๊ฒŒ์ดํŠธ์›จ์ด ๋ณ‘๋ชฉ์„ ํ•ด์†Œํ•˜๊ธฐ ์œ„ํ•œ FreeRTOS ๋ง๋ฒ„ํผ(Ring Buffer) ๊ตฌ์กฐ ์ตœ์ ํ™” ๊ธฐ๋ฒ•์„ ์‹ค๋ฌด ์ˆ˜์ค€์—์„œ ๊นŠ์ด ์žˆ๊ฒŒ ๋‹ค๋ฃน๋‹ˆ๋‹ค.



2. RF ์ฑ„๋„ ๊ฐ„์„ญ๊ณผ ํŒจํ‚ท ์œ ์‹ค(Packet Loss) ์›์ธ ๋ถ„์„

๋Œ€๊ทœ๋ชจ ESP-NOW ๋„คํŠธ์›Œํฌ์—์„œ ๋ฐœ์ƒํ•˜ ํŒจํ‚ท ์œ ์‹ค์˜ ์›์ธ์€ ํฌ๊ฒŒ ๋ฌด์„  ๋ฌผ๋ฆฌ ๊ณ„์ธต(PHY Layer)์˜ ๊ฐ„์„ญ๊ณผ ์‹œ์Šคํ…œ ๋‚ด๋ถ€์˜ ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ(Buffer Overflow) ๋‘ ๊ฐ€์ง€๋กœ ๋‚˜๋‰ฉ๋‹ˆ๋‹ค.

2.1. 2.4GHz ๋Œ€์—ญ ํ˜ผ์‹ ๊ณผ CCA(Clear Channel Assessment) ์‹คํŒจ

ESP-NOW๋Š” Wi-Fi์˜ MAC ๊ณ„์ธต ํ”„๋ ˆ์ž„(Action Frame)์„ ํ™œ์šฉํ•˜๋ฏ€๋กœ CSMA/CA(Carrier Sense Multiple Access with Collision Avoidance) ๋ฉ”์ปค๋‹ˆ์ฆ˜์— ์˜์กดํ•ฉ๋‹ˆ๋‹ค. ์ฃผ๋ณ€์— ๊ฐ•๋ ฅํ•œ Wi-Fi AP ์‹ ํ˜ธ๋‚˜ ๋ฐ์ดํ„ฐ ํŠธ๋ž˜ํ”ฝ์ด ๋ฐ€์ง‘๋˜์–ด ์žˆ์œผ๋ฉด ๋‹ค์Œ๊ณผ ๊ฐ™์€ ํ˜„์ƒ์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • ๋™์ผ ์ฑ„๋„ ๊ฐ„์„ญ(Co-Channel Interference, CCI): ๋™์ผํ•œ ์ฑ„๋„(์˜ˆ: Channel 1)์„ ์‚ฌ์šฉํ•˜๋Š” ํƒ€ ๊ธฐ๊ธฐ์˜ ์‹ ํ˜ธ๋กœ ์ธํ•ด ์‹ ํ˜ธ ๋Œ€ ์žก์Œ๋น„(Signal-to-Noise Ratio, SNR)๊ฐ€ ๊ธ‰๊ฒฉํžˆ ์ €ํ•˜๋ฉ๋‹ˆ๋‹ค.
  • ์ธ์ ‘ ์ฑ„๋„ ๊ฐ„์„ญ(Adjacent Channel Interference, ACI): ๋Œ€์—ญํญ์ด ์ค‘์ฒฉ๋˜๋Š” ์ฃผํŒŒ์ˆ˜ ๋Œ€์—ญ์—์„œ ๋ฐœ์ƒํ•˜๋Š” ์ŠคํŽ™ํŠธ๋Ÿผ ์Šคํ•„์˜ค๋ฒ„(Spillover) ํ˜„์ƒ์ž…๋‹ˆ๋‹ค.
  • ACK ๋ฏธ์ˆ˜์‹  ๋ฐ ์žฌ์ „์†ก ์˜ค๋ฒ„ํ—ค๋“œ: ๋‹จ๋ฐฉํ–ฅ ๋˜๋Š” ์œ ๋‹ˆ์บ์ŠคํŠธ(Unicast) ์ „์†ก ์‹œ RF ํ˜ผ์‹ ์œผ๋กœ ACK๊ฐ€ ์†์‹ค๋˜๋ฉด ํ†ต์‹  ํƒ€์ž„์•„์›ƒ์ด ๋ฐœ์ƒํ•˜์—ฌ ์ „์ฒด ํ†ต์‹  ์Šค๋ฃจํ’‹(Throughput)์ด ๊ธ‰๊ฐํ•ฉ๋‹ˆ๋‹ค.

2.2. ๊ฒŒ์ดํŠธ์›จ์ด์˜ ISR(Interrupt Service Routine) ์ง€์—ฐ๊ณผ Ring Buffer ๋ถˆ๊ท ํ˜•

์ˆ˜์‹ญ ๊ฐœ์˜ ์Šฌ๋ ˆ์ด๋ธŒ ๋…ธ๋“œ๊ฐ€ ๋™์‹œ์— ๋ฐ์ดํ„ฐ๋ฅผ ์ „์†กํ•  ๋•Œ, ๊ฒŒ์ดํŠธ์›จ์ด์˜ ESP-NOW ์ˆ˜์‹  ์ฝœ๋ฐฑ ํ•จ์ˆ˜(esp_now _recv_cb_t)๋Š” ์ธํ„ฐ๋ŸฝํŠธ ์ปจํ…์ŠคํŠธ(ISR) ๋˜๋Š” High-priority Wi-Fi Task์—์„œ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค. ์ˆ˜์‹  ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ ๋‹ค์Œ๊ณผ ๊ฐ™์€ ์‹ค์ˆ˜๋ฅผ ๋ฒ”ํ•  ๊ฒฝ์šฐ ํŒจํ‚ท ์œ ์‹ค์ด ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  • ์ˆ˜์‹  ์ฝœ๋ฐฑ ๋‚ด์—์„œ ๋™๊ธฐ์‹ I/O ์ฒ˜๋ฆฌ(UART ์ถœ๋ ฅ, Flash ์ €์žฅ, ๋ณต์žกํ•œ ํŒŒ์‹ฑ ์—ฐ์‚ฐ ๋“ฑ) ์ˆ˜ํ–‰
  • FreeRTOS ํƒœ์Šคํฌ ๊ฐ„ ํ(Queue) ํฌ๊ธฐ ๋ถ€์กฑ์œผ๋กœ ์ธํ•œ ์ˆ˜์‹  ํŒจํ‚ท ๋“œ๋กญ(Packet Drop)
  • ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น ๋ฐ ํ•ด์ œ(malloc/free)์˜ ์žฆ์€ ํ˜ธ์ถœ๋กœ ์ธํ•œ ๋ฉ”๋ชจ๋ฆฌ ํŒŒํŽธํ™”(Memory Fragmentation)


3. ๋™์  ์ฑ„๋„ ์Šค์œ„์นญ(Dynamic Channel Switching, DCS) ์„ค๊ณ„

RF ๊ฐ„์„ญ์— ๋Šฅ๋™์ ์œผ๋กœ ๋Œ€์‘ํ•˜๊ธฐ ์œ„ํ•ด ๋„คํŠธ์›Œํฌ ์ „์ฒด๊ฐ€ ์ตœ์ ์˜ Wi-Fi ์ฑ„๋„์„ ํƒ์ƒ‰ํ•˜์—ฌ ๋™์‹œ์— ์ฑ„๋„์„ ๋ณ€๊ฒฝํ•˜๋Š” ๋™์  ์ฑ„๋„ ์Šค์œ„์นญ(Dynamic Channel Switching) ์•Œ๊ณ ๋ฆฌ์ฆ˜์„ ๋„์ž…ํ•ฉ๋‹ˆ๋‹ค.

3.1. ์ฑ„๋„ ํ’ˆ์งˆ ํ‰๊ฐ€(Channel Quality Assessment) ๋ฉ”์ปค๋‹ˆ์ฆ˜

๊ฒŒ์ดํŠธ์›จ์ด๋Š” ๊ฐ ๋…ธ๋“œ๋กœ๋ถ€ํ„ฐ ์ˆ˜์‹ ๋˜๋Š” ํŒจํ‚ท์˜ RSSI(Received Signal Strength Indicator), ํŒจํ‚ท ์—๋Ÿฌ์œจ(Packet Error Rate, PER), ๋ฐ NOISE floor ๊ฐ’์„ ์ฃผ๊ธฐ์ ์œผ๋กœ ๊ฐ์‹œํ•ฉ๋‹ˆ๋‹ค.

์ง€ํ‘œ (Metric) ์ž„๊ณ„๊ฐ’ (Threshold) ๋™์  ์ฑ„๋„ ์ „ํ™˜ ์กฐ๊ฑด
PER (Packet Error Rate) > 15% (์ตœ๊ทผ 100๊ฐœ ํ”„๋ ˆ์ž„ ๊ธฐ์ค€) PER ์กฐ๊ฑด์„ 5์ดˆ ์ด์ƒ ์ง€์† ์ถฉ์กฑํ•˜๊ฑฐ๋‚˜ ์ˆ˜์‹  ์‹คํŒจ ์นด์šดํŠธ๊ฐ€ ํ•œ๊ณ„์น˜ ์ดˆ๊ณผ ์‹œ ์ฑ„๋„ ๋ณ€๊ฒฝ ์ ˆ์ฐจ(Channel Switching Sequence) ์ง„์ž…
RSSI < -85 dBm (๋…ธ๋“œ ํ‰๊ท )

3.2. ๋™๊ธฐํ™” ๋ฐ ์ฑ„๋„ ํ˜ธํ•‘ ํ”„๋กœํ† ์ฝœ (Channel Hopping Protocol)

์ฑ„๋„ ๋ณ€๊ฒฝ ์‹œ ์ผ๋ถ€ ๋…ธ๋“œ๊ฐ€ ๋ฏธ์•„(Orphan) ์ƒํƒœ๊ฐ€ ๋˜๋Š” ๊ฒƒ์„ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•ด 3๋‹จ๊ณ„ ํ•‘ํ ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  1. Channel Switch Announcement (CSA) ๋ฐฉ์†ก: ๊ฒŒ์ดํŠธ์›จ์ด๊ฐ€ ํ˜„์žฌ ์ฑ„๋„์—์„œ ๋ชจ๋“  ๋…ธ๋“œ์—๊ฒŒ ๋ณ€๊ฒฝ๋  ํƒ€๊ฒŸ ์ฑ„๋„ ๋ฒˆํ˜ธ์™€ ์Šค์œ„์นญ ํƒ€์ž„์Šคํƒฌํ”„(Ticks)๊ฐ€ ๋‹ด๊ธด ํŒจํ‚ท์„ Broadcast๋กœ 3ํšŒ ์—ฐ๋‹ฌ์•„ ๋ฐœ์†กํ•ฉ๋‹ˆ๋‹ค.
  2. ์ˆ˜์‹  ํ™•์ธ ๋ฐ ์ฑ„๋„ ๋ณ€๊ฒฝ ์ค€๋น„: ์Šฌ๋ ˆ์ด๋ธŒ ๋…ธ๋“œ๋Š” CSA ํŒจํ‚ท ์ˆ˜์‹  ์ฆ‰์‹œ ํƒ€์ด๋จธ๋ฅผ ์„ค์ •ํ•˜๊ณ , ๋ณ€๊ฒฝ๋  ์ฑ„๋„๋กœ ์ด๋™ํ•  ์ค€๋น„๋ฅผ ๋งˆ์นฉ๋‹ˆ๋‹ค.
  3. Fallback & Scanning Mode: ๋งŒ์•ฝ ํŠน์ • ์Šฌ๋ ˆ์ด๋ธŒ ๋…ธ๋“œ๊ฐ€ CSA๋ฅผ ๋†“์น˜๊ณ  ์ผ์ • ์‹œ๊ฐ„ ๋™์•ˆ ๊ฒŒ์ดํŠธ์›จ์ด์™€์˜ ํ†ต์‹ ์ด ๋Š๊ธฐ๋ฉด(Heartbeat Timeout), ํ•ด๋‹น ๋…ธ๋“œ๋Š” 1~13๋ฒˆ ์ฑ„๋„์„ ์ˆœ์ฐจ์ ์œผ๋กœ ์Šค์บ๋‹(Channel Scanning)ํ•˜๋ฉฐ ๊ฒŒ์ดํŠธ์›จ์ด์˜ Beacon์„ ํƒ์ƒ‰ํ•˜๋Š” ๋ณต๊ตฌ ๋ชจ๋“œ๋กœ ์ „ํ™˜๋ฉ๋‹ˆ๋‹ค.

3.3. C/C++ ๊ธฐ๋ฐ˜ ๊ตฌํ˜„ ํ•ต์‹ฌ ์˜ˆ์‹œ

ESP-IDF ํ™˜๊ฒฝ์—์„œ ๋™์ ์œผ๋กœ Wi-Fi ์ฑ„๋„์„ ๋ณ€๊ฒฝํ•˜๋Š” ํ•ต์‹ฌ ์ œ์–ด ์ฝ”๋“œ ๊ตฌ์กฐ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

#include "esp_wifi.h"
#include "esp_now.h"
#include "esp_log.h"

static const char *TAG = "DCS_MODULE";
static uint8_t current_channel = 1;

// ํŠน์ • ์ฑ„๋„๋กœ ์•ˆ์ „ํ•˜๊ฒŒ ์Šค์œ„์นญํ•˜๋Š” ํ•จ์ˆ˜
esp_err_t switch_esp_now_channel(uint8_t new_channel) {
    if (new_channel < 1 || new_channel > 13) {
        ESP_LOGE(TAG, "Invalid channel: %d", new_channel);
        return ESP_ERR_INVALID_ARG;
    }

    // Wi-Fi Primary ์ฑ„๋„ ๋ณ€๊ฒฝ
    esp_err_t ret = esp_wifi_set_channel(new_channel, WIFI_SECOND_CHAN_NONE);
    if (ret == ESP_OK) {
        current_channel = new_channel;
        ESP_LOGI(TAG, "Successfully switched to Channel %d", current_channel);
    } else {
        ESP_LOGE(TAG, "Failed to set channel: %s", esp_err_to_name(ret));
    }
    return ret;
}

4. FreeRTOS ๋ง๋ฒ„ํผ(Ring Buffer) ์ตœ์ ํ™” ๋ฐ ๋ฉ€ํ‹ฐ์ฝ”์–ด ์•„ํ‚คํ…์ฒ˜

ESP32-S3๋Š” 240MHz๋กœ ๋™์ž‘ํ•˜๋Š” ๋‘ ๊ฐœ์˜ Xtensa LX7 ์ฝ”์–ด(Core 0, Core 1)๋ฅผ ํƒ‘์žฌํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๋ฌด์„  ํŠธ๋ž˜ํ”ฝ์ด ๋ชฐ๋ฆด ๋•Œ ์ˆ˜์‹  ํŒจํ‚ท์„ ๋†“์น˜์ง€ ์•Š์œผ๋ ค๋ฉด ์ƒ์‚ฐ์ž-์†Œ๋น„์ž ํŒจํ„ด(Producer-Consumer Pattern)์„ ๊ทน๋Œ€ํ™”ํ•œ ์•„ํ‚คํ…์ฒ˜ ๊ตฌํ˜„์ด ํ•„์ˆ˜์ ์ž…๋‹ˆ๋‹ค.

4.1. Core Affinity์™€ Task ๋ถ„๋ฆฌ ์„ค๊ณ„

  • Core 0 (System Core): Wi-Fi Protocol Stack, ESP-NOW ISR, ๋ฐ Wi-Fi Driver Task ์ „๋‹ด. ์ˆ˜์‹ ๋œ ํŒจํ‚ท์€ ์ฆ‰์‹œ ๋ฉ”๋ชจ๋ฆฌ ๋ณต์‚ฌ ์ตœ์†Œํ™” ์ƒํƒœ๋กœ ๋ง๋ฒ„ํผ์— Push.
  • Core 1 (Application Core): FreeRTOS ๋ง๋ฒ„ํผ์—์„œ ๋ฐ์ดํ„ฐ๋ฅผ Pop ํ•˜์—ฌ ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค/SD์นด๋“œ ๋กœ๊น…, MQTT ์—…๋งํฌ ํ†ต์‹  ๋“ฑ ๊ณ ๋ถ€ํ•˜ ๋กœ์ง ์ฒ˜๋ฆฌ.

4.2. FreeRTOS Ring Buffer ํ™œ์šฉ ํŒจํ„ด

๊ธฐ์กด์˜ xQueueSend๋Š” ๊ตฌ์กฐ์ฒด ์ „์ฒด๋ฅผ ๋ณต์‚ฌํ•˜๋ฏ€๋กœ Overhead๊ฐ€ ํฝ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด FreeRTOS Ringbuffer ํŒจํ‚ค์ง€๋Š” ๊ฐ€๋ณ€ ๊ธธ์ด ๋ฐ ์—ฐ์† ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น(No-split mode)์„ ์ง€์›ํ•˜์—ฌ Zero-copy์— ๊ฐ€๊นŒ์šด ์ดˆ๊ณ ์† ๋ฒ„ํผ๋ง์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "freertos/ringbuf.h"

#define RING_BUFFER_SIZE (64 * 1024) // 64KB ๋Œ€์šฉ๋Ÿ‰ ๋ฒ„ํผ ํ• ๋‹น

static RingbufHandle_t xRingBuffer = NULL;

typedef struct {
    uint8_t mac_addr[6];
    uint8_t payload[250];
    uint8_t payload_len;
    int8_t rssi;
} __attribute__((packed)) sensor_packet_t;

// ESP-NOW ์ˆ˜์‹  ์ฝœ๋ฐฑ (ISR Context / High Priority Task)
void custom_esp_now_recv_cb(const esp_now_recv_info_t *recv_info, const uint8_t *data, int len) {
    sensor_packet_t packet;
    memcpy(packet.mac_addr, recv_info->src_addr, 6);
    memcpy(packet.payload, data, len);
    packet.payload_len = len;
    packet.rssi = recv_info->rx_ctrl->rssi;

    // ISR ๋˜๋Š” ์ˆ˜์‹  ์ฝœ๋ฐฑ ๋‚ด๋ถ€์—์„œ RingBuffer๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๋น ๋ฅด๊ฒŒ ๋ฐ€์–ด ๋„ฃ์Œ
    UBaseType_t res = xRingbufferSend(xRingBuffer, &packet, sizeof(sensor_packet_t), pdMS_TO_TICKS(10));
    if (res != pdTRUE) {
        // Buffer Full ์ƒํ™ฉ: ์„ฑ๋Šฅ ์ธก์ • ์นด์šดํ„ฐ ์ฆ๊ฐ€ ๋ฐ ์˜ˆ์™ธ ๋กœ๊ทธ
        // (์ฃผ์˜: ISR ๋‚ด๋ถ€์—์„œ ์ง์ ‘ Printf/ESP_LOG ํ˜ธ์ถœ ์ง€์–‘)
    }
}

// Core 1์—์„œ ์‹คํ–‰๋˜๋Š” ๋ฐ์ดํ„ฐ ์†Œ๋น„์ž ํƒœ์Šคํฌ (Consumer Task)
void packet_processing_task(void *pvParameters) {
    sensor_packet_t *item;
    size_t item_size;

    while (1) {
        // ๋ง๋ฒ„ํผ๋กœ๋ถ€ํ„ฐ ๋ฐ์ดํ„ฐ ์ธ์ถœ (Data Arrival ์‹œ๊นŒ์ง€ Blocking)
        item = (sensor_packet_t *)xRingbufferReceive(xRingBuffer, &item_size, portMAX_DELAY);
        if (item != NULL) {
            // ๋ณต์žกํ•œ ์—ฐ์‚ฐ ๋ฐ ์„ผ์„œ ๋ฐ์ดํ„ฐ ํŒŒ์‹ฑ ์ฒ˜๋ฆฌ
            // process_sensor_data(item);

            // ์‚ฌ์šฉ ํ›„ ๋ฉ”๋ชจ๋ฆฌ ๋ฐ˜ํ™˜
            vRingbufferReturnItem(xRingBuffer, (void *)item);
        }
    }
}

void app_main_init(void) {
    // RingBuffer ์ƒ์„ฑ (NOSPLIT ๋ชจ๋“œ๋กœ ๋ฐ์ดํ„ฐ ์—ฐ์†์„ฑ ๋ณด์žฅ)
    xRingBuffer = xRingbufferCreate(RING_BUFFER_SIZE, RINGBUF_TYPE_NOSPLIT);

    // Application Task๋ฅผ Core 1์— ๋ฐ”์ธ๋”ฉ
    xTaskCreatePinnedToCore(
        packet_processing_task,
        "pkt_proc_task",
        4096,
        NULL,
        10, // ๋†’์€ ์šฐ์„ ์ˆœ์œ„ ๋ถ€์—ฌ
        NULL,
        1   // Core 1
    );
}


5. ์‹ค๋ฌด ๊ฒ€์ฆ, ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๊ฒฝํ—˜ ๋ฐ ์—ฃ์ง€ ์ผ€์ด์Šค ์ฒ˜๋ฆฌ

์‹ค์ œ 100๊ฐœ ์ด์ƒ์˜ ์„ผ์„œ ๋…ธ๋“œ๊ฐ€ ๊ฐ€๋™ ์ค‘์ธ ํ™˜๊ฒฝ์—์„œ ์ ์šฉ ๋ฐ ๊ฒ€์ฆ๋œ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ…๊ณผ ๋Œ€์‘ ์ „๋žต์€ ๋‹ค์Œ๊ณผ ๊ฐ™์Šต๋‹ˆ๋‹ค.

5.1. ์—ฃ์ง€ ์ผ€์ด์Šค 1: ์ฑ„๋„ ์ „ํ™˜ ์‹ ํ˜ธ ๋ถ„์‹ค๋กœ ์ธํ•œ isolated ๋…ธ๋“œ ๋ณต๊ตฌ

๊ฒŒ์ดํŠธ์›จ์ด๊ฐ€ ์ฑ„๋„์„ 6๋ฒˆ์—์„œ 11๋ฒˆ์œผ๋กœ ๋ณ€๊ฒฝํ•  ๋•Œ, ๋ฌผ๋ฆฌ์  ์žฅ์• ๋ฌผ์ด๋‚˜ ์ˆœ๊ฐ„ ์ถฉ๋Œ๋กœ ์ฑ„๋„ ๋ณ€๊ฒฝ ํŒจํ‚ท์„ ์ˆ˜์‹ ํ•˜์ง€ ๋ชปํ•œ ๋…ธ๋“œ๋Š” ๊ตฌ ์ฑ„๋„์— ๊ณ ๋ฆฝ๋ฉ๋‹ˆ๋‹ค. ์ด๋ฅผ ๋ฐฉ์ง€ํ•˜๊ธฐ ์œ„ํ•œ Smart Scan Algorithm์„ ๋…ธ๋“œ ์ธก์— ๊ตฌํ˜„ํ–ˆ์Šต๋‹ˆ๋‹ค.

  • ๋…ธ๋“œ๋Š” ๊ฒŒ์ดํŠธ์›จ์ด๋กœ ์ „์†ก ํ›„ ESP_NOW_SEND_SUCCESS ์ƒํƒœ๋ฅผ ๋ฐ›์ง€ ๋ชปํ•˜๊ฑฐ๋‚˜, ์ฃผ๊ธฐ์ ์ธ ACK/Beacon ํŒจํ‚ท ์ˆ˜์‹ ์ด 30์ดˆ ์ด์ƒ ์ค‘๋‹จ๋˜๋ฉด Orphan Mode๋กœ ์ง„์ž…ํ•ฉ๋‹ˆ๋‹ค.
  • Orphan Mode์—์„œ๋Š” ์ฑ„๋„ 1๋ถ€ํ„ฐ 13๊นŒ์ง€ ๊ฐ ์ฑ„๋„๋‹น 100ms ๊ฐ„๊ฒฉ์œผ๋กœ Beacon Request๋ฅผ ๋ธŒ๋กœ๋“œ์บ์ŠคํŒ…ํ•ฉ๋‹ˆ๋‹ค.
  • ๊ฒŒ์ดํŠธ์›จ์ด๋Š” Orphan Beacon์„ ์ˆ˜์‹ ํ•˜๋ฉด ํ•ด๋‹น ๋…ธ๋“œ์—๊ฒŒ ํ˜„์žฌ ๋„คํŠธ์›Œํฌ ์ฑ„๋„ ์ •๋ณด๋ฅผ ๋‹ด์€ Beacon Response๋ฅผ ๋ฐ˜ํ™˜ํ•˜์—ฌ ๋ณต๊ตฌ์‹œํ‚ต๋‹ˆ๋‹ค.

5.2. ์—ฃ์ง€ ์ผ€์ด์Šค 2: ESP32-S3 Dual Core Inter-core Synchronization Issue

Core 0์—์„œ ์‹คํ–‰๋˜๋Š” ESP-NOW Rx Callback๊ณผ Core 1์˜ Consumer Task๊ฐ€ ๋™์ผํ•œ ์ „์—ญ ์ƒํƒœ ๋ณ€์ˆ˜(์˜ˆ: ์—ฐ๊ฒฐ๋œ ๋…ธ๋“œ ๋ฆฌ์ŠคํŠธ, ์ฑ„๋„ ์ƒํƒœ ๋“ฑ)๋ฅผ ์ฐธ์กฐํ•  ๋•Œ, ๋ฐ์ดํ„ฐ ๊ฒฝํ•ฉ ์กฐ๊ฑด(Data Race Condition)์œผ๋กœ ์ธํ•œ Crash๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

์ด๋ฅผ ์˜ˆ๋ฐฉํ•˜๊ธฐ ์œ„ํ•ด ํฌ๋ฆฌํ‹ฐ์ปฌ ์„น์…˜ ์ง„์ž… ์‹œ ๋‹จ์ˆœ Mutex๋ณด๋‹ค๋Š” ESP-IDF ์ „์šฉ Spinlock (portMUX_TYPE)์„ ์ ์šฉํ•˜์—ฌ ์ปจํ…์ŠคํŠธ ์Šค์œ„์นญ ์ง€์—ฐ ์—†์ด ๋ฉ”๋ชจ๋ฆฌ ์›์ž์„ฑ(Atomicity)์„ ๋ณด์žฅํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

5.3. ์„ฑ๋Šฅ ์ธก์ • ๊ฒฐ๊ณผ ๋น„๊ต (Optimization Metrics)

๊ตฌ๋ถ„ (Category) ์ตœ์ ํ™” ์ „ (Before) ์ตœ์ ํ™” ํ›„ (DCS + Ring Buffer)
ํ‰๊ท  ํŒจํ‚ท ์œ ์‹ค๋ฅ  (Packet Error Rate) 18.4% 0.2% ๋ฏธ๋งŒ
๊ฒŒ์ดํŠธ์›จ์ด ๋ฒ„ํผ ์˜ค๋ฒ„ํ”Œ๋กœ์šฐ ํšŸ์ˆ˜ ์‹œ๊ฐ„๋‹น 40~50ํšŒ ๋ฐœ์ƒ 0ํšŒ (์™„์ „ ํ•ด์†Œ)
์ตœ๋Œ€ ์ฒ˜๋ฆฌ ์Šค๋ฃจํ’‹ (Data Throughput) ~120 pkts/sec 800+ pkts/sec ์ด์ƒ ์ง€์—ฐ ์—†์ด ์ฒ˜๋ฆฌ

6. ๊ฒฐ๋ก  ๋ฐ ์š”์•ฝ

ESP32-S3 ๋ฐ ESP-NOW๋ฅผ ํ™œ์šฉํ•œ ๋Œ€๊ทœ๋ชจ ๋‹ค์  ์„ผ์„œ ๋„คํŠธ์›Œํฌ ๊ตฌ์ถ•์€ ๋›ฐ์–ด๋‚œ ๊ฐ€์„ฑ๋น„์™€ ํ™•์žฅ์„ฑ์„ ์ž๋ž‘ํ•˜์ง€๋งŒ, 2.4GHz ISM ๋Œ€์—ญ์˜ ํ˜ผ์‹ ๊ณผ ๊ฒŒ์ดํŠธ์›จ์ด ๋ณ‘๋ชฉ ๋ฌธ์ œ๋ฅผ ๊ณ ๋ คํ•˜์ง€ ์•Š์œผ๋ฉด ์‹ ๋ขฐ์„ฑ์„ ๋‹ด๋ณดํ•˜๊ธฐ ์–ด๋ ต์Šต๋‹ˆ๋‹ค.

๋ณธ ๊ฐ€์ด๋“œ์—์„œ ๋‹ค๋ฃฌ ๋™์  ์ฑ„๋„ ์Šค์œ„์นญ(DCS)์„ ํ†ตํ•ด ๋ฌด์„  ํ™˜๊ฒฝ์˜ ์žก์Œ ๋ณ€ํ™”์— ๋Šฅ๋™์ ์œผ๋กœ ๋ฐ˜์‘ํ•˜๊ณ , FreeRTOS ๋ง๋ฒ„ํผ ๊ธฐ๋ฐ˜ ๋ฉ€ํ‹ฐ์ฝ”์–ด ์ด์ค‘ํ™” Architecture๋ฅผ ํ†ตํ•ด ๋‚ด๋ถ€ ์ˆ˜์‹  ๋ณ‘๋ชฉ์„ ์™„๋ฒฝํžˆ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์œ„์™€ ๊ฐ™์€ ๊ฐ€๋™ ์ „๋žต๊ณผ ํŠธ๋Ÿฌ๋ธ”์ŠˆํŒ… ๋ฉ”์ปค๋‹ˆ์ฆ˜์„ ํ˜„์žฅ์— ์ ์šฉํ•˜์—ฌ ์‚ฐ์—…์šฉ ์ˆ˜์ค€์˜ ๋›ฐ์–ด๋‚œ ๋ฌด์„  ์„ผ์„œ ๋„คํŠธ์›Œํฌ ์ธํ”„๋ผ๋ฅผ ์„ฑ๊ณต์ ์œผ๋กœ ๊ตฌ์ถ•ํ•ด ๋ณด์‹œ๊ธฐ ๋ฐ”๋ž๋‹ˆ๋‹ค.

๋ฐ˜์‘ํ˜•