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 появятся новые пункты меню с нашими платами.

Есть идея сделать онлайн конфигуратор для всех этих файлов, чтобы не изменять их вручную. Но когда дойдут до этого руки — пока не знаю)