Перейти к содержимому

Настройка Arduino IDE для работы с ESP32

Метки:

Доброго здравия, уважаемые читатели!

Из данного сумбурного текста вы сможете узнать как:

  • настроить Arduino IDE для работы с микроконтроллерами семейства ESP32
  • как правильно выбрать подходящую плату из списка предложенных
  • как выбрать разметку flash-памяти под ваши задачи
  • на что влияют те или иные опции в параметрах выбранной платы

То есть всё то, что необходимо сделать перед тем, как вы начнете создавать свой первый скетч для ESP32. 

Дисклеймер
1. Скриншоты и примеры сделаны на основе Arduino IDE 2 версии 2.3. Версию ветки 1.x я не рассматривал, но там все очень похоже.
2. Со временем некоторая информация может устареть из-за того, что выходят новые версии ПО, плат, чипов и т.д. В мире программирования все меняется слишком быстро. Учитывайте это и сверяйтесь с официальной документацией.

Предупреждение! С некоторых пор разработчики Arduino IDE ( сайт arduino.cc и все что с ним связано ) добавили бан по российским IP-адресам. Произошло это видимо после того, как Arduino был продан компании Qualcomm (ноябрь 2025 года). Поэтому Arduino IDE может не загружаться при запуске, зависать на загрузке пакетов и библиотек. В этом случае вам придется либо искать обходные пути самостоятельно, либо перейти на более профессиональную IDE: Visual Studio code + ESP-IDF + Arduino32 as component, которую пока что можно скачать совершенно свободно.

Оглавление

 


Добавляем ссылку на менеджер плат ESP32

Прежде всего нужно добавить официальный пакет плат от Espressif в IDE, если это не было сделано ранее.

Для чего это нужно? Установка пакета плат от Espressif по сути означает установку в Arduino IDE специального «ядра» Arduino core и «инструментария» toolchain, созданного именно для SoC ESP32. Это позволяет IDE распознавать чип ESP32, компилировать код для него и прошивать его. Arduino IDE изначально поддерживает только архитектуру AVR (как у Arduino Uno), а ESP32 построен на архитектуре Xtensa или RISC-V. Их наборы инструкций полностью несовместимы. Поэтому вам нужно установить через менеджер плат «переводчика» и «инструментарий» — это и есть пакет поддержки ESP32. 

Этот процесс выполняет несколько ключевых задач:

  • Установка специализированного компилятора: загружается необходимый инструментарий (например idf.py, xtensa-esp32-elf-gcc), который преобразует ваш скетч Arduino в машинный код, понятный ESP32.
  • Добавление базовых библиотек: предоставляет API для работы с аппаратными возможностями ESP32 (GPIO, Wi-Fi, Bluetooth). Например, когда вы вызываете digitalWrite(), ядро переводит этот вызов в соответствующий вызов esp_gpio API, а тот, в свою очередь – в операцию с регистрами ESP32.
  • Встраивание инструмента для прошивки: включает утилиты типа esptool.py, которые при прошивке через последовательный порт записывают скомпилированную программу во флеш-память ESP32.

 

1. Для этого открываем параметры Arduino IDE через меню Файл → Параметры:

2. В открывшемся окне найдите строку “Дополнительные ссылки для менеджера плат” и кликните по кнопке справа от нее:

3. В редакторе ссылок добавьте одну из приведенных ниже ссылок. Я рекомендую первую (стабильный релиз), но если у вас какая-то супер-новая плата, можно попробовать и пре-релиз.

Стабильный релиз (рекомендуется):

https://espressif.github.io/arduino-esp32/package_esp32_index.json

Релиз для разработчиков (последние обновления, пре-релиз):

https://espressif.github.io/arduino-esp32/package_esp32_dev_index.json

Если в списке у вас уже есть ссылка (например для ESP8266) – добавляем новую на другой строке. Не забываем сохранить внесенные изменения кнопкой “ОК“. И еще раз “ОК” для сохранения всех параметров.

4. После добавления ссылки откройте Инструменты → Плата → Менеджер плат, найдите esp32 by Espressif Systems и нажмите Установить.

Теперь нужно подождать – установка может занять около 10 минут. Дожидаемся сообщения “Платформа esp32:esp32@версия установлена“:

Добавить пакет с платами ESP в менеджер было легко и просто. И теперь Arduino IDE полностью готово к работе с SoC ESP32 и платами на его основе.


Выбираем плату (модуль) ESP32

Теперь нужно выбрать плату, с которой мы будем работать. Откройте меню Инструменты → Плата → esp32 → … и вы увидите огромный список поддерживаемых плат. Какую же из них выбрать? Здесь все зависит от того, какая плата у вас имеется в наличии. В большинстве случаев можно ограничится списком Dev Module, в зависимости от серии вашего SoC (ESP32 / ESP32C5 / ESP32C6 / ESP32S2 / ESP32S3 и т.д.), но есть нюансы

Чтобы понять, для чего важно правильно выбрать плату, необходимо понять, что при этом происходит. При выборе той или иной платы Arduino IDE настраивает следующие параметры:

  • Ядро компилятора — какой набор библиотек и инструментов использовать
  • Метод прошивки — протокол, скорость, максимальный размер
  • Метод отладки — инструмент (JTAG), скрипты OpenOCD, уровень оптимизации
  • Карту выводов (pin mapping) — как физические пины называются в коде (макросы)
  • Параметры памяти — FLASH, PSRAM, размер, частота, режим
  • Аппаратные возможности — Bluetooth, USB CDC, PSRAM и т.д.

Если вы выберете “неправильную” плату, все эти параметры станут неверными, и вы можете получить ошибки компиляции, проблемы с прошивкой, неработающие пины или отладку.

Параметры плат

Для ОС Windows все эти параметры для пакета esp32 by Espressif Systems хранятся в файле %USER_PROFILE%\AppData\Local\Arduino15\packages\esp32\hardware\esp32\%version%\boards.txt. Карты пинов и прочие настройки конкретных платы хранятся в соответствующем подкаталоге ...\Arduino15\packages\esp32\hardware\esp32\%version%\variants. Для Linux путь очень похож: $HOME/Arduino15/packages/esp32/hardware/esp32/%version%/boards.txt.

Что там может быть задано:

  • Базовые параметры платы
    Эти параметры определяют, как именно будет собираться ваш код:

    • build.board – внутренний идентификатор платы для системы сборки, например: ESP32_DEV
    • build.core – указывает, какое ядро Arduino использовать, например: esp32
    • build.mcu  – тип (серия) микроконтроллера для компилятора, например: esp32, esp32s2, esp32s3
    • build.variant – путь к папке с файлом pins_arduino.h, который определяет карту выводов, например: lolin_s2_mini
    • build.f_cpu – тактовая частота процессора “по умолчанию” в Гц, например: 240000000L, 160000000L
  • Методы прошивки (загрузки двоичного кода)
    Эти параметры определяют, КАК программа будет загружаться на плату:

    • upload.protocol – протокол загрузки прошивки: espota (OTA), esptool (UART), jtag
    • upload.speed – скорость последовательного порта при загрузке: 921600, 115200
    • upload.port – порт по умолчанию (обычно оставляют пустым)
    • upload.maximum_size – максимальный размер загружаемой прошивки, например: 1310720 (1.25MB)
    • upload.offset_apps – смещение приложений на флеш-памяти, по умолчанию 0x10000
    • upload.erase_flash – стереть всю флеш-память перед загрузкой: all
  • Методы отладки
    Эти параметры определяю то, как будем отлаживать прошивку:

    • debug_tool – инструмент для отладки (JTAG): cmsis-dap, jlink, ftdi
    • debug.svd – файл SVD (System View Description) для отладки регистров: esp32.svd
    • build.openocd_scripts – путь к скриптам OpenOCD для отладки: esp32.cfg
    • build.debug_format – формат отладочной информации: elf
    • build.extra_flags – дополнительные флаги для компилятора для включения отладки: -DDEBUG -g3
    • build.optimize – уровень оптимизации (влияет на возможность отладки): debug (без оптимизации), release (с оптимизацией)
    • build.lto_enable – включить Link-Time Optimization (мешает отладке, но уменьшает размер): 1 (вкл), 0 (выкл)
  • Параметры falsh-памяти и хранения прошивки
    Эти параметры очень важны — от них зависит, поместится ли ваш код и как будет организована память:

    • build.flash_size – размер флеш-памяти: 4MB, 8MB, 16MB
    • build.flash_mode – режим работы флеш-памяти (скорость и количество линий): qio, dio, opi
    • build.flash_freq – частота работы флеш-памяти: 80m, 40m
    • build.psram_type – тип внешней PSRAM (если есть): qspi, ospi
    • build.psram_enable – включает поддержку PSRAM: 1 (вкл), 0 (выкл)
    • build.bt_enable – включает поддержку Bluetooth (экономит память, если отключить): 1 (вкл), 0 (выкл)
    • build.esp_efuse_enable – включает работу с eFuse (энергонезависимая память для ключей): 1 (вкл), 0 (выкл)
  • Аппаратные интерфейсы и выводы
    Настройка того, какие аппаратные возможности доступны и как они привязаны к пинам:

    • build.variant – путь к файлу pins_arduino.h — это карта всех выводов платы
    • build.USB_CDC – включает эмуляцию Serial через USB (для плат с USB): 1 (вкл), 0 (выкл)
    • build.USB_MSC – включает режим USB Mass Storage (плата видна как диск): 1 (вкл), 0 (выкл)
    • build.USB_DFU – включает поддержку DFU (Device Firmware Upgrade): 1 (вкл), 0 (выкл)

Пример параметров для ESP32 Dev Module:

esp32.esp32.esp32.name=ESP32 Dev Module

# Базовые параметры
esp32.esp32.esp32.build.board=ESP32_DEV
esp32.esp32.esp32.build.core=esp32
esp32.esp32.esp32.build.mcu=esp32
esp32.esp32.esp32.build.variant=esp32
esp32.esp32.esp32.build.f_cpu=240000000L

# Параметры памяти
esp32.esp32.esp32.build.flash_size=4MB
esp32.esp32.esp32.build.flash_mode=qio
esp32.esp32.esp32.build.flash_freq=80m
esp32.esp32.esp32.build.psram_type=disabled

# Прошивка
esp32.esp32.esp32.upload.protocol=esptool
esp32.esp32.esp32.upload.speed=921600
esp32.esp32.esp32.upload.maximum_size=1310720

# Отладка
esp32.esp32.esp32.debug_tool=jlink
esp32.esp32.esp32.build.openocd_scripts=interface/ftdi/esp32_devkitj_v1.cfg
esp32.esp32.esp32.build.debug_format=elf

Эти параметры не обязательно установлены “раз и навсегда”, некоторые из них можно будет изменить в интерфейсе – это мы обсудим в следующем разделе.

 

Как выбрать правильную плату?

Так как же выбрать “правильную” плату, если вам не известно её название?

Если вам известен производитель и точное название платы, то все проще простого – просто выберите его из списка. Например легко узнать ESP32DevKit, Ai Thinker ESP32 CAM или Node32s. Некоторые модели вы найдете в списке ниже.

Если вы не уверены, какую плату выбрать, то в первую очередь определитесь с семейством – ESP32 / ESP32C5 / ESP32C6 / ESP32S2 / ESP32S3 и т.д. – это самое важное. Причем здесь может быть “подстава” от некоторых производителей – например модуль с маркировкой ESP32-S на самом деле обычный ESP32 (а не ESP32S2 / ESP32S3, как можно подумать), только производства Ai Thinker. При необходимости “опросите” модуль с помощью кабеля.

Определившись с типом модуля, можно выбрать соответствующий Dev Module – но это чревато тем, что многие параметры придется выбирать вручную; а список “определений” выводов очень небольшой (и некоторое выводы могут быть уже заняты установленным на плате оборудованием). В итоге: Dev Module – это вариант, который подойдет почти всегда, но может потребовать значительной “доработки напильником”.

 

Примеры плат

Некоторые широко популярные платы вы можете опознать по фотографиям – их названия указаны из списка boards.txt.

NodeMCU-32S

ESP32 Dev Module

ESP32S3 Dev Module

AI Thinker ESP32-CAM

WEMOS D1 R32

WT32-ETH01


Настройка параметров выбранной платы

Хорошо, плату выбрали. Теперь нужно определиться с её параметрами. У разных плат может этот список может сильно отличаться, но самый большой список параметров по определению – у плат типа Dev Module. Поэтому по ним и стоит пройтись, для примера я взял плату на основе ESP32-S3.

Список настроек платы ESP32S3 Dev Module

Стандартные опции плат Espressif

Не все перечисленные ниже опции могут быть показаны для вашей платы. Некоторые специфичны только для отдельных серий чипов, некоторые – для отдельных плат. Но список приведен полностью на текущий момент, дабы вы смогли найти нужную опцию при необходимости.

Upload Speed (UploadSpeed)

Задает скорость передачи данных при прошивке через последовательный порт, влияет на время загрузки и стабильность. Высокие значения (до 921600) быстрее, но могут вызывать ошибки при плохом качестве соединения. Если вы видите ошибки при прошивке, попробуйте снизить это значение. Возможны варианты от 115200 до 921600.

 

USB Mode (USBMode)

Режим работы USB-интерфейса. Определяет, как плата взаимодействует с компьютером через USB: как виртуальный COM-порт, как устройство ввода и т.д. Здесь два варианта:

  • Hardware CDC and JTAG — родной и самый простой способ подключения, рекомендуется для начинающих. Он работает “из коробки” на аппаратном уровне самого чипа. Ваша плата притворяется обычным USB-устройством, которое сразу видно в системе как виртуальный COM-порт (точно также, как это обычно происходит у обычных Arduino с чипом USB-UART). Но если ваша программа “упадет” или “зависнет”, плата может перестать отвечать по USB, и для следующей загрузки её придется перевести в режим загрузки вручную, зажав кнопку BOOT и сбросить.
  • USB-OTG (TinyUSB) — это более продвинутый «программируемый» USB-порт, который настраивается уже в самой прошивке. Требует библиотеку TinyUSB. Здесь Вы сами в коде  прошивки решаете, кем ей быть: виртуальным COM-портом, мышкой, клавиатурой, флешкой или даже хостом для подключения другого USB-устройства. Это дает гибкость и надежность после загрузки прошивки. Плата становится более “живучей” — даже если скетч упадет, порт для перепрошивки часто остается доступным. Но сложнее, особенно  для новичков. И для первой прошивки, скорее всего, все равно прошить плату обычным способом. Также есть шанс, что после обновления прошивки номер COM-порта в системе может измениться, что может запутать.

 

USB CDC On Boot (CDCOnBoot)

Эта опция определяет, когда этот виртуальный порт CDC становится активным: сразу при включении платы или только после того, как загрузится ваша программа. Здесь два варианта:

  • Enabled (Включено) — “Всегда готов к общению”. Это самый простой и удобный режим для большинства пользователей. Как только вы подаете питание на плату (или подключаете USB-кабель), USB-порт сразу становится активным и видимым в системе как COM-порт. Это происходит даже до того, как начнет выполняться ваш скетч. Вы всегда видите порт в Arduino IDE, даже если программа еще не загружена или “упала”. Можно легко перепрошить плату без нажатия кнопки BOOT — просто нажали “Загрузить”, и IDE сама подключится.
    Подвох: Плата тратит немного энергии на поддержание USB-соединения даже в момент запуска. Для батарейных устройств это может быть очень критично. Или если вам катастрофически не хватает пинов и вы готовы пожертвовать USB-портом.
  • Disabled (Отключено) — “Порт появится только в программе”. Этот режим требует, чтобы вы сами в коде включили USB-порт. Он не активен во время загрузки и перезагрузки. Он станет видимым для компьютера только после того, как загрузится ваш скетч и вызовет функцию инициализации USB (обычно Serial.begin() в setup()). Это дает два преимущества: экономия энергии (USB-порт не тратит ток, пока не понадобится) и можно использовать USB-пины для других целей (как обычные GPIO), пока порт не включен программно.
    Подвох: Главная ловушка для новичков! Если вы отключили CDC On Boot и загрузили скетч, который не вызывает Serial.begin() или в котором есть ошибка, плата перестанет определяться компьютером. Чтобы снова её перепрошить, придется вручную зажать кнопку BOOT при подключении или сбросе.

 

USB Firmware MSC On Boot (MSCOnBoot)

Активирует режим Mass Storage Class (USB-накопитель) при загрузке. Позволяет компьютеру видеть плату как флеш-диск для обмена файлами, а не как COM-порт. Компьютер видит ESP32 как обычный USB-накопитель. Главная идея этого режима — максимально упростить обновление прошивки: вы можете просто перетащить скомпилированный файл прошивки (.bin) в окно этого “диска”, и плата обновится. Это очень удобно для конечных пользователей, которым не нужно запускать Arduino IDE и разбираться в протоколах загрузки. Доступ к накопителю может осуществляться через SPI Flash (часть памяти самой ESP32) или через SD-карту.

  • Enabled (Включено) — “Плата как флешка”. При загрузке плата регистрируется в системе как съемный диск. Для обновления прошивки нужно просто скопировать .bin-файл в корень этого виртуального диска. Максимальная простота. Идеально для конечных устройств, где пользователь должен легко и без лишних программ обновить прошивку.
    Важное условие: Для работы этого режима обязательно нужно переключить опцию USB Mode в значение USB-OTG (TinyUSB).
    Подвох: В этом режиме загрузчик (bootloader) получает монопольный доступ к USB-порту. Это означает, что вы не сможете одновременно использовать USB для отладки через Serial Monitor (эмуляция COM-порта будет отключена)
  • Disabled (Отключено) — “Обычный режим”. Плата даже не пытается стать флешкой при старте. USB-порт используется в стандартном режиме (обычно как виртуальный COM-порт для загрузки скетчей и отладки). Для разработчиков, которые активно отлаживают код через COM-порт и им нужен доступ к Serial Monitor.

 

USB DFU On Boot (DFUOnBoot)

Включает режим DFU при старте. DFU расшифровывается как Device Firmware Upgrade. По сути, это USB-стандарт, который позволяет загружать новую прошивку в устройство через сам USB-порт. Когда эта опция включена (Enabled), плата при старте представляет себя компьютеру как DFU-устройство, готовое к приёму новой программы. Это особенно удобно для разработки: во многих случаях можно избавиться от необходимости вручную удерживать кнопку BOOT для входа в режим загрузки.
Подвох: В этом режиме загрузчик (bootloader) получает монопольный доступ к USB-порту. Это означает, что вы не сможете одновременно использовать USB для отладки через Serial Monitor (эмуляция COM-порта будет отключена)
Важное условие: Чтобы эта функция заработала, важно выполнить два условия:

  • Аппаратная поддержка: Ваша плата должна иметь USB-разъём, подключённый напрямую к встроенному USB-периферийному модулю, например ESP32-S2 или ESP32-S3, а не через внешний USB-UART чип (например CP2102) .
  • Правильные настройки в Arduino IDE: Вам нужно будет выставить несколько параметров в меню Инструменты:
    • Для ESP32-S3: USB Mode = USB-OTG (TinyUSB), USB DFU On Boot = Enabled
    • Для ESP32-S2: USB DFU On Boot = Enabled, Upload Mode = Internal USB

 

Upload Mode (UploadMode)

Способ загрузки прошивки: через UART (последовательный порт) или по воздуху (OTA – Over-The-Air). Эта опция определяет канал передачи данных, по которому ваша готовая прошивка (скомпилированный .bin-файл) попадает из Arduino IDE на микроконтроллер.

  • UART (Serial) — “По проводу”. Это классический, стандартный способ, который используется по умолчанию.
    Плата подключается к компьютеру через USB-кабель (напрямую или через внешний USB-UART чип). Прошивка передается по последовательному порту (COM-порту) с помощью утилиты esptool.py.
    Плюсы: Надежность и скорость. Связь стабильная, не зависит от Wi-Fi, скорость загрузки высокая (до 921600 бод).
    Минусы: Требуется физический доступ к устройству и USB-кабель.
  • OTA (Over-The-Air) — “По воздуху”. Это продвинутый способ для устройств, которые уже находятся в эксплуатации.
    Прошивка передается не по проводу, а через Wi-Fi (или Ethernet). Вам не нужно подключать устройство к компьютеру кабелем — достаточно, чтобы оно было в одной сети с вашим ПК. Для удаленных устройств, которые физически недоступны (например, датчики на потолке, уличные метеостанции).
    Плюсы: Не нужен физический доступ к устройству. Можно обновлять прошивку удаленно.
  • Минусы: Требуется правильная конфигурация сети и разделов флеш-памяти (для OTA нужно две секции APP — активная и резервная). Медленнее – загрузка по Wi-Fi медленнее, чем по проводу (особенно при слабом сигнале). Есть риск “окирпичивания” – если во время OTA-обновления пропадет питание или Wi-Fi, устройство может остаться без рабочей прошивки (хотя есть механизмы защиты).

 

Core Debug Level (DebugLevel)

Уровень отладочных сообщений ядра. Значения от None (без отладочных сообщений) до Verbose (максимум информации). Влияет на размер прошивки и скорость выполнения – чем больше сообщений, тем медленнее работа и больше размер прошивки. Если ваша прошивка “не влезает” в заданный размер раздела – попробуйте отключить лишние отладочные сообщения.

 

CPU Frequency (CPUFreq)

Тактовая частота процессора. Влияет на производительность и энергопотребление. Выберите:

  • 80 МГц для экономии энергии при питании от автономной батареи
  • 240 МГц для большей скорости работы при питании от сети
  • 160 МГц это компромиссный вариант

 

Flash Frequency (FlashFreq)

Процессор и флеш-память соединены через интерфейс SPI. Частота, которую вы выбираете в этой опции, определяет тактовую частоту этого интерфейса. Более высокая частота ускоряет чтение/запись, но может быть нестабильной на длинных проводах.

  • 80 MHz – максимальная производительность. Память работает на самой высокой частоте. Скетч загружается и выполняется быстрее. Это выбор для проектов, где важна скорость, например, при обработке потоковых данных или работе с дисплеями.
  • 40 MHz – режим повышенной стабильности. Более консервативная частота, безопасная отправная точка. Шина работает медленнее, но значительно надёжнее. Рекомендуется, если ваша плата ведет себя нестабильно на 80 МГц. Иногда это является решением проблем со случайными сбоями и перезагрузками.

Для современных серий частота шины может быть и ещё выше – например 120MHz.

 

Flash Mode (FlashMode)

Режим работы SPI-интерфейса флеш-памяти. Определяет количество линий для передачи данных. В порядке возрастания производительности они выглядят так :

  • DIO (Dual Input/Output) – 2 линии для адреса и данных, скорость немного выше, чем dout (~55% от QIO)
  • QIO (Quad I/O) – 4 линии для адреса и данных, самая высокая скорость (эталон)
  • OPI (Octal PI) – 8 линий данных (только для ESP32-S3)

Иногда выбор режима Flash Mode совмещен со скоростью передачи, тогда эта опция выглядит как DIO 80MHz / QIO 120MHz / OPI 80MHz.

 

Flash Size (FlashSize)

Объем встроенной флеш-памяти. Должен соответствовать физическому размеру микросхемы памяти, распаянному на плате или модуле. Неправильный выбор может привести к ошибкам при прошивке устройства.
Узнайте реальный размер флеш-памяти на вашей плате – на современных модулях он указан в названии модуля после буквы N (например, для ESP32-WROOM-32 по умолчанию имеется 4 МБ flash, а модуль ESP32-S3-DevKitC-1-N8 имеет 8 МБ). Узнать размер flash-памяти можно и из документации к плате, если она имеется.

 

Partition Scheme (PartitionScheme)

Таблица разделов флеш-памяти. Определяет размеры областей для кода программы, файловой системы (SPIFFS/FATFS) и количество разделов для OTA-обновлений. Весь доступный объем flash памяти разбивается на несколько отдельных областей (разделов) для хранения разного типа данных. Более подробно об этом поговорим в следующем разделе.
Важно: таблица разделов должна соответствовать размеру памяти, заданному в Flash Size

 

Erase All Flash Before Sketch Upload (EraseFlash)

Включение этой опции (Enabled) полностью очищает всю flash-память перед загрузкой нового скетча. Рекомендуется активировать при смене Partition Scheme. Сильно замедляет загрузку прошивки и ускоряет износ памяти. При обычной загрузке лучше отключить эту опцию.

 

PSRAM (PSRAM)

Активация внешней PSRAM (псевдостатической RAM), если он распаян на плате или в модуле. Активация этой опции (Enabled) позволяет использовать в вашем скетче дополнительную оперативную память для больших массивов данных. Настраивать размер подключенной PSRAM не требуется – система сама способна это определить. А вот тип SPI шины указать потребуется-выберите то же самое значение, как и для  Flash Mode, так как они подключены к одной и той же шине SPI0. Подробнее об PSRAM можно прочитать здесь.

 

Arduino Runs On (LoopCore)

Ядро CPU, на котором будет запущен основной цикл Arduino (loop). Действительно только для SoC с двумя ядрами. По умолчанию это Core 1.

 

Events Run On (EventsCore)

На каком ядре CPU запускается цикл событий и обрабатываются системные события (WiFi, Bluetooth, прерывания). Действительно только для SoC с двумя ядрами. По умолчанию Core 0.

 

JTAG Adapter (JTAGAdapter)

Выбор адаптера для отладки через интерфейс JTAG – Эта опция указывает среде разработки, каким именно “инструментом” вы будете пользоваться для отладки.

Если Serial.print() для вас как “стучать по стене, чтобы понять, что за ней”, то JTAG — это возможность заглянуть в “окно”. JTAG (Joint Test Action Group) — это аппаратный интерфейс, который позволяет профессионально отлаживать код. Вы можете:

  • Останавливать выполнение программы в любой момент (брейкпоинты).
  • Пошагово проходить по коду, отслеживая, что происходит в каждой строке.
  • Смотреть и изменять значения переменных и регистров процессора в реальном времени.

Это бесценно при поиске сложных ошибок, особенно в многозадачных программах ESP32 с FreeRTOS.

  • Integrated USB JTAG (Встроенный USB JTAG): Это самый простой и удобный способ для современных плат ESP32 с встроенным USB-портом (например, S3, C3). Для него не нужен внешний адаптер или программатор! Отладка и связь с платой происходят прямо через USB-кабель, который вы используете для загрузки кода. Нужно лишь выбрать эту опцию в меню и правильно подключить плату.
  • External JTAG (Внешний адаптер): Этот режим используется для плат, у которых нет встроенной поддержки JTAG по USB, или когда требуется больше возможностей. Вы подключаете внешний отладчик (например, ESP-Prog, J-Link или FT2232H) к специальным пинам ESP32 (TDI, TDO, TCK, TMS). Это потребует от вас больше знаний и правильного подключения.
  • Disabled (Отключено): Режим отладки JTAG выключен. Это значение по умолчанию. 

 

Zigbee Mode (ZigbeeMode)

Опция Zigbee Mode в Arduino IDE используется для настройки роли вашего устройства в сети Zigbee. Если говорить проще, она определяет, будет ли ваша плата главным устройством, создающим сеть, или обычным устройством, которое к этой сети подключается. В меню ИнструментыZigbee mode вы обычно можете выбрать один из двух вариантов:

  • Zigbee ZCZR (координатор/маршрутизатор) — это режим для главного устройства сети. Выбирайте его, если ваша плата должна создавать Zigbee-сеть и управлять ею. Координатор отвечает за формирование сети, позволяет другим устройствам подключаться и обрабатывает команды управления, например, от выключателя к лампочке.
  • Zigbee ED (конечное устройство) — это режим для периферийного устройства. Выбирайте его, если плата должна подключаться к уже существующей Zigbee-сети. Конечные устройства могут быть лампочками, датчиками движения и другими элементами «умного дома». Этот режим подходит не для всех SoC ESP32, а только для микроконтроллеров, которые аппаратно поддерживают Zigbee.

Важно: При выборе режима Zigbee важно помнить, что его работа также требует корректной схемы разделов (Partition Scheme). Для Zigbee-проектов обычно используется специальная схема, например Zigbee 4MB with spiffs. Это гарантирует, что на флеш-памяти достаточно места для стека Zigbee и вашего приложения.

 

Pin Numbering (PinNumbers)

Опция Pin Numbering (Нумерация выводов) — это специальный переключатель, который решает давний конфликт между двумя разными системами обозначений для одних и тех же физических контактов на некоторых платах ESP32.

Некоторые платы, такие как Arduino Nano, используют логическую нумерацию: контакты на плате подписаны как D0, D1, D2 и так далее. В то же время, чип ESP32 на этих платах имеет собственную, внутреннюю нумерацию выводов — GPIO (General Purpose Input/Output) номера (например, GPIO5, GPIO44). Иногда эти номера не совпадают. Например, на плате Arduino Nano ESP32 физический контакт, подписанный как D2, внутри микроконтроллера соединен с выводом GPIO5. Эта путаница приводит к проблемам: вы пишете в коде digitalWrite(2, HIGH), а система не всегда может однозначно понять: вы имеете в виду контакт D2 на плате (что логично) или внутренний вывод GPIO2 (что ожидает ESP32)?

Меню Pin Numbering предлагает выбор между двумя схемами:

  • By Arduino pin (default): (По умолчанию): Использует номера, напечатанные на самой плате (например, D0, D1). Удобно, если вы переносите проект с другой платы Arduino Nano, так как номера контактов в коде будут соответствовать вашей схеме подключения.
  • By GPIO number (legacy): (По GPIO): Использует внутреннюю нумерацию GPIO микроконтроллера ESP32. Этот режим предпочтительнее при использовании сторонних библиотек, которые изначально создавались для ESP32.

Эта опция не является стандартной для всех ESP32-плат. В основном она предназначена для решения проблемы совместимости на конкретных платах, например Arduino Nano ESP32. На большинстве других ESP32-плат (например, от Adafruit или Seeed Studio) нумерация выводов по умолчанию и всегда соответствует GPIO, и вы не увидите подобного переключателя в меню. Для них выбор очевиден — всегда используйте GPIO номера, которые указаны в документации к вашей плате.

 

Chip Variant (ChipVariant)

Вариант микроконтроллера в серии. Опция Chip Variant — это один из самых “глубинных” параметров, обычно его вы не увидите в настройках Arduino IDE, но он есть – почти как суслик. По сути, это выбор основной модели процессора ESP32, на котором работает ваша плата. Дело в том, что разные чипы семейства ESP32 — это не просто разные версии одного и того же устройства. У них могут быть разные архитектуры ядер, разные наборы периферии и разные возможности. Когда вы выбираете конкретную плату, система сама выбирает один из вариантов: ESP32, ESP32-S2, ESP32-S3 и т.д.

 

Опции периферийного оборудования (Custom options)

На некоторых платах, например Heltec WiFi LoRa 32 V3/V4/T114, доступны дополнительные опции. Я не буду сейчас их подробно описывать, просто оставлю это здесь:

  • Board Revision (Revision)
    Версия аппаратной ревизии платы. Разные версии могут иметь разные распиновки или компоненты
  • LoRaWan Region (LORAWAN_REGION)
    Регион для работы LoRaWAN (EU868, US915, AS923 и т.д.). Определяет частотный диапазон для LoRa-связи
  • LoRaWan Debug Level (LoRaWanDebugLevel)
    Уровень детализации логов для LoRaWAN-стека. Помогает отлаживать проблемы с подключением к сети
  • LoRaWan DevEUI (LORAWAN_DEVEUI)
    Уникальный идентификатор устройства в сети LoRaWAN. Используется для регистрации устройства в сети
  • LoRaWan Preamble Length (LORAWAN_PREAMBLE_LENGTH)
    Длина преамбулы в пакетах LoRa. Влияет на дальность связи и энергопотребление
  • LoRa FEM Type (LORA_FEM_TYPE)
    Тип внешнего FEM (Front-End Module) для LoRa. Усилитель для улучшения дальности связи
  • LoRa External FEM Receive Gain (LORA_RX_LNA)
    Коэффициент усиления при приеме внешнего FEM. Настраивает чувствительность приемника
  • Slow Clk Type (only for LoRaWAN) (SLOW_CLK_TPYE)
    Тип медленного тактового сигнала для LoRaWAN. Влияет на точность временных интервалов
  • E-Ink Display Size (einksize)
    Размер подключенного E-Ink дисплея. Определяет разрешение и буфер кадра
  • Network Log Level (NetworkLogLevel)
    Уровень логирования сетевых операций (WiFi, Ethernet). Помогает отлаживать сетевые подключения
  • Display Model (DisplayModel)
    Модель подключенного дисплея. Определяет контроллер, разрешение и интерфейс
  • Language (Language)
    Язык интерфейса или локализация. Может влиять на кодировку и символы в выводе

Выбор таблицы разделов памяти

Флеш-память ESP32 — это не единое целое, а набор логических разделов (partition). В одном разделе может храниться ваша программа, в другом — настройки Wi-Fi, в третьем — файловая система для веб-страниц и т.д. Задача таблицы разделов — рассказать системе, где находится каждый такой кусочек памяти, какого он типа и размера. Без этой карты загрузчик просто не поймет, откуда запускать программу. Это очень похоже на жесткий диск компьютера – там тоже есть разделы и таблица разделов. Более подробно об этом вы можете почитать здесь.

Таблица разделов — это специальный служебный блок в самом начале flash-памяти. Исходный текст таблицы разделов представляет собой простой текст в формате CSV. Выглядит она примерно так:

# Name,     Type, SubType, Offset,  Size,   Flags
nvs,        data, nvs,     0x9000,  0x6000,
phy_init,   data, phy,     0xf000,  0x1000,
factory,    app,  factory, 0x10000, 1M,

Каждая строка описывает один раздел и состоит из следующих полей:

  • Name (Имя): Это просто понятное человеку имя, чтобы было легче ориентироваться. Важно, чтобы оно было не длиннее 16 символов.
  • Type (Тип): Определяет, какого рода данные там хранятся. Основных типа два: app (двоичный код программы) и data (для любых других данных: настроек, файлов и т.д.).
  • SubType (Подтип) : Уточняет назначение раздела. Например, для типа app есть специальный подтип factory (заводская прошивка) или ota_0, ota_1 (слоты для обновлений по воздуху). А для типа data есть подтипы nvs (хранение настроек), phy (калибровка Wi-Fi/Bluetooth), spiffs, fat (файловые системы) и другие.
  • Offset (Смещение): Адрес в байтах, с которого начинается этот раздел. Если оставить это поле пустым, специальный инструмент при компиляции сам подставит корректное значение, разместив раздел сразу после предыдущего.
  • Size (Размер): Размер раздела. Можно указывать в байтах, а можно использовать суффиксы, например 1M (1 мегабайт) или 4K (4 килобайта).
  • Flags (Флаги): Дополнительные свойства, например, encrypted (раздел будет зашифрован) или readonly (только для чтения, защита от случайной записи).

Если вы создаете свою программу в ESP-IDF, то в ней вы найдете только две-три “стандартных” таблицы разделов. Если вам нужно что-то иное, вы должны создать свою собственную таблицу разделов, например как это описано в статье [Настройка таблицы разделов FLASH-памяти для ESP32]. Arduino IDE избавляет вас от этой необходимости и предоставляет на выбор набор готовых таблиц с разными характеристиками. Строго говоря, раньше в Arduino IDE вообще не было возможности добавить свою собственную таблицу (сейчас есть, и мы это обсудим ниже).

 

Что необходимо понимать, дабы выбрать правильную схему?

Прежде всего вы должны определиться с размером FLASH-памяти, которая установлена на вашей плате или модуле (2MB, 4MB, 8MB, 16MB или 32MB). Стандартный размер для ESP32-WROOM это 4MB, но нужно обязательно уточнять, так как могут быть варианты. На современных модулях он указан в названии модуля после буквы N (например плата ESP32-S3-DevKitC-1-N8 имеет 8 МБ). Узнать размер flash-памяти можно и из документации к плате или модулю, если она имеется.

В разделы типа app (Application) записывается ваша программа (скомпилированный скетч). Они могут быть разных субтипов: factory – “заводская” прошивка и ota – разделы для OTA. OTA (Over-The-Air) – это возможность обновления прошивки по Wi-Fi, без использования кабеля. Но здесь есть важный нюанс – для того, чтобы это сработало, нужно иметь как минимум два OTA-раздела. Как это работает можно почитать в статьях [OTA обновления прошивки “по воздуху” для ESP8266 и ESP32 на платформе Arduino] и [OTA обновления прошивки “по воздуху” для ESP32 и платформы ESP-IDF].

Файловые системы могут использоваться для хранения различных файлов: шаблоны html и css файлы для веб-интерфейсов, шаблоны сообщений, логи, настройки в виде JSON-файлов и т.д.

  • SPIFFS / SPI Flash File System – Файловая система для небольших данных (хорошо подходит для шаблонов веб-страниц, различных конфигов в виде файлов)
  • FATFS / FAT File System – Файловая система, которая дает совместимость с Windows (можно читать как флешку на ПК)
  • LittleFS / Little File System – Современная файловая система для встраиваемых устройств

Специальные разделы, свойственные ESP

 

Выбор одной из готовых таблиц разделов

Arduino IDE избавляет вас от этой необходимости и предоставляет на выбор набор готовых таблиц с разными характеристиками. Строго говоря, раньше в Arduino IDE вообще не было возможности добавить свою собственную таблицу (сейчас есть, и мы это обсудим ниже). Выглядит это примерно так:

Выбор таблицы разделов для ESP32-S3

А теперь внимание – вопрос: что скрывается за этими загадочными называниями? Для этого нужно открыть файлик с разметкой, и посмотреть какие разделы в нем присутствуют. Но я сделал это за вас – ниже в таблицах (для каждой серии SoC отдельно) вы найдете ответ на этот вопрос. 

Пояснения

  • Размеры партиций указаны в “честных” килобайтах и мегабайтах, то есть размер в байтах / 1024 и размер в байтах / 1024 / 1024, а не как китайцы пишут “с потолка”.
  • Если в таблице вы видите знак Х, это означает что данный раздел отсутствует
  • Если размер указан без знака ~, например 1,50MB, значит это ровно 1.5 МБ, то есть размер в байтах / 1024 / 1024.
  • Если размер указан со знаком ~, значит это приблизительное значение, округленное до 2-х знаков после запятой.
  • Все размеры получены путем сканирования скриптом файлов таблиц разделов, то есть отражают фактические данные на момент написания статьи. Но со временем эти файлы могут измениться (в следующих релизах Arduino core).

 

Таблицы (схемы) разделов для серии ESP32

Partition sheme (таблица разделов) flash-памяти для SoC ESP32

Partition sheme (таблица разделов) flash-памяти для SoC ESP32 “классической” серии

Таблицы (схемы) разделов для серии ESP32-S2

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-S2

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-S2

Таблицы (схемы) разделов для серии ESP32-S3

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-S3

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-S3

Таблицы (схемы) разделов для серии ESP32-C3

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C3

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C3

Таблицы (схемы) разделов для серии ESP32-C5

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C5

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C5

Таблицы (схемы) разделов для серии ESP32-C6

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C6

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-C6

Таблицы (схемы) разделов для серии ESP32-H2

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-H2

Partition sheme (таблица разделов) flash-памяти для SoC ESP32-H2

Как выбрать “правильную” схему разделов?

Допустим, вы имеете плату со стандартными 4MB flash.

  • Если вы не знаете, что выбрать — начните с Default 4MB with spiffs. Это оптимальный баланс между кодом и файлами, если нужна SPIFFS и OTA одновременно.
  • Если файловая система не нужна совсем — возьмите No FS 4MB
  • Если у вас много данных (картинки, звуки) — No OTA (3MB SPIFFS).
  • Для обновлений по Wi-Fi (OTA) обязательно выбирайте схему с двумя OTA-секциями (app0 и app1).
  • Для устройств с Zigbee выбирайте специальные схемы с сертификацией для Zigbee-устройств.

 

Как добавить свою (custom) схему разделов?

Сейчас Arduino IDE без особых танцев с бубном позволяет добавить свою, кастомизированную, таблицу разделов. В ней вы сможете учесть все ваши требования, создать только те разделы, которые вам действительно нужны. Например можно увеличить размер NVS раздела для хранения настроек.

Создайте CSV-файл с вашей таблицей разделов. Я не буду сейчас описывать этот процесс, как это сделать вы можете прочитать здесь: [Настройка таблицы разделов FLASH-памяти для ESP32]. Назовите его partitions.csv и поместите в папку со скетчем, где находится ваш основной .ino файл. Затем просто выберите опцию ИнструментыPartition SchemeCustom.

Если опция Custom недоступна для вашей платы, или она не появляется после добавления файла, это может быть связано с тем, что для некоторых плат (например, ESP32S3 Dev Module Octal) в файле boards.txt отсутствует соответствующая запись.


Карты выводов (pin mapping)

Pin mapping (карта выводов, или распиновка) — это, по сути, таблица соответствия между тем, как вы обращаетесь к контакту в своем коде (например, D2 или GPIO_NUM_5), и тем, к какому физическому контакту на микроконтроллере этот номер ведет. 

На некоторых платах разработчика, таких как Arduino или Wemos D1 R32, физические контакты на корпусе микросхемы перераспределены по выводам на плате с другой нумерацией. Производитель делает это для удобства пользователя, группируя контакты и подписывая их в соответствии с некими правилами. Без pin mapping вам бы пришлось писать код, используя номера GPIO микроконтроллера, которые известны только в даташите на чип, а не на самой плате.

На примере платы Arduino Nano ESP32 это видно особенно хорошо: физический вывод микроконтроллера имеет номер, скажем, GPIO5. На плате этот контакт подписан как D2. Файл Pin mapping для этой платы говорит системе: «Когда программист использует D2 в своем коде, я должен обратиться к физическому выводу с номером GPIO5». Иногда в Arduino IDE для таких плат появляется специальная опция Pin Numbering – она переключает, какую нумерацию использовать, чтобы избежать путаницы (а на деле только её добавляет) и сделать код переносимым.

Для чего это нужно разработчику?

Когда вы пишете digitalWrite(2, HIGH), важно понимать, что число 2 может означать как номер логического контакта (тот, что напечатан на разъеме платы), так и GPIO2. Если плата имеет нестандартную распиновку, использование логических номеров (D2) помогает сохранять совместимость с кодом от других плат, например, от Arduino Uno, где контакт D2 аппаратно закреплен за GPIO2. Кроме того, некоторые аппаратные функции ESP32 (например, SPI, I2C, UART) могут быть «привязаны» к конкретным физическим выводам микроконтроллера. Pin mapping позволяет библиотекам и вашему коду правильно инициализировать эти интерфейсы на тех платах, которые вы используете.

Подключить файл к скетчу очень просто: #include "pins_arduino.h". Вот так, например, выглядит файл для Wemos D1 UNO (R32). Это обычный “заголовочный” файл Си, где объявлены константы “имен” выводов:

#ifndef Pins_Arduino_h
#define Pins_Arduino_h

// Board Pinmap: https://www.botnroll.com/en/esp/3639-wemos-d1-r32-w-esp32-uno-r3-pinout.html

#include <stdint.h>

static const uint8_t TX = 1;
static const uint8_t RX = 3;

static const uint8_t SDA = 21;
static const uint8_t SCL = 22;

static const uint8_t SS = 5;
static const uint8_t MOSI = 23;
static const uint8_t MISO = 19;
static const uint8_t SCK = 18;

static const uint8_t A0 = 2;
static const uint8_t A1 = 4;
static const uint8_t A2 = 35;
static const uint8_t A3 = 34;
static const uint8_t A4 = 36;
static const uint8_t A5 = 39;

static const uint8_t LED_BUILTIN = 2;
#define BUILTIN_LED LED_BUILTIN  // backward compatibility
#define LED_BUILTIN LED_BUILTIN  // allow testing #ifdef LED_BUILTIN

#define PIN_WIRE_SDA SDA  // backward compatibility
#define PIN_WIRE_SCL SCL  // backward compatibility

static const uint8_t D0 = 3;
static const uint8_t D1 = 1;
static const uint8_t D2 = 26;
static const uint8_t D3 = 25;
static const uint8_t D4 = 17;
static const uint8_t D5 = 16;
static const uint8_t D6 = 27;
static const uint8_t D7 = 14;
static const uint8_t D8 = 12;
static const uint8_t D9 = 13;
static const uint8_t D10 = 5;
static const uint8_t D11 = 23;
static const uint8_t D12 = 19;
static const uint8_t D13 = 18;

#define PIN_SPI_SS   SS    // backward compatibility
#define PIN_SPI_MOSI MOSI  // backward compatibility
#define PIN_SPI_MISO MISO  // backward compatibility
#define PIN_SPI_SCK  SCK   // backward compatibility

#define PIN_A0 A0  // backward compatibility

#endif /* Pins_Arduino_h */ 

Физически файлы pins_arduino.h расположены в папках, соответствующих логическим именам плат: %USER_PROFILE%\AppData\Local\Arduino15\packages\esp32\hardware\esp32\%version%\variants\%плата%\.


Какие еще есть варианты программирования ESP32?

В заключение хотелось бы отметить, что Arduino IDE – далеко не единственный вариант, где можно программировать ESP32. Есть гораздо более удобные среды – Visual Studio Code, Theia IDE, CLion и т.д.. В том числе можно работать и с Arduino core, при необходимости.

Для полноценного программирования ESP8266 и ESP32 в основном используется язык C / C++ с применением платформ Arduino или ESP-IDF, но также можно работать и с языками MicroPython, LUA, Rust и др. Список поддерживаемых языков постоянно расширяется. А использовать для этого можно много самых разных сред разработки: Arduino IDE, PlatformIO, Espressif IDE, Theia IDE, CLion, VisualGdb, ESPLorer и другие.

ESP8266
├── Язык: C / C++
│   ├── Фреймворк: Arduino core for ESP8266  ← Простой, для обучения
│   │   ├── IDE: Arduino IDE 1 / 2
│   │   └── IDE: VS Code + PlatformIO
│   ├── Фреймворк: ESP8266 Non-OS SDK  ← Сложный, не рекомендуется
│   └── Фреймворк: ESP8266 RTOS SDK   ← Сложный, не рекомендуется
│
├── Язык: MicroPython (Python 3)
│   └── IDE: ESPlorer
│
└── Язык: LUA (NodeMCU)
    └── IDE: ESPlorer

ESP32 (ESP32, ESP32-S, ESP32-C, ESP32-H и т.д.)
├── Язык: C / C++
│   ├── Фреймворк: Arduino core for ESP32  ← Простой, для обучения
│   │   ├── IDE: Arduino IDE 1 / 2
│   │   └── IDE: VS Code + PlatformIO
│   │
│   └── Фреймворк: ESP-IDF  ← Профессиональный
│       ├── Режим: Чистый ESP-IDF
│       ├── Режим: Arduino as component  ← Компромисс
│       ├── IDE: VS Code + ESP-IDF Extension  ← Официальный
│       ├── IDE: VS Code + PlatformIO
│       ├── IDE: Eclipse Theia + ESP-IDF
│       ├── IDE: Eclipse CDT (Espressif IDE)
│       ├── IDE: CLion + ESP-IDF
│       └── IDE: Visual Studio + VisualGDB  ← Платное расширение
│
├── Язык: MicroPython (Python 3)
│   └── IDE: ESPlorer
│
├── Язык: LUA (NodeMCU)
│   └── IDE: ESPlorer
│
├── Язык: Rust
│   ├── IDE: VS Code + espup
│   └── IDE: RustRover
│
└── Язык: Free Pascal  ← Специфичный
    └── IDE: Lazarus + FPCUPdeluxe

Шаг 1. Для начала необходимо определиться с тем, какой язык программирования вы будете использовать.

Шаг 2. Если вы выбрали язык C / C++ – определитесь с платформой (фреймворком)

  • для ESP8266 основной платформой можно считать Arduino core for ESP8266, Другие варианты сложны и мало используются.
  • для ESP32ESP-IDF или Arduino core for ESP32. Платформа Arduino core более простая в освоении, а ESP-IDF дает больше возможностей (но можно сочетать ESP-IDF + Arduino core).

Шаг 3. Исходя из выбранной платформы подберите подходящую IDE:

  • Arduino IDE подойдет вам, если вы хотите программировать ESP8266 или ESP32 с использованием Arduino core for ESP32. Прост, но не удобен. Кроме того, последние версии IDE не получится скачать и запустить без квн - доступ заблокировали новые владельцы платформы (Qualcomm).
  • Visual Studio Code (или Theia) с плагином ESP-IDF v2 можно использовать для работы с ESP32 с использованием ESP-IDF или ESP-IDF + Arduino core как компонент. Официальный инструмент от Espressif. Сложнее Arduino IDE, но несравненно удобнее.
  • Visual Studio Code с плагином PlatformIO можно использовать для работы и с ESP8266 и с ESP32, и с любым фреймворком - Arduino core for ESP32 или ESP-IDF или ESP-IDF + Arduino core как компонент. Но относительно сложен в освоении. 

Я советую второй или третий вариант, но Выбор за вами. А также вы можете воспользоваться схемой или таблицей ниже:

Но это уже совсем другая история…


На этом пока всё. Спасибо, что дочитали! Надеюсь информация будет полезной. До новых встреч.


Пожалуйста, оцените статью:
[ 5 из 5, всего 2 оценок ]

-= Каталог статей (список по разделам) =-   -= Архив статей (плитки, все подряд) =-

Небольшой анонимный опрос: какие статьи вы предпочитаете?

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

  −  6  =  2