Consulting Services
إنترنت الأشياءلغة سي و متحكماتمقالات

كل ما يتعلق بـESP32 – الجزء الأول

لمحة عامة والأدوات و الليد الوامض

أجزاء سلسلة كل ما يتعلق بـESP32

متعلقات

في الربع الأخير من عام 2016 تم الإعلان عن ESP32 وفي عالم النظم المضمنة المزدحم بالكثير من الحلول والدارات الجديدة، كان على دارة ESP32 أن تنتظر في درجي حتى 2018 حتى أبدأ باكتشاف هذا الوحش الصيني.

ESP32 هي System on Chip SoC تحوي طرفيات غنيّة جداً، حيث تحصي الداتاشيت أكثر من 19 طرفية داخل هذه الآيسية إلى جانب طرفيتي البلوتوث والواي فاي. ليس هذا فقط، بل أيضاً تحوي ESP32 (نسخ محدّدة) على نواتي معالجة dual core 32-bit microprocessor. في ظل هذا التنوع الكبير كان لابد من تسمية السلسلة بـ “كل ما يتعلق بـESP32” لكثرة المميزات التي يجب اكتشافها.

لمحة عامة

 

طلب ESP32

 

تختلف إصدارات الـESP32 بالتالي:

  1. عدد الأنوية cores.
  2. وجود ذاكرة فلاش 16-Mbit داخل الآيسية.
  3. حجم الغلاف للآيسية.

 

ESP32 Part number

ESP32 Order Number

توفر الشركة المصمّمة Expressif العديد من الموديولات modules الجاهزة للاستخدام والتي تحوي آيسية ESP32 ومعها كل العناصر المتفرّقة اللازمة لعمل الآيسية، من مقاومات ومكثفات وذاكرة فلاش وذاكرة رام (بعض الموديولات) وهوائي مطبوع PCB Antenna (بعض الموديولات)، وعلى كل الأحوال يمكن مراجعة الصفحة الرسمية للموديولات المتوفرة.

Module Name
ESP32 Version
External Memories
Antenna(s)
ESP32-WROOM-32
esp-wroom-32
ESP32-D0WD4-MB flash memory
PCB antenna
ESP32-WROOM-32D
esp-wroom-32d
ESP32-D0WD4-MB flash memory
PCB antenna
ESP32-WROOM-32U
esp32-wroom-32u
ESP32-D0WD4-MB flash memory
IPEX antenna
ESP32-WROVER
esp32-wrover-1
ESP32-D0WD4-MB flash memory & 4-MB SRAM memory
PCB antenna
ESP32-WROVER-I
esp32-wrover
ESP32-D0WD4-MB flash memory & 4-MB SRAM memory
PCB antenna & IPEX antenna
ESP32-SOLO-1
esp32-solo
ESP32-S0WD4-MB flash memory PCB antenna

نجد من الجدول أعلاه (حتى هذا الوقت) أن جميع الموديولات تستخدم نفس رقم الـESP32 وهو ESP32-D0WD (باستثناء ESP32-SOLO-1 الذي يستخدم ESP32-S0WD وحيد النواة) ويبقى الشيء الذي تتمايز فيه:

  1. نوع الهوائي.
  2. وجود ذاكرة رام حجم 4 ميغا بايت من عدمه.

إن آخر شكل للـESP32 يمكن الحديث عنه هو ESP32-PICO-D4 وهو نظام داخل غلاف System-in-Package (SiP) حيث يحوي الـESP32 وأيضاً كل العناصر المطلوبة من مكثفات الفلترة والذاكرة فلاش والمهتز وتقريباً كل شيء ما عدا الهوائي.

 

الشيء الأخير الذي يجب الكلام عنه عن طلب ESP32 هو اللوحات التطويرية وهي أكثر من أن تحصى، فإما يتم استخدام دارة تطويرية من تصميم الشركة المصنعة نفسها Expressif Dev KITS أو من شركات مصممة متخصّصة معروفة مثل SparkFun ESP32 Thing أو شراء دارة تطويرية صينية رخيصة الثمن كالتي بحوزتي الآن Goouuu-ESP32 Development Board.

ميزات أساسية

 

توفر ESP32 خيارين للاتصال اللاسلكي وهما: الواي فاي 802.11 b/g/n والبلوتوث نسخة 4.2 كما أن مواصفات المعالج والذواكر المتاحة أمر مهم حيث يتوفر Xtensa single-/dual-core 32-bit LX6 microprocessor(s) مع ذواكر داخلية 448 kB ROM و 520 kB SRAM ويدعم ESP32 ذواكر خارجية بحجم 4 x 16 MB  عبر واجهة QSPI. يحوي ESP32 ذاكرة كاش ووحدات حماية وتنظيم الذاكرة MPU و MMU وذلك لتنظيم النفاذ للذواكر الداخلية والخارجية.

هذا الوحش الصيني لا يحوي طرفيات فقط بل أيضاً حساسات داخلية وهي:

  1. حساس حرارة بمجال -40°C إلى 125°C.
  2. 10 أرجل قابلة للعمل كحساسات سعوية (حساس لمس) capacitive-sensing.
  3. حساس الأثر Hall وبهذا باستخدام مغناطيس ودارة ESP32 يمكن صنع تطبيق تحسس لحالة الباب.

لتعداد بعض الطرفيات الأخرى المتاحة:

  1. 34 دخل/خرج.
  2. 18 قناة للتحويل التماثلي الرقمي ADC بدقة 12 بت.
  3. قناتين للتحويل الرقمي التماثلي DAC بدقة 8 بت.
  4. واجهة إيثرنت Ethernet MAC.
  5. SD/SDIO/MMC host controller
  6. SDIO/SPI Slave Controller
  7. ثلاث وجهات تسلسلية UART.
  8. واجهتين I2C.
  9. واجهتين I2S.
  10. ثماني أقنية لاستقبال وإرسال الإشارة IR.
  11. عدّاد نبضات.
  12. Pulse Width Modulation (PWM)
  13. متحكم النفاذ المباشر للذاكرة DMA.
  14. مجموعتي عدادات. كل مجموعة 2 x 64-bit.

نهايةً، إن مصممي ESP32 قد أبدوا انتباهاً جيداً لموضوع توفير الطاقة والذي شمل تضمين متحكم خاص للعمل في نمط التوفير الأقصى ultra-low-power processor وسموه ULP co-processor ويحوي ذاكرة رام بحجم 8 كيلو بايت للبيانات والتعليمات معاً. هذا المعالج المساعد له بيئته التطويرية الخاصة من ناحية الأدوات والـtoolchain ولمزيد من المعلومات يمكن التحقق من الدليل الرسمي.

 

الأدوات البرمجية Toolchain

 

يتوفر لبرمجة الـESP32 وكسابقتها ESP8266 خيارين أساسيين وهما استخدام حزمة أدوات التطوير(كيت) الرسمية من الشركة official SDK أو استخدام نواة الأردوينو لـESP32 على الرغم أن نواة الأردوينو فعلياً مكتوبة باستخدام الكيت التطويري الرسمي ولكن مع توفير طبقة تجريد للمطوّر.

اخترتُ في هذه السلسلة الكيت التطويري الرسمي لكثير من الأسباب المتعلقة بالأداء والبعد عن المشاكل البرمجية ولتحقيق فهماً أعمق. خلافاً لـESP8266 فإن ESP32 لا توفر كيت تطويري مع/بدون نظام RTOS وإنما نظام FreeRTOS معتمد بشكل أساسي في هذه الكيت التطويرية. إن الاسم الرسمي لهذه الكت التطويرية هو ESP-IDF (Espressif IoT Development Framework)، ومما لا شك فيه أنه يوجد العديد من الخيارات الأخرى لكتابة البرنامج بلغات أخرى مثل الجافا سكربت أو البايثون وفي صفحة الـESP32 بموقع الويكيبيديا قائمة جيدة حول هذه الخيارات.

إنه من غير المجدي إعادة كتابة خطوات تحميل وتهيئة سلسلة الأدوات toolchain  والـ ESP-IDF فهي موثّقة بشكل جيد جداً رسمياً، وكتأكيد يجب أن يكون في حاسب القارئ:

  1. سلسلة الأدوات toolchain.
  2. الـ ESP-IDF من مستودع Expressif.

إن الخرج التالي يجب أن يظهر بعد تنزيل وتهيئة ناجحة لما سبق عبر إرسال الأوامر التالية عبر التيرمينال في لينكس أو MinGW في الويندوز الموجود داخل ESP-IDF:

  • Command: echo $IDF_PATH
    Output: \your\path\to\esp-idf
  • Command: printenv PATH
    Output: /home/user-name/esp/xtensa-esp32-elf/bin

 

الليد الوامض Blinking LED

 

لأخذ قالب جاهز لمشروع ESP32، فإننا ننسخ مشروع من الأمثلة المتاحة في ESP-IDF وذلك باستخدام التعليمة الخاصة بإنشاء مجلد للمشاريع وثم نسخ المشروع إليه باسم جديد وهو first_app.

mkdir esp32-workspace

cp -r $IDF_PATH/examples/get-started/hello_world esp32-workspace/first_app

لنفهم بداية وقبل تعلم كيفية بناء الكود وبرمجته على ESP32 كيفية كتابة الكود الأول لتحقيق ليد وامض.

ملفات الترويس

 

#include "freertos/FreeRTOS.h"

#include "freertos/task.h"

يستخدم الكود تابع من الـFreeRTOS، لذلك يلزمنا الملفين السابقين إضافة إلى الملف التالي والذي يحوي توابع للتعامل مع الدخل/الخرج GPIO.

#include "driver/gpio.h"

 

التابع app_main

 

هذا التابع هو التابع الرئيسي الذي يحوي البرنامج. طالما أن ESP-IDF تستخدم FreeRTOS، فإنه يمكننا إنشاء اجرائية task خاصة بعملية الوميض. يتم إنشاء هذه الإجرائية باستدعاء التابع xTaskCreate. قد لا يكون القارئ مطلعاً على FreeRTOS لذلك كلما أحتجنا لشيء معين منه يتم شرحه في وقته ولنبدأ بـ xTaskCreate والذي له التعريف التالي وأقتبس هنا من دليل FreeRTOS الرسمي reference manual :

BaseType_t xTaskCreate( TaskFunction_t pvTaskCode,
const char * const pcName,
unsigned short usStackDepth,
void *pvParameters,
UBaseType_t uxPriority,
TaskHandle_t *pxCreatedTask );

This function creates a new instance of a task, and takes the following parameters:

  • pvTaskCode: Tasks are simply C functions that never exit and, as such, are normally implemented as an infinite loop. The pvTaskCode parameter is simply a pointer to the function (in effect, just the function name) that implements the task.
  • pcName: A descriptive name for the task. This is mainly used to facilitate debugging, but can also be used in a call to xTaskGetHandle() to obtain a task handle.
  • usStackDepth: Each task has its own unique stack that is allocated by the kernel to the task when the task is created. The usStackDepth value tells the kernel how large to make the stack.
  • pvParameters: Task functions accept a parameter of type ‘pointer to void’ ( void* ). The value assigned to pvParameters will be the value passed into the task.
  • uxPriority: Defines the priority at which the task will execute. Priorities can be assigned from 0, which is the lowest priority, to (configMAX_PRIORITIES – 1), which is the highest priority.
  • pxCreatedTask: pxCreatedTask can be used to pass out a handle to the task being created.

باختصار يهمنا وسيط واحد بشكل خاص وهو أول وسيط، أي اسم التابع الذي سيتم استدعاءه من قبل المجدول الخاصة بنظام التشغيل كلّما حان وقت التنفيذ الخاص به وأيضاً الوسيط الثاني وهو اسم الإجرائية ولكن ليس لها أي تأثير حالياً ولا تهمنا.

xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);

 

تابع blink_task

 

void blink_task(void *pvParameter)

{
    gpio_pad_select_gpio(BLINK_GPIO);

    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);

    while(1) {
       gpio_set_level(BLINK_GPIO, 0);

       vTaskDelay(1000 / portTICK_PERIOD_MS);
       gpio_set_level(BLINK_GPIO, 1);
       vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

إن كود هذا التابع سهل ومباشر كأي كود تعامل مع مداخل/مخارج، حيث يتضمن اختيار رقم الرجل والنمط وسوية الخرج وكل هذا عبر توابع من ESP-IDF.

لنرَ الآن ما مهمّة الـ vTaskDelay وسأقتبس مرة أخرى من الدليل الرسمي للـFreeRTOS :

“vTaskDelay Places the task that calls vTaskDelay() into the Blocked state for a fixed number of tick interrupts”. portTICK_PERIOD_MS is macro for the period of each tick in mS, so for  1000mS delay, we need 1000/portTICK_PERIOD_MS of ticks.

وبالتالي هو مسؤول عن نقل الإجرائية إلى حالة الانتظار لمدة تساوي عدد عدّات معين ولتوليد تأخير 1000 ميلي ثانية فإن عدد العدّات يساوي 1000 تقسيم زمن العدّة الواحدة بالميلي ثانية وهو ثابت موجود في النظام.

 

لنرَ الآن المثال كاملاً:

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

#define BLINK_GPIO 1

void blink_task(void *pvParameter)
{
    gpio_pad_select_gpio(BLINK_GPIO);

    gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);

    while(1) {

       gpio_set_level(BLINK_GPIO, 0);

       vTaskDelay(1000 / portTICK_PERIOD_MS);

       gpio_set_level(BLINK_GPIO, 1);

       vTaskDelay(1000 / portTICK_PERIOD_MS);

    }
}

void app_main()
{
    xTaskCreate(&blink_task, "blink_task", configMINIMAL_STACK_SIZE, NULL, 5, NULL);
}
هناك نمط تسمية محدد متبع في FreeRTOS كما ورد في كتاب FreeRTOS Real Time Kernel A Hands-On Tutorial Guide حيث: “يبدأ اسم التوابع بمحرف يدل على نوع القيمة التي يرجعها التابع” أي مثلاً: لو بدأ اسم التابع بـ v فهو يعني من النوع void ولو بدأ بـ x فهو من النوع BaseType_t ولو بدأ بـ pv فإنه يعيد مؤشر من نوع pointer to void.

 

بناء الكود

 

يجب وضع الكود السابق في المسار التالي first_app/main/first_app_main.c ويجب أن يكون الـ terminal مشير للمجلد first_app. إن الأمر التالي make سيؤدي إلى تشغيل واجهة رسومية بسيطة:

ESP32 make menuconfig

توفر هذه الواجهة الكثير من الخيارات والتي سنكتشفها تباعاً لاحقاً ولكن ما يهمنا الآن هو تحديد اسم ورقم المنفذ الموصول إليه الدارة وذلك من أجل البرمجة. من الممكن حفظ الإعدادات من أجل اختصار هذه الخطوة في عملية البناء القادمة. تم توضيح هذه الخطوات في التسجيل التالي:

خيار آخر متاح لبناء وبرمجة الدارة مباشرة هو “make flash” ولإرغام الواجهة الرسومية للظهور مجدداً  “make menuconfig”.

قد يُلاحظ بطء في عملية البناء وخاصة في أجهزة الويندوز. يمكن استخدام حل مقترح لتسريع العمليّة قليلاً وهو تفعيل التنفيذ التفرعي لعملية البناء عبر الخيار -j مثال: make -j5

تبدو عملية بناء وبرمجة صحيحة كما يلي:

ESP32 Flashing

 

اقرأ أكثر

 

هذا كل ما هنالك في هذا الجزء نلتقي في الجزء الثاني. في هذه الأثناء أنصح القرّاء بالاطلاع على كتاب كولبان Kolban’s Book on ESP32 وكما هو مذكور في مقدمة الكتاب، فهو دفتر ملاحظات أكثر من كونه كتاب ولكن يحوي على ملاحظات قيّمة ومتنوعة وتقريباً حول كل شيء يتعلق بالـESP32  مع شرح لكثير من الأساسيات. مرجع آخر يُنصح به بشدة وهو سلسلة موجودة في موقع آخر وأيضاً تناقش تقريباً كل شيء عن ESP32 وباستخدام الـESP-IDF. يبقى أخيراً المرجع الأساسي رفيق الدرب الرئيسي في تعلّم الـ ESP-IDF.

 

أجزاء سلسلة كل ما يتعلق بـESP32

متعلقات

Yahya Tawil

مؤسس عتاديات وأسعى لدعم المحتوى العربي عن النظم المضمنة في الويب العربي. خبرتي في مجال النظم المضمّنة تتركز في كتابة البرامج المضمنة وتصميم الدارات المطبوعة والمخططات وإنشاء المحتوى.

اترك تعليقاً

لن يتم نشر عنوان بريدك الإلكتروني. الحقول الإلزامية مشار إليها بـ *

هذا الموقع يستخدم Akismet للحدّ من التعليقات المزعجة والغير مرغوبة. تعرّف على كيفية معالجة بيانات تعليقك.

زر الذهاب إلى الأعلى