الرئيسية قاعدة المعرفة الكهرباء والإلكترون ESP32 والاتصال اللاسلكي: مستشعر ذكي متصل بالشبكة
الكهرباء والإلكترون

ESP32 والاتصال اللاسلكي: مستشعر ذكي متصل بالشبكة

ESP32: متحكم مع WiFi و Bluetooth مدمج

ESP32 من Espressif هو متحكم ثنائي النواة (Xtensa LX6) بتردد حتى 240 MHz، مع WiFi 802.11 b/g/n و Bluetooth مدمجين في الشريحة نفسها. هذا يجعله مثالياً لتطبيقات إنترنت الأشياء الصناعي (IIoT) حيث تحتاج وحدات مراقبة ترسل بيانات المستشعرات للسحابة.

المواصفات الرئيسية

  • المعالج: نواتان Xtensa LX6 @ 240 MHz
  • RAM: 520 KB SRAM
  • Flash: خارجي 4-16 MB
  • WiFi: 802.11 b/g/n حتى 150 Mbps
  • Bluetooth: Classic + BLE 4.2
  • الطرفيات: 34 GPIO, 18 ADC, 2 DAC, 4 SPI, 2 I2C, 3 UART
  • الاستهلاك: 80 mA عادي، 10 uA في النوم العميق

ESP32-S3 و ESP32-C3

الإصدارات الأحدث تضيف ميزات مهمة:

  • ESP32-S3: يدعم USB أصلياً ومسرّع AI لتشغيل نماذج TinyML
  • ESP32-C3: نواة RISC-V واحدة بسعر أقل، مثالي لعقد IoT البسيطة

إعداد بيئة التطوير: ESP-IDF أو Arduino

ESP-IDF (الإطار الرسمي)

ESP-IDF هو إطار التطوير الرسمي من Espressif، مبني على FreeRTOS. يوفر تحكماً كاملاً بكل ميزات الشريحة. مناسب للمشاريع الصناعية الجادة.

# تثبيت ESP-IDF على Linux/macOS
mkdir -p ~/esp && cd ~/esp
git clone --recursive https://github.com/espressif/esp-idf.git
cd esp-idf && ./install.sh esp32
source export.sh

Arduino Framework

أبسط وأسرع للنماذج الأولية. يعمل فوق ESP-IDF ويوفر واجهة Arduino المألوفة. لكنه يخفي تفاصيل قد تحتاجها في التطبيقات الصناعية.

الاتصال بشبكة WiFi

// الاتصال بشبكة WiFi باستخدام ESP-IDF
#include "esp_wifi.h"
#include "esp_event.h"
#include "nvs_flash.h"

#define WIFI_SSID      "Factory_Network"
#define WIFI_PASSWORD   "secure_password"

static void wifi_event_handler(void *arg, esp_event_base_t base,
                               int32_t id, void *data) {
    if (base == WIFI_EVENT && id == WIFI_EVENT_STA_DISCONNECTED) {
        esp_wifi_connect();  // إعادة الاتصال تلقائياً
    }
}

void wifi_init(void) {
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    esp_netif_create_default_wifi_sta();

    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);

    esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID,
                               wifi_event_handler, NULL);

    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASSWORD,
            .threshold.authmode = WIFI_AUTH_WPA2_PSK,
        },
    };

    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
    esp_wifi_connect();
}

إعادة الاتصال التلقائي

في البيئة الصناعية، انقطاع WiFi متوقع. يجب أن يعيد النظام الاتصال تلقائياً مع تأخير متزايد (Exponential Backoff) لتجنب إغراق نقطة الوصول:

static int retry_count = 0;

static void wifi_event_handler(void *arg, esp_event_base_t base,
                               int32_t id, void *data) {
    if (id == WIFI_EVENT_STA_DISCONNECTED) {
        int delay_ms = (1 << retry_count) * 1000;
        if (delay_ms > 30000) delay_ms = 30000;
        vTaskDelay(pdMS_TO_TICKS(delay_ms));
        esp_wifi_connect();
        retry_count++;
    } else if (base == IP_EVENT && id == IP_EVENT_STA_GOT_IP) {
        retry_count = 0;
    }
}

بروتوكول MQTT: لغة إنترنت الأشياء الصناعي

MQTT (Message Queuing Telemetry Transport) بروتوكول خفيف مصمم للأجهزة محدودة الموارد والشبكات غير المستقرة. يعمل بنموذج النشر/الاشتراك (Publish/Subscribe):

  • الناشر (Publisher): يرسل رسالة إلى موضوع (Topic)
  • المشترك (Subscriber): يستقبل رسائل من موضوعات يتابعها
  • الوسيط (Broker): خادم يوزّع الرسائل (مثل Mosquitto أو EMQX)

هيكل المواضيع الصناعي

factory/line1/motor1/temperature
factory/line1/motor1/current
factory/line1/motor1/status
factory/line1/motor1/command

مستويات جودة الخدمة (QoS)

  • QoS 0: إرسال مرة واحدة بدون تأكيد (أسرع)
  • QoS 1: تأكيد الاستلام مع إمكانية التكرار
  • QoS 2: توصيل مرة واحدة بالضبط (أبطأ وأثقل)

للبيانات الدورية (حرارة كل ثانية)، QoS 0 كافٍ. للأوامر الحرجة (إيقاف محرك)، استخدم QoS 1.

إرسال بيانات المستشعرات للخادم عبر MQTT

#include "mqtt_client.h"
#include "cJSON.h"

esp_mqtt_client_handle_t mqtt_client;

void mqtt_init(void) {
    esp_mqtt_client_config_t cfg = {
        .broker.address.uri = "mqtt://192.168.1.100:1883",
        .credentials.username = "iiot_node_01",
        .credentials.authentication.password = "secure_token",
        .session.keepalive = 30,
    };
    mqtt_client = esp_mqtt_client_init(&cfg);
    esp_mqtt_client_start(mqtt_client);
}

void publish_sensor_data(float temp, float current, float pressure) {
    cJSON *root = cJSON_CreateObject();
    cJSON_AddNumberToObject(root, "temperature", temp);
    cJSON_AddNumberToObject(root, "current", current);
    cJSON_AddNumberToObject(root, "pressure", pressure);
    cJSON_AddNumberToObject(root, "timestamp", esp_timer_get_time() / 1000);

    char *json_str = cJSON_PrintUnformatted(root);
    esp_mqtt_client_publish(mqtt_client,
        "factory/line1/pump1/telemetry",
        json_str, 0, 1, 0);  // QoS 1

    free(json_str);
    cJSON_Delete(root);
}

استقبال أوامر من الخادم

static void mqtt_event_handler(void *arg, esp_event_base_t base,
                                int32_t id, void *data) {
    esp_mqtt_event_handle_t event = data;
    if (event->event_id == MQTT_EVENT_DATA) {
        char topic[128];
        snprintf(topic, sizeof(topic), "%.*s", event->topic_len, event->topic);

        if (strcmp(topic, "factory/line1/pump1/command") == 0) {
            cJSON *cmd = cJSON_Parse(event->data);
            if (cmd) {
                int speed = cJSON_GetObjectItem(cmd, "speed")->valueint;
                motor_set_speed(speed);
                cJSON_Delete(cmd);
            }
        }
    }
}

مثال عملي: عقدة IIoT تقرأ حرارة ورطوبة وترسلها كل 10 ثوانٍ

#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "esp_log.h"

#define LED_STATUS   GPIO_NUM_2
#define SENSOR_POWER GPIO_NUM_4

static const char *TAG = "IIoT_Node";

void sensor_task(void *p) {
    (void)p;
    while (1) {
        gpio_set_level(LED_STATUS, 1);

        float temp = read_ntc_temperature();
        float humidity = read_dht22_humidity();
        float voltage = read_battery_voltage();

        publish_sensor_data(temp, humidity, voltage);

        ESP_LOGI(TAG, "Sent: T=%.1fC H=%.1f%% V=%.2fV",
                 temp, humidity, voltage);
        gpio_set_level(LED_STATUS, 0);

        vTaskDelay(pdMS_TO_TICKS(10000));
    }
}

void watchdog_task(void *p) {
    (void)p;
    while (1) {
        if (!wifi_is_connected()) {
            ESP_LOGW(TAG, "WiFi lost, reconnecting...");
            esp_wifi_connect();
        }
        if (!mqtt_is_connected()) {
            ESP_LOGW(TAG, "MQTT lost, reconnecting...");
            esp_mqtt_client_reconnect(mqtt_client);
        }
        vTaskDelay(pdMS_TO_TICKS(5000));
    }
}

void app_main(void) {
    gpio_set_direction(LED_STATUS, GPIO_MODE_OUTPUT);
    gpio_set_direction(SENSOR_POWER, GPIO_MODE_OUTPUT);
    gpio_set_level(SENSOR_POWER, 1);

    wifi_init();
    vTaskDelay(pdMS_TO_TICKS(3000));
    mqtt_init();

    esp_mqtt_client_subscribe(mqtt_client,
        "factory/line1/pump1/command", 1);

    xTaskCreate(sensor_task,   "sensor",   4096, NULL, 5, NULL);
    xTaskCreate(watchdog_task, "watchdog", 2048, NULL, 3, NULL);
}

الخلاصة

ESP32 مع MQTT يشكّلان أساس عقد إنترنت الأشياء الصناعي. القدرة على إرسال بيانات المستشعرات واستقبال أوامر التحكم عبر WiFi تفتح آفاقاً واسعة للمراقبة عن بعد والصيانة التنبؤية. في الدرس الأخير سنبني مشروعاً صناعياً متكاملاً يجمع كل ما تعلمناه.

ESP32 WiFi MQTT IIoT wireless sensor-node المتحكم اللاسلكي واي فاي عقدة المستشعر إنترنت الأشياء الاتصال البيانات