Переход с Arduino IDE на PlatformIO IDE на базе Microsoft Visual Studio Code. Что нужно знать.

Несколько лет тому назад я подарил сыну набор «Матрёшка» с электронными компонентами и микроконтроллером Arduino Uno. Набор сопровождался скромным, но толковым учебным пособием, с которым можно не только освоить основы электроники, но и попытаться научиться программировать в среде Arduino. И хотя по первому образованию я радиотехник, а по второму инженер в ИТ, но мне было жутко интересно проходить все уроки «Матрешки» вместе с молодым поколением. Постепенно я втянулся и по дому начали плодиться многочисленные системы «Умного дома», различные датчики, улучшители и все прочее. А затем хобби перекинулось и на профессиональную сферу деятельности. И вот уже по рабочим вопросам начали появляться устройства автоматизации, измерительно-контрольные приборы и прочая уникальная незаменимая электронная утварь.

Но время идет и постепенно проекты начали усложнятся. В скетчах Arduino уже не десятки, а сотни строк. Количество переменных не влезает на один экран, а отсутствие отладчика временами приводит к нервному истощению. И в конце концов, было принято окончательное решение по миграции с Arduino IDE на что-то более удобное в плане разработки. Мой выбор почти сразу пал на PlatformIO IDE, причем перешел я на него только со второй попытки. Первая оказалась неудачной, поковырявшись несколько часов с PlatformIO я пришел к выводу, что в Arduino IDE все делается куда легче и быстрее. Но затем, спустя несколько месяцев я выкроил еще несколько часов своего драгоценнейшего времени для того, чтобы все же разобраться с PlatformIO IDE и постараться понять ее, а затем и полностью перейти на эту интегрированную систему. В качестве альтернативы я рассматривал Atmel Studio 7… Но обо всем по порядку.

Что такое Arduino?

В головах большинства — Arduino это что-то для Самоделкиных, не умеющих писать программу в двоичном коде и не способных к сборке схемы мостового выпрямителя вслепую. Отчасти это так и есть. Arduino как экосистема, сделала доступным мир электроники даже простому обывателю. Но и профессионалы могут получить очень неплохой бенефит, от использования экосистемы. Разработаны мириады различных плат, датчиков, сенсоров, библиотек и всего прочего, что может существенно сократить время от идеи до внедрения. Без Arduino никуда не деться, если нужно соорудить единичное устройство или прототип ограниченной серией. И все потому, что можно соединить отдельные элементы, быстро сочинить код и устройство готово. Зачастую больше времени тратишь на сборку корпуса, чем на разработку самого устройства.

А еще Arduino это фреймворк. Программная компонента, облегчающая взаимодействие программы, написанной программистом и низлежащим железом. Созданный «язык» Arduino значительно облегчает написание программ в экосистеме Arduino, особенно если пишутся они постоянно под разные устройства и время от времени. Arduino, как фреймворк, позволяет частично абстрагироваться от оборудования и сосредоточиться на реализуемых функциях, а не поиске микрокода от конкретного микроконтроллера.

Вот примерно так выглядит прозаичный Blink на С для компиляции AVR ToolChain (тулчейн — набор утилит, библиотек и полный набор компиляторов, соответственно AVR ToolChain есть набор для платформы AVR).

#define F_CPU 1000000UL
#include <avr/io.h>
#include <util/delay.h>
int main ()
{
    DDRB |= (1 << PB0);
    while(1) 
    {
        PORTB ^= (1 << PB0);
        _delay_ms(1000);
        _delay_ms(1000);
        _delay_ms(1000);
        _delay_ms(1000);
        _delay_ms(1000);
        _delay_ms(1000);
        _delay_ms(1000);
    }
}

Немного странно, но еще можно жить. А следующий пример «мигателя» уже на ассемблере (правда пример нерабочий, но не суть):

LDI R16,0x20
OUT DDRB,R16
LDI R17,0x00
OUT PORTB,R17
LDI R18,0x0D
STS TCCR1B,R18
STS TCNT1H,R17
STS TCNT1L,R17
LDI R20,0xF4
LDI R21,0x23
STS OCR1AH,R20
STS OCR1AL,R21
BEGIN1: IN R17,TIFR1
        CPI R17,2
        BRNE BEGIN1
        SBI TIFR1, OCF1A
        LDI R17,0x20
        OUT PORTB,R17
BEGIN2: IN R17,TIFR1
        CPI R17,2
        BRNE BEGIN2
        SBI TIFR1, OCF1A
        NOP;
        LDI R17,0x00
        OUT PORTB,R17
        RJMP BEGIN1

А следующий кусочек кода взят из примеров Atmel Studio 7. Тут применяется фреймворк ASF, так же как и Arduino, облегчающий разработку, в данном случае, под микроконтроллеры AVR Microchip (бывшие Atmel):

#include <asf.h>
/**
 * \brief Example 1 main application routine
 */
int main( void )
{
    /* The 4 PWM config structs */
    struct pwm_config pwm_cfg[4];
    /* Initialize sysclock */;
    sysclk_init();
    /* Set up all 4 PWM channels with 500 Hz frequency. We want to use TCE0
       since this is where our LEDs are connected (PE0-PE3) */
    pwm_init(&pwm_cfg[0], PWM_TCE0, PWM_CH_A, 500); /* LED0 / PE0 */
    pwm_init(&pwm_cfg[1], PWM_TCE0, PWM_CH_B, 500); /* LED1 / PE1 */
    pwm_init(&pwm_cfg[2], PWM_TCE0, PWM_CH_C, 500); /* LED2 / PE2 */
    pwm_init(&pwm_cfg[3], PWM_TCE0, PWM_CH_D, 500); /* LED3 / PE3 */
    /* Start all 4 PWM channels with different duty cycles
      (which means different LED intensity).
      Since the LEDs are active low, 0% duty cycle means constantly lit */
    pwm_start(&pwm_cfg[0], 97);
    pwm_start(&pwm_cfg[1], 85);
    pwm_start(&pwm_cfg[2], 60);
    pwm_start(&pwm_cfg[3], 0);
    while(1) {
        /* Nothing to do */
    }
}

В примере выше устанавливается разная степень светимости четырех светодиодов. И, наконец, любимый Blink из Arduino:

int led = 9;           // the PWM pin the LED is attached to
int brightness = 0;    // how bright the LED is
int fadeAmount = 5;    // how many points to fade the LED by
// the setup routine runs once when you press reset:
void setup() {
  // declare pin 9 to be an output:
  pinMode(led, OUTPUT);
}
// the loop routine runs over and over again forever:
void loop() {
  // set the brightness of pin 9:
  analogWrite(led, brightness);
  // change the brightness for next time through the loop:
  brightness = brightness + fadeAmount;
  // reverse the direction of the fading at the ends of the fade:
  if (brightness <= 0 || brightness >= 255) {
    fadeAmount = -fadeAmount;
  }
  // wait for 30 milliseconds to see the dimming effect
  delay(30);
}

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

А если один и тот же код должен работать сразу под несколькими микроконтроллерами? А если и с разной архитектурой. Конечно, никто не спорит, что в большинстве случаев код на ассемблере получится меньше по размеру и скорее всего будет работать быстрее, нежели код, написанный с применением фреймворка Arduino или ASF. Но жизнь такова, что труд разработчика куда дороже, чем «железо» с которым он работает. Исключения, разумеется, есть и тут. Если разрабатывается устройство, которое будет выпускаться миллионными тиражами, то да, экономия на коде и как следствие на железе может дать существенную экономию, а может и не дать, если подразумевается последующая поддержка устройств.

Мы уже поняли, что Arduino это экосистема, фреймворк, а что еще? Еще Arduino — интегрированная среда разработки (Integrated Development Environment, IDE). Это такой программный продукт, не выходя их которого и не отвлекаясь на прочие программулины и тулзы можно написать, скомпилировать и задеплоить (в нашем случае прошить в микроконтроллер) микропрограмму. В своих статьях я уже не раз отмечал, что Arduino IDE — очень простая в освоении и работе система. В ней нет огромного количества функций, в которых можно утонуть, она проста как автомат Калашникова, работает почти безотказно. Более того, Arduino IDE расширяема. В ней можно программировать не только платы Arduino на основе микроконтроллеров AVR, но и множество других. Достаточно только установить соответствующий ToolChain и Framework. Как правило, процедура осуществляется легко и непринужденно через BoardsManager. Именно благодаря ей в Arduino IDE можно вольготно программировать микроконтроллеры на основе SAM (Cortex), ESP32, ESP8266, многочисленные системы на основе процессоров Intel для IoT и многие другие.

Но и это еще не все. Если вам не нравится фреймворк Arduino, в Arduino IDE вы можете установить другой фреймворк. Совсем недавно я узнал, что можно использовать, например, MiniCore, MightyCore и другие вариации от MCUDude. Эти фреймворки расширяют возможности использования микроконтроллеров AVR и при этом остается совместимость со стандартным Arduino. Возможно, что существуют и другие реализации, автор просто не изучал глубоко данный вопрос. Хотя… Хотите ли вы использовать систему реального времени с многозадачностью при программировании микроконтроллера из-под Arduino IDE? А такая возможность есть уже сейчас. Зовется она Simba и работает с AVR, SAM и ESP32.

Еще одно преимущество Arduino IDE — возможность разделения единого файла на отдельные части. Предположим, что ваш скетч получился излишне большим и вы начинаете в нем путаться. Можно, конечно, пойти стандартным путем, создать новый файл с исходным кодом, создать заголовочный файл и подключить его через директиву include. Но гораздо проще, для небольших проектов, просто разделить один большой файл на несколько маленьких, прямо в Arduino IDE и без всяких заголовочных файлов. Красота. А еще в Arduino IDE можно использовать для редактирования кода внешний редактор. Например, Visual Studio Code, Atom или Notepad++. Только вот в тот момент, когда вам захотелось использовать внешний редактор, стоит подумать о переходе на другую среду разработки, с большим удобством для программиста.

Итак, о недостатках Arduino IDE. Один из моих проектов разросся до такого размера, что по непонятным для меня, абсолютно мистическим причинам код компилировался через раз на третий. Хотя никаких изменений никто не вносил. Мелочь, а жутко, до покалываний под ногтями, неприятно. Что будет, если вдруг код совсем перестанет компилироваться, хотя еще 10 минут назад все было превосходно, а с тех пор никаких изменений не вносилось?

В Arduino IDE напрочь отсутствует версиализация (и контроль версий) и какая-либо возможность по работе с ней прямо из среды. Я выкручивался примитивнейшим образом, когда нужно было начать новую версию, я просто делал «Сохранить как …» и изменял имя скетча, обновляя версию в имени и все более-менее работало. Продвинутые разработчики скажут, что мол дескать можно было бы использовать и внешнюю систему, но мне хотелось бы работать из интегрированной среды, а не выполнять кучу манипуляций после финализации очередной версии. Для малых и простых проектов можно обойтись без системы контроля версий, но если делать что-то немного большее, то себе дороже не использовать проверенные годами и телами программистов практики.

Что еще? В Arduino IDE напрочь отсутствует хоть какой-то вид отладчика. Единственным средством по отладке кода является обыкновенный Serial.print. Который проставляется в местах хоть как-то объясняющих логику выполнения программы. Без отладчика с серьёзным проектом работать просто невозможно. Тем более, что старшие модели микроконтроллеров поддерживают отладку прямо в чипе, останавливая выполнение и предоставляя всю служебную информацию. Поиск ошибок с отладчиком осуществляется на порядок быстрее, тратится куда меньше драгоценных калорий мозговой активности. Тут же сразу хочу вставить три копейки про Atmel Studio 7. Да, в этой IDE есть отладчик, и она поддерживает отладку на чипе посредством специальных средств. Есть в Atmel Studio и эмуляция микроконтроллеров, когда отладку можно совершить без наличия физического микроконтроллера, только вот в эмуляторе отсутствует периферия, а как правило ошибки ищутся в последствии обработки кнопок, сигналов с датчиков и прочих информационных потоков. Но идем дальше.

Когда-то данным давно, когда компьютеры были большими, программисты писали код на перфокартах, потом появились терминалы и код начали набирать на клавиатуре. С тех пор компьютеры изменились, мой мобильный телефон меньше в миллион раз и во столько же мощнее, чем самый мощный компьютер сорок лет тому назад. А программы люди по-прежнему пишут при помощи всего десяти пальцев (хотя некоторые уникумы могут писать код и с применением меньшего количества пальцев, но не будем о них). Многократные попытки применения визуального программирования или программирования без программирования, так и остаются попытками, широкого применения парадигма упрощенной алгоритмизации не нашла. И мы, все так же, как и сорок лет тому назад, вводим программу буква за буквой, операнд за переменной, функция за классом. Мало что поменялось в труде разработчика, появились лишь незначительные улучшения. Но их нет в Arduino IDE. Например, я не могу найти объявление переменной находясь где-то в коде и быстро понять какого она типа (для этого я именую переменные встраивая тип в имя, например, ulSuperValue12 относится к типу Unsigned Long). Я не могу сразу же получить список всех методов объекта, а еще лучше с их описанием, у меня нет подсказки об ошибках в то время, как я ввожу код. В других IDE есть, а в Arduino IDE только форматирование, да folding кода. Однажды я потратил несколько часов разбираясь, почему один и тот же код нормально работает с esp8266 и некорректно себя ведет с Atmega328P. А дело было в размерности двух переменных. В тулчейне esp8266 все целочисленные переменные имеют размерность в 4 байта, а в AVR тулчейне из-за ограничения в объеме памяти для int используется 2 байта, а для long уже 4. Вот и происходило округление при компиляции, а я потом гадал, почему код, выглядящий нормально, нормально не работает. Да, подобная ошибка есть ошибка разработчика, но на то мы и люди, чтобы их совершать. А в других IDE подобное пометилось бы красным сразу, еще до компиляции.

Вот мы и подобрались к тому, что Arduino IDE, конечно, здорово и незаменимо для начинающего, но с определенного момента нужно что-то более живое.

Что такое PlatformIO

Знакомство в PlatformIO начнем с текстового редактора Visual Studio Code. Да-да, VSCode это текстовой редактор, ориентированный на программистов, на написание исходного кода на различных языках, и оттого жутко навороченный. VSCode не просто редактор, а почти интегрированная среда разработки. Именно почти и совсем чуть-чуть почти, поскольку VSCode используется механизм расширений и его набор функций может разрастаться почти до бесконечности. Хотите писать на C? Пожалуйста, устанавливаете расширение для C и вперед, с песнями и карточными играми. Пишите код, компилируете его, всё не выходя из VSCode.

VSCode весьма активно развивается Microsoft и имеет огромное сообщество. VSCode отчаянно соперничает с другим текстовым редактором для программистов — Atom. Atom обладает почти тем же набором функций, что и VSCode. Тут поддерживаются расширения, присутствует интеграция с Git и GitHub, изменяются темы, присутствуют автоматическое дополнение и множество всех функций, что есть в VSCode. И при выборе с каким же редактором работать совместно с PlatformIO пользователь обычно впадает в ступор, так как и то и другое обладает феноменальными способностями. Вот, только что выбрать? Если не полагаться на чужое мнение, то следует попробовать и Atom, и VSCode. А если почитать обзоры, то VSCode имеет незначительный перевес в голосах. Для меня же чашу весов в сторону VSCode перевесило как раз наличие бо́льшего сообщества, чем у Atom и поддержки софтверного гиганта Microsoft.

Кстати, PlatformIO работает как с VSCode, так и с Atom (вообще PlatformIO работает с 14-тью редакторами, offline и облачными). Однако, следует сделать небольшое отступление и дать пояснение о том, из чего состоит сама PlatformIO.

По сути, PlatformIO это набор из компонентов, основным из которых является PlatfromIO Core. Компонент ответственный за компиляцию, обновление и установку библиотек, именно в Core гнездятся все тулчейны и фреймворки. Для полноценной работы с PlatformIO достаточно только Core компонента. Пишите код в блокноте или FAR-е, работаете исключительно из командной строки. А почему бы и нет?

Следующий компонент, особенно если хочется больше комфорта, PlatformIO IDE. Та самая «интегрированная среда разработки», которую все так нахваливают. Хотя, если честно, то в том же VSCode PlatformIO IDE выглядит как добавка к статусной строке, пунктик в выпадающем меню, да заглавная страничка с доступом ко всем основным функциям наподобие установки новой библиотеки или выбора конкретной платы, под которую разрабатывается код.

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

Плюшки и не плюшки связки PlatformIO с VSCode

Начнем со всех тех удобств, что предоставляет VSCode разработчику. Про возможность менять темы, шрифты и все такое прочее, я упоминать не буду. Тему можно поменять, хоть и не очень прямо, и в Arduino IDE, шрифт, впрочем, тоже. А вот скорость работы просто удивляет. VSCode работает раза так в 10, если не меньше, оперативнее, чем Arduino IDE. Начиная от запуска и заканчивая компиляцией. Система настолько отзывчивая, что с ней просто приятно работать.

Для удобства программиста в VSCode есть всё, о чем только можно мечтать, а чего нету, то можно установить, как плагин.

При работе с большим и длинным файлом возникает проблема, связанная с навигацией по коду. Найти нужный участок не всегда удается быстро. В VSCode проблема решается сразу несколькими путями. Присутствует общий обзор всего файла. Вкупе с подсветкой текста можно очень быстро перепрыгивать по миниатюре в нужное место. К примеру, нужны мне дефиниции #define. Я знаю, что они где-то в начале идут. На миниатюре они фиолетовые. Нажал туда и опа, уже на нужном месте. А можно просто перейти к описанию встретившейся переменной или же выбрать ее (или любую функцию или класс) в списке всех функций и переменных.

VSCode, Platformio, mini view

Просмотр всего кода сразу

Вообще работать с текстом в VSCode — сплошное удовольствие. Нужно как-то попробовать начать писать в нем художественные произведения. А вдруг окажется куда удобнее, чем в Scrivener или Word? В VSCode можно открыть сразу несколько файлов. При желании их можно закрыть, перемещать, открыть несколько панелей с файлами, открыть несколько вкладок одного файла и прочее, прочее, прочее. Не хуже работает и поиск. Ищешь структуру, и она подсвечивается в миниатюре. Про сворачивание кода я распространяться не буду, оно есть даже и в Arduino IDE.

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

Особо стоит отменить работу IntelliSense. Той самой примочки, о которой только могут мечтать пользователи Arduino IDE. IntelliSense подсвечивает потенциальные ошибки в коде, в тот самый момент, как вы их совершаете. Система дает более развернутое описание ошибок компиляции. Навелся на подчеркнутое и получил совет, что с этим можно сделать. А вот наличие автодополнения делает мой день каждый раз, когда я сажусь и расчехляю VSCode с установленным PlatformIO. Начинаешь писать код, и система сама подсказывает какие функции могут начинаться с написанного или же какие методы и поля есть у введенной структуры. Удобно неимоверно. А для особо продвинутых работников клавиатуры присутствует отдушина в виде разного рода шорткодов. Допустим вы пишите весьма однообразный код, который имеет множество повторяющихся элементов. Так чтоб не вводить их каждый раз руками, можно просто использовать условные обозначения, которые автоматически развернутся в заранее подготовленную структуру. В общем, всех вкусностей и полезностей не сосчитаешь, и не переберешь.

Но у такой повышенной хипкости есть и свои, вполне очевидные недостатки. Система позволяет установить сотни улучшений, десятки языков и множество диалектов. При подобном винегрете начинает что-то работать не так. Самый простой пример. Помимо PlatformIO в системе есть дополнение Arduino (выпущенное Microsoft). Дополнение почти полностью повторяет по функциям оригинальную IDE, но при этом периодически возникают коллизии с PlatfromIO. Поэтому я рекомендую, если уж стали работать с PlatformIO, то дополнительный модуль с Arduino не подключаем. Для этого у нас есть родное ПО. Или же при подключении библиотек и новых классов. IntelliSense подхватывает их ой как не сразу и приходиться перезагружать VSCode или же руками перестраивать индексы VSCode, благо такая возможность присутствует и выполняется лишь одним нажатием пункта в меню (операцию можно вызвать, например, через Run Task… или через меню PlatformIO).

Но, не смотря на все эти заморочки, системой пользовать не просто удобно, а приятно. Нужно только с ней разобраться. Идем дальше.

Структура проекта PlatformIO + VSCode и что такое Workspace

После Arduino IDE или других интегрированных сред разработки, просто так взять и разобраться в нагромождении меню и папочек в PlatformIO IDE на базе VSCode не так-то уж и просто. Требуется некоторое время на то, чтобы начать понимать, как же все же оно все вместе работает.

vscode, программа

Общий вид структуры файлов

Начнем со структуры папок нашей комбинации PlatformIO и VSCode. По умолчанию структурой, с которой работает VSCode является проект. Один проект помещается в отдельную папку, в которое располагаются поддиректории. VSCode, как редактор, может работать и с единичным файлом, а может и с более крупной структурой Workspace, но о ней ниже. В папке располагаются следующие подпапки, сразу буду давать пояснения, что там и как:

  • .git — скрытая папка со служебными файлами Git, если папка проекта подключена к соответствующей системе управления версиями.
  • .pio — все волшебство PlatformIO хранится тут. Сюда происходит компиляция исходного кода, сюда помещаются библиотеки проекта устанавливаемые через менеджер библиотек PlatformIO, тут же хранятся откомпилированные библиотеки фреймворка для последующей линковки. В общем в эту папку залезаем только за готовым результатом. Если вы компилируете проект сразу для нескольких плат/платформ, то на каждую будет создана своя отдельная директория. Процедура Clean в блоке компиляции PlatformIO очистит эту папку и при следующей компиляции она произойдет медленнее из-за перекомпиляции всего. В этой особенности наличия предкомпилированных библиотек и заключается повышенная скорость компиляции в PlatformIO.
  • .vscode — служебная папка VSCode, здесь хранятся настройки самого VSCode в разрезе проекта, а так же базы для служб на подобие IntelliSense (подсказывают код, ловят ошибки и тому подобное).
  • boards — если вы используете только штатные платы для программирования в PlatformIO, то эта папка отсутствует в списке.
  • include — папка для хранения заголовочных файлов, если вы работаете на C/C++. PlatformIO в отличие от Arduino IDE не может просто так взять и разделить файл исходного кода на несколько более мелких, с которыми проще работать. Вычленение отдельных блоков кода возможно только с указанием последующей директивы include и с созданием заголовочного файла с расширением .h, впрочем, я складирую заголовочные файлы в папке src, не знаю почему.
  • lib — папка для частных библиотек проекта. Некоторые пользователи, и я в том числе, недоумевают, почему при установке библиотеки через менеджера библиотек не в глобальный контекст, а в контекст конкретного проекта они попадают в .pio, а не в lib. Логика создателей PlatformIO следующая: все стандартные библиотеки устанавливаются через Library Manager, все стандартные библиотеки обновляются, если пользователю нужна библиотека в lib, то он устанавливает ее руками в эту папку. Всё.
  • src — папка для хранения нашего исходного кода. То место, куда мы добавляем, в том числе, и новые файлики. Файл по умолчанию main.cpp.
  • test — специальная папка для модульного тестирования исходного кода. Подробнее о нем можно узнать в документации на PlatformIO.

Помимо папок, стоит обратить еще внимание и на несколько файлов, которые обычно располагаются в корне проекта:

  • .gitignore — файл с простым перечислением каталогов и файлов, которые не стоит синхронизировать с Git. Сюда вносятся настройки VSCode На локальной машине, весь каталог .pio, можно надобавлять еще много чего.
  • .travis.yml — данный файл является конфигурационным файлом надстройки Travis, помогающей в синхронизации исходного кода, в том числе и с GitHub. Подробнее в документации.
  • platformio.ini — пожалуй самый интересный из файлов корневой директории в PlatformIO IDE. Данный файл позволяет изменять конфигурацию IDE, включая используемые библиотеки, платы, фреймворки и все остальное, специально для проекта. Рекомендую изучать структуру и предикаты данного файла в первую очередь.

Все вышесказанное относилось к проектам-папкам. Но в определенный момент времени разработчик обнаруживает, что каким-то чудесным образом у него вместо папки-проекта образовалась непонятная рабочая область (Workspace). Наличие и функции Workpace нигде четко и толком не объясняются. В документации Microsoft все настолько неясно изложено, что даже после трехкратного ознакомления так и не остается трезвого понимания того, что такое Workspace и на кой ляд он нужен. Попробую все же дать мои объяснения по поводу того, что это такое и зачем оно нам может пригодиться.

Начну с того, что в одном экземпляре VSCode можно открыть только одну папку проекта. Если попытаетесь открыть еще одну папку, то текущий проект закроется и откроется новая папка. Если вдруг возникло непреодолимое желание работать сразу с двумя папками-проектами, то можно запустить еще раз VSCode и открыть нужный проект в нем. А можно поступить хитрее.

add folder to workspace, file, vscode, platformio

Добавляем каталог к рабочей области

При уже открытом проекте идем в меню File и вызываем подменю Add Folder to Workspace… В этом случае автоматически создается рабочая область в которой будет уже два проекта-папки. И можно заниматься редактированием файлов в них обоих. Таким образом можно добавить в рабочую область еще проектов. А затем сохранить всю рабочую область (по факту сохраняется одинокий файлик, при открытии которого в последствии откроется эта самая рабочая область). Других способов по созданию рабочих областей мне обнаружить не удалось.

Зачем же нужны рабочие области? При работе с крупными наборами проектов, когда этих наборов несколько, имеет смысл их группировать и открывать вместе. Более того, в рабочей области можно использовать специфические настройки VSCode. Например, для одной группы проектов будет использовать серая цветовая схема, а для другой черная и более мелкий шрифт.

Удалять папки проектов из рабочей области можно безболезненно, они удаляются только в рабочей области, а физически остаются на диске. Важно не перепутать и не удалить папку внутри проекта, а не удалить папку проекта из рабочей области.

Добавляем свою плату в проект (минимум 2 способа)

Если у вас вдруг возникает потребность в добавлении своей собственной платы в PlatformIO, то провернуть такую манипуляцию можно двумя способами. Самый достоверный и грозящий наименьшими проблемами — добавить плату в папку boards проекта. В этом случае плата будет синхронизирована с конкретным проектом и не будет риска, что она будет использована в другом проекте, там, где не должна или же при синхронизации через интернет на новом ПК, не будет описания этой платы.

{
    "build": {
      "core": "arduino",
      "extra_flags": "-DARDUINO_AVR_ATmega328P",
      "f_cpu": "8000000L",
      "mcu": "atmega328p",
      "variant": "standard"
    },
    "frameworks": [
      "arduino",
      "simba"
    ],
    "fuses": {
        "efuse": "0xFD",
        "hfuse": "0xD0",
        "lfuse": "0xD2",
        "lock": "0x0F"
      },
    "name": "ATmega328P BB 8Mhz",
    "upload": {
      "maximum_ram_size": 2048,
      "maximum_size": 32256,
      "protocol": "stk500v2",
      "require_upload_port": true,
      "speed": 57600,
      "flags": "-v -e"
    },
    "url": "https://blog.kvv213.com",
    "vendor": "kvv213"
  }

Выше я привел описание моей любимой Atmega328P без какой-либо обвязки. Имя файла выбираем в соответствии с блоком "name", в моем случае оно соответственно ATmega328P BB 8Mhz.json.

В описании указываем такие настройки, как частота процессора, варианты компиляции, флаги для компилятора из тулчейна, используемые протоколы и флаги для утилиты прошивки и все такое прочее.

При необходимости модификации уже существующей платы, можно не создавать новую, а внести необходимые изменения через platfromio.ini:

[platformio]
default_envs = ATmega328P BB 8Mhz
[env:d1_mini]
platform = espressif8266
board = d1_mini
framework = arduino
upload_port = COM3
monitor_speed = 19200 
lib_deps =
    1106
[env:ATmega328P]
platform = atmelavr
board = ATmega328P
framework = arduino
upload_port = COM3
upload_protocol= stk500v2
upload_flags = 
    -v
    -e
lib_deps =
    1106    
[env:ATmega328P BB 8Mhz]
platform = atmelavr
board = ATmega328P BB 8Mhz
framework = arduino
monitor_port = COM5
upload_port = COM3
upload_protocol= stk500v2
upload_flags = 
    -v
    -e
lib_deps =
    1106

В данном примере для Atmega328P существует два варианта компиляции прошивки (стандартная ATmega328P и созданная мное ATmega328P BB 8MHz), с подключением библиотеки с идентификатором 1106, и особыми флагами для загрузчика прошивки.

Второй способ не так далеко ушел от первого, но плата добавляется на глобальном уровне (на вашем ПК, разумеется). Создается точно такой же файл и складывается в папку соответствующей аппаратной платформы PlatformIO, для AVR это будет где-то тут .platformio\platforms\atmelavr\boards\. Кстати, там же можно посмотреть и на примеры заполнения файлов плат.

Загрузка через не Arduino загрузчики

Сперва может показаться, что PlatformIO умеет работать только с платами Arduino. Но это далеко не так. PlatfromIO, благодаря усилиям разработчиков и многочисленного сообщества может работать с сотнями плат и прошивать большинство их них прямо не выходя из среды.

В предыдущем абзаце я пояснил каким образом можно добавить свою плату для компиляции. Там же указывается и то, каким образом ее прошивать. Альтернативно те же самые условия можно указать и в файле конфигурации проекта platformio.ini.

Для примера рассмотрим все ту же банальную Atmega328P. В файле описании платы есть как минимум три важных блока:

1. Описание «железа» платы.

"build": {
      "core": "arduino",
      "extra_flags": "-DARDUINO_AVR_ATmega328P",
      "f_cpu": "8000000L",
      "mcu": "atmega328p",
      "variant": "standard"
    },

Как мы видим, в этом блоке мы прописываем дополнительные флаги для компиляции, указываем частоту процессора (в данном случае это 8 МГц, так как чип работает без внешнего осциллятора), собственно тип микроконтроллера и прочие специфические параметры конкретного тулчейна (тут он у нас AVR).

  "build": {
    "core": "esp8266",
    "extra_flags": "-DESP8266 -DARDUINO_ARCH_ESP8266 -DARDUINO_ESP8266_WEMOS_D1MINI",
    "f_cpu": "80000000L",
    "f_flash": "40000000L",
    "flash_mode": "dio",
    "ldscript": "eagle.flash.4m1m.ld",
    "mcu": "esp8266",
    "variant": "d1_mini"
  },

На коде выше приведен блок build от WeMos D1 R2 mini. Другой тулчейн, другие параметры. Отсюда сразу же напрашивается вывод о том, где посмотреть информацию по всем этим флагам — в описании тулчейна, где же еще. Нужно добраться до папки platforms в .platformio, там все тулчейны и устанавливаются.

2. Специфичная настройка железа микроконтроллера.

    "fuses": {
        "efuse": "0xFD",
        "hfuse": "0xD0",
        "lfuse": "0xD2",
        "lock": "0x0F"
      },

Пока PlatrofmIO не умеет прошивать фьюзы и загрузчики, но ситуация может поменяться в ближайшем будущем. Для этих целей заранее можно прописать специфичные «предохранители» для конкретного микроконтроллера. Точное значение фьюзов на тех МК, где такую операцию можно проводить, необходимо добывать из официальных спецификаций. В приведенном выше примере Atmega328P настраивается на работу без чипа и с работающим вводом Reset. К слову, у WeMos такой штуки просто нет, все прошивается через загрузчик.

3. Специфика загрузчика.

    "upload": {
      "maximum_ram_size": 2048,
      "maximum_size": 32256,
      "protocol": "stk500v2",
      "require_upload_port": true,
      "speed": 57600,
      "flags": "-v -e"
    },

В этом блоке прописываются конкретные указания, как и чем прошивать. Соответственно для Atmega328P указываются максимальные значения по размерам кода и ОЗУ, указывается скорость, на которой стоит прошивать (МК без внешнего кварца шьется на пониженной скорости), указывается конкретный протокол прошивки. В моем случае это stk500v2, так как я использую программатор, работающий с этим протоколом.

  "upload": {
    "maximum_ram_size": 81920,
    "maximum_size": 4194304,
    "require_upload_port": true,
    "resetmethod": "nodemcu",
    "speed": 115200
  },

У WeMos указываются другие параметры, так нет протокола, он у них один, зато указывается способ сброса устройства. Какие протоколы используются можно глянуть в документации PlatformIO, там даны основные виды. Для AVR так же можно посмотреть, какие протоколы поддерживает avrdude (под AVR все шьется исключительно через него).

Таким образом система дает небывалую гибкость. Настроить получится не так быстро, как в оригинальном Arduino IDE, но если разобраться и прочувствовать весь доступный контроль, то будет уже трудно вернуться к классической среде разработки из Италии.

Используем Git и GitHub

В Visual Studio Code уже встроена поддержка Git (распределённая система управления версиями). Почему? Видимо потому, что один из самых популярных репозиторных сервисов — GitHub, был не так давно приобретен Microsoft. Вообще поведение редмондского гиганта в последнее время весьма странное. То изобрел Community-версию своей интегрированной среды разработки Visual Studio, бесплатную заметьте, то разрешил бесплатно создавать частные репозитарии на GitHub. И что дальше? Бесплатные версии Windows и Office?

Но вернемся к Git и GitHub. Поддержка Git уже встроена в Visual Studio Code и ее можно использовать если в вашей системе установлен Git и к репозитарию присоединен проект. При создании нового проекта на GitHub дается простенькая инструкция что необходимо сделать, а подключение уже существующего проекта к локальной папке можно провернуть по следующей несложной инструкции. Хотя можно подключать репозиторий и напрямую из меню PlatformIO. Кому какой способ больше нравится.

Git и GitHub пользуются, наверное, миллионы пользователей. И в случае какого-либо затруднения можно получить помощь и поддержку почти незамедлительно. А наличие частных репозитариев в неограниченном количестве, да еще и бесплатно, позволит вам упражняться в кодотворчестве сколь угодно часто.

Итак, для начала использования Git и GitHub необходимо скачать версию Git под вашу операционную систему, подключить проект и начать пользоваться вкладкой Source Control. Управление Git простое и сосредоточено в нижней строке состояния. Там можно выбрать текущую ветку исходного кода, узреть сколько изменений необходимо интегрировать в репозитарий, если таковые есть. Ну и в общем-то все. Информация по отдельным изменениям выводится во вкладку Source Control.

Помимо GitHub можно использовать любое другое хранилище репозитариев под управлением Git. А можно вообще установить расширение для VSCode и использовать в качестве системы управления версиями, например, SVN или Azure DevOps. Выбор остается, в общем-то, за вами.

Вместо вывода

Увы и ах, время Arduino IDE для меня прошло безвозвратно. Те несколько лет, что мы провели вместе останутся в моей памяти до самого последнего дня. На смену простецкой системы пришел настоящий монстр PlatformIO вместе с еще более монстроидальным VSCode. Увы и ах, прости прощай…



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