PlatformIO: Программируем Arduino в Sublime Text (часть 2)
В прошлой статье я описал, как установить и настроить PlatformIO с Sublime Text. Теперь я расскажу, как можно переключаться между различными версиями платформы, так, как если бы мы использовали разные версии Arduino IDE. Для чего это может понадобиться? Например, если у вас есть библиотека, которая давно не обновлялась автором и поэтому не работает в последних версиях Arduino IDE. Или есть скетч, который был написан под более раннюю версию и некорректно работает в последней.

Открываем папку C:\Users\{имя_пользователя}\.platformio\packages\framework-arduinoavr\cores\ . И видим там несколько папок с «ядрами»:

Фактически, каждая папка содержит набор исходников платформы, содержащие все функции языка Wiring, который мы и используем при программировании Arduino. Именно там содержится код функций типа digitalRead, delay и т.д. Можно (и нужно!) глянуть эти исходники и поизучать.

Так вот, чтобы «сменить» номер версии, достаточно всего лишь подменить эти исходники. К примеру, вытащить из необходимой версии Arduino IDE. Но мы поступим немного по-другому: не будем подменять, а создадим столько новых «ядер», сколько нам нужно. Для этого я создал несколько папок: arduino1_0_5, arduino1_6_0. Теперь в эти папки копируем содержимое из папок arduino-X.X.X\hardware\arduino\avr\cores\arduino\ , где «arduino-X.X.X» — папка с Arduino IDE нужной нам версии.
Получили несколько папок с разными версиями, где просто «arduino» — это штатная от PlatformIO с самой последней версией:

Теперь надо указать PlatformIO использовать наши папки с исходниками. Это нужно сделать сразу в двух местах: PlatformIO в Python и в Sublime Text. Открываем в текстовом редакторе файл: c:\Python27\Lib\site-packages\platformio\boards\arduino.json . Видим там описание различных плат Arduino. Ищем секции описания плат, которыми мы пользуемся. Дальше нужно скопировать эти секции и заменить в них параметр «core». Также меняем идентификатор платы и название («name»), чтобы их отличать. Например:
Было:
"diecimilaatmega328": { "build": { "core": "arduino", "extra_flags": "-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE", "f_cpu": "16000000L", "mcu": "atmega328p", "variant": "standard" }, "frameworks": ["arduino"], "name": "Arduino Duemilanove or Diecimila ATmega328", "platform": "atmelavr", "upload": { "maximum_ram_size": 2048, "maximum_size": 30720, "protocol": "arduino", "require_upload_port" : true, "speed": 57600 }, "url": "http://arduino.cc/en/Main/ArduinoBoardDiecimila", "vendor": "Arduino" },
Стало:
"diecimilaatmega328": { "build": { "core": "arduino", "extra_flags": "-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE", "f_cpu": "16000000L", "mcu": "atmega328p", "variant": "standard" }, "frameworks": ["arduino"], "name": "Arduino Duemilanove or Diecimila ATmega328", "platform": "atmelavr", "upload": { "maximum_ram_size": 2048, "maximum_size": 30720, "protocol": "arduino", "require_upload_port" : true, "speed": 57600 }, "url": "http://arduino.cc/en/Main/ArduinoBoardDiecimila", "vendor": "Arduino" }, "diecimilaatmega328_105": { "build": { "core": "arduino1_0_5", "extra_flags": "-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE", "f_cpu": "16000000L", "mcu": "atmega328p", "variant": "standard" }, "frameworks": ["arduino"], "name": "Arduino Duemilanove or Diecimila ATmega328 1.0.5", "platform": "atmelavr", "upload": { "maximum_ram_size": 2048, "maximum_size": 30720, "protocol": "arduino", "require_upload_port" : true, "speed": 57600 }, "url": "http://arduino.cc/en/Main/ArduinoBoardDiecimila", "vendor": "Arduino" }, "diecimilaatmega328_160": { "build": { "core": "arduino1_6_0", "extra_flags": "-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE", "f_cpu": "16000000L", "mcu": "atmega328p", "variant": "standard" }, "frameworks": ["arduino"], "name": "Arduino Duemilanove or Diecimila ATmega328 1.6.0", "platform": "atmelavr", "upload": { "maximum_ram_size": 2048, "maximum_size": 30720, "protocol": "arduino", "require_upload_port" : true, "speed": 57600 }, "url": "http://arduino.cc/en/Main/ArduinoBoardDiecimila", "vendor": "Arduino" },
Теперь этот файл (arduino.json) копируем с заменой в папку C:\Progs\Sublime Text 2.0.2\Data\Packages\User\Deviot\penv\Lib\site-packages\platformio\boards (путь к Sublime Text не забываем заменить на свой).
Открываем командную строку и запрашиваем список интересующих нас плат:
platformio boards diecimila

Всё нормально, платы в списке появились. Но вот в Sublime Text мы их пока не увидим. Оказывается, нужно подправить ещё два файла:
C:\Progs\Sublime Text 2.0.2\Data\Packages\User\Deviot\Preset\platformio_boards.json
В этом файле не всё так просто. Будьте внимательны.
Было:
\"diecimilaatmega328\": {\"vendor\": \"Arduino\", \"name\": \"Arduino Duemilanove or Diecimila ATmega328\", \"platform\": \"atmelavr\", \"url\": \"http://arduino.cc/en/Main/ArduinoBoardDiecimila\", \"upload\": {\"maximum_ram_size\": 2048, \"maximum_size\": 30720, \"protocol\": \"arduino\", \"speed\": 57600, \"require_upload_port\": true}, \"frameworks\": [\"arduino\"], \"build\": {\"core\": \"arduino\", \"mcu\": \"atmega328p\", \"f_cpu\": \"16000000L\", \"extra_flags\": \"-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE\", \"variant\": \"standard\"}},
Стало:
\"diecimilaatmega328\": {\"vendor\": \"Arduino\", \"name\": \"Arduino Duemilanove or Diecimila ATmega328\", \"platform\": \"atmelavr\", \"url\": \"http://arduino.cc/en/Main/ArduinoBoardDiecimila\", \"upload\": {\"maximum_ram_size\": 2048, \"maximum_size\": 30720, \"protocol\": \"arduino\", \"speed\": 57600, \"require_upload_port\": true}, \"frameworks\": [\"arduino\"], \"build\": {\"core\": \"arduino\", \"mcu\": \"atmega328p\", \"f_cpu\": \"16000000L\", \"extra_flags\": \"-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE\", \"variant\": \"standard\"}}, \"diecimilaatmega328_105\": {\"vendor\": \"Arduino\", \"name\": \"Arduino Duemilanove or Diecimila ATmega328 1.0.5\", \"platform\": \"atmelavr\", \"url\": \"http://arduino.cc/en/Main/ArduinoBoardDiecimila\", \"upload\": {\"maximum_ram_size\": 2048, \"maximum_size\": 30720, \"protocol\": \"arduino\", \"speed\": 57600, \"require_upload_port\": true}, \"frameworks\": [\"arduino\"], \"build\": {\"core\": \"arduino1_0_5\", \"mcu\": \"atmega328p\", \"f_cpu\": \"16000000L\", \"extra_flags\": \"-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE\", \"variant\": \"standard\"}}, \"diecimilaatmega328_160\": {\"vendor\": \"Arduino\", \"name\": \"Arduino Duemilanove or Diecimila ATmega328 1.6.0\", \"platform\": \"atmelavr\", \"url\": \"http://arduino.cc/en/Main/ArduinoBoardDiecimila\", \"upload\": {\"maximum_ram_size\": 2048, \"maximum_size\": 30720, \"protocol\": \"arduino\", \"speed\": 57600, \"require_upload_port\": true}, \"frameworks\": [\"arduino\"], \"build\": {\"core\": \"arduino1_6_0\", \"mcu\": \"atmega328p\", \"f_cpu\": \"16000000L\", \"extra_flags\": \"-DARDUINO_ARCH_AVR -DARDUINO_AVR_DUEMILANOVE\", \"variant\": \"standard\"}},

Теперь следующий файл:
C:\Progs\Sublime Text 2.0.2\Data\Packages\User\Deviot\Preset\env_boards.json
Было:
{ "diecimilaatmega328": { "children": [ { "args": { "board_id": "diecimilaatmega328" }, "caption": "Arduino Duemilanove or Diecimila ATmega328", "checkbox": true, "command": "select_env" } ] } },
Стало:
{ "diecimilaatmega328": { "children": [ { "args": { "board_id": "diecimilaatmega328" }, "caption": "Arduino Duemilanove or Diecimila ATmega328", "checkbox": true, "command": "select_env" } ] } }, { "diecimilaatmega328_105": { "children": [ { "args": { "board_id": "diecimilaatmega328_105" }, "caption": "Arduino Duemilanove or Diecimila ATmega328 1.0.5", "checkbox": true, "command": "select_env" } ] } }, { "diecimilaatmega328_160": { "children": [ { "args": { "board_id": "diecimilaatmega328_160" }, "caption": "Arduino Duemilanove or Diecimila ATmega328 1.6.0", "checkbox": true, "command": "select_env" } ] } },
Вот теперь в Sublime Text появятся новые пункты меню с нашими платами.
Есть идея сделать онлайн конфигуратор для всех этих файлов, чтобы не изменять их вручную. Но когда дойдут до этого руки — пока не знаю)