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

Урок 1. Знакомство с микроконтроллером

Описание микроконтроллерного модуля

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

Экосистема VBCores поддерживается и развивается лабораторией робототехники института механики МГУ и проектом Voltbro ("Братья Вольт"), разработчиком робототехнического оборудования и образовательных методик в области робототехники.

Сердце проекта - микроконтроллерный модуль VB32G4 с мощным микроконтроллером STM32G474RE, преобразователем питания, позволяющий работать с напряжением до 50 вольт и выводом коммуникационной шины CAN/CANFD. Благодаря своей совместимости с различными средами разработки и библиотеками, подходит как для опытных, так и для начинающих разработчиков с минимальным входным порогом знаний в области электроники и программирования. Этот модуль представляет из себя электронную плату в компактном форм-факторе, несущую минимально необходимый набор микросхем, общих для всех электронных устройств робота. Для построения внутри робота распределенной системы управляющих устройств используется шина CAN или CANFD, работа которой организована через встроенный приемопередатчик.

Основной модуль (рис. 1) предназначен для пайки на функциональные платы. Он спроектирован как встраиваемое устройство, имеет односторонний монтаж. Порт программирования и отладки выведен на отдельный разъем, легко доступный даже в составе готового устройства.

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

Благодаря примерам типовых программ, таких как работа с интерфейсами физического уровня, протоколами связи, управление различными типами двигателей, обработка данных с датчиков, разработка становится гораздо проще.

qj

Рис. 1. Модуль VBCore VB32G4

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

qj

Рис. 2. Электронные модули проекта VBCores: а – драйвер бесколлекторного двигателя, б – преобразователь питания 50В в 12В, в – преобразователь интерфейса Ethernet-CAN, г – программатор для микроконтроллеров STM32.

В реальности перечень плат гораздо больше, чем представлено на рис. 2. Со списком всех плат можно ознакомиться в документации проекта.

В рамках текущего цикла лабораторных работ мы будем пользоваться платой VBCores Eval Board (рис. 3). Эта плата спроектирована таким образом, чтобы начинающему разработчику было проще разобраться в программировании микроконтроллеров. На ней установлены разъемы, совместимые с платами расширения Arduino и STM32 Nucleo. Это позволяет подключать весь спектр уже разработанных дополнительных устройств. Например, вы можете расширить ваши возможности, подключив устройства для работы с Ethernet и Bluetooth, установить силовые реле и аккумуляторы, или позволить работать c мобильной сетью или Wi-Fi. Более того, к плате можно прикрепить беспаечную макетную плату (в простонародье — бредборд). Он представляет собой плату с отверстиями, которые соединены внутри платы определенным образом. С помощью него можно без пайки реализовать собственные электрические схемы. К примеру, с помощью этого устройства вы можете подключить к микроконтроллеру резисторы, конденсаторы, различные датчики и микросхемы. Другим преимуществом Eval Board является то, что установка микроконтроллерного модуля VBCore VB32G4 происходит без пайки. Т.е. даже если в процессе работы вы совершите ошибку и у модуля сгорит какой-то компонент (например преобразователь питания или сам микроконтроллер), то вам не нужно будет менять всю плату целиком. Достаточно будет лишь заменить микроконтроллерный модуль.

qj

Рис. 3. Фотография платы VBCores Eval Board

Hello, World!

Приступим к разработке собственных проектов. В программировании изучение нового языка традиционно начинается с программы Hello, World!. Чаще всего это простая программа, которая выводит приветствие на экран и заодно знакомит с новым языком – его синтаксисом и структурой программы. Не будем нарушать эту традицию, тем более ей уже больше 40 лет. В мире электроники аналог Hello, World! показывает, как мигать светодиодом.

В модуль уже встроены два светодиода. Они обозначены как LD1 и LD2 и подключены к выводам микроконтроллера. Чтобы понять, куда подключается то или иное устройство, разработчики используют схемы, поставляемые вместе с документацией. Давайте узнаем, куда подключены наши светодиоды. Откройте схему выводов модуля VB32G4 из документации. На ней представлена вся информация о том, за что отвечает каждый вывод платы. Пока не будем вдаваться в излишние подробности по каждому элементу схемы. Для начала нам нужно просто определить подключение светодиодов. Найдите на схеме два блока синего цвета LED1 и LED2 (подсказка: слева и слева-снизу) – они как раз обозначают встроенные светодиоды. Эти блоки идут к желтым прямоугольникам, которые означают номер ножки микроконтроллера. Таким образом мы видим, что LED1 подключен к PD2, а LED2 – к PA5. Эта информация нам сейчас понадобится в процессе написания программы.

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

warning

Не забудьте подготовить и настроить всё необходимое ПО! Это можно сделать в разделе Подготовка

Если после всей настройки при открытии Arduino IDE вы видите уведомление Updates are available for some of your libraries, обязательно нажмите Later, иначе библиотеки для VBCores не будут корректно работать.

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

void setup() {
// put your setup code here, to run once:

}

void loop() {
// put your main code here, to run repeatedly:

}

Если вы видите что-то другое, то выберите пункт меню File -> New Sketch или нажмите Ctrl+N.

Каждый раз при создании нового файла, среда вписывает в него заранее сформированный шаблон, состоящий из двух функций. Функция setup() служит для инициализации программы, она запускается только один раз, когда вы подаете питание на плату или нажимает на сброс. Чаще всего её используют для назначения режима работы выводов или для выполнения команд, которые необходимо выполнить в момент загрузки программы. Функция loop() вызывается постоянно в бесконечном цикле пока на плату подано питание.

Обе функции должны быть в каждом скетче, даже если вы их не используете. Дело в том, что при запуске микроконтроллера, начинает работать встроенная микропрограмма, которая вызывает эти функции. Если у вас не будет одной из этих функций, или они, наоборот, будут присутствовать более одного раза, компилятор выдаст ошибку.

Напишите следующий код:

#include <VBCoreG4_arduino_system.h>

void setup() {
// инициализировать цифровой вывод LED2 в качестве выхода.
pinMode(PA5, OUTPUT);
}

// функция loop вызывается постоянно в бесконечном цикле
void loop() {
digitalWrite(PA5, HIGH); // включаем светодиод
delay(1000); // ждем 1 секунду
digitalWrite(PA5, LOW); // выключаем светодиод
delay(1000); // ждем 1 секунду
}

Внимательно изучите его и комментарии к нему. Разберем этот код подробнее:

#include <VBCoreG4_arduino_system.h>

В этой строке происходит подключение библиотеки VBCoreG4_arduino_system, которую вы установили, выполняя раздел Подготовка. Эту библиотеку нужно подключать к каждой программе, которую вы собираетесь загружать на плату VBCore VB32G4, используя базовые библиотеки Arduino.

Далее в программе мы видим использование трёх новых функций: pinMode(), digitalWrite() и delay(). Разберем каждую из них:

  • pinMode(pin, mode) устанавливает режим работы заданного вывода pin на вход или выход. В режиме входа mode=INPUT пин считывает напряжение от 0 до 3.3 вольт, а в режиме выхода mode=OUTPUT – выдает на пине напряжение 0 или 3.3 вольт с максимальным током 40 мА. В нашем случае, так как светодиод LED2 подключен к ножке PA5, мы указываем pin=PA5. А так как МК должен работать на вывод, то значение pin=OUTPUT.
  • digitalWrite(pin, value) позволяет выдавать цифровой сигнал, имеющий два значения – 0 или 1 (0 вольт или 3.3 вольт соответственно). К пинам микроконтроллера нельзя подключать устройства, потребляющие ток более 40 мА, так как основное назначение микроконтроллера — это управление другими устройствами при помощи логических сигналов. Если к пину подключить устройство, потребляющее ток больше указанного значения, то пин может выгореть. Поэтому к выводам микроконтроллера не следует подключать ничего мощнее светодиода.
  • delay(ms) останавливает выполнение программы на заданное время в милисекундах, указанное в параметре ms.

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

Переходим к следующему шагу, а именно загрузке программы в память микроконтроллера:

  1. Подключите программатор VBCore STM32 Programmer одним концом к плате микроконтроллера, а другим – к вашему рабочему компьютеру через USB, как показано на изображении:
qj

Рис. 4. Подключение платы Eval Board к компьютеру с помощью программатора.

  1. Скомпилируйте программу нажатием на кнопку с символом галочки в верхней части Arduino IDE:
qj

Рис. 5. Компиляция скетча в Arduino IDE

  1. Если компиляция прошла успешно, и компилятор не выдал никаких ошибок, загрузите программу нажатием кнопки с символом стрелки (находится справа от галочки).

Если вы всё сделали правильно, то светодиод LED2 должен начать мигать, меняя своё состояние 1 раз в секунду. При возникновении ошибок во время компиляции, внимательно проверьте, правильно ли вы перепечтали/скопировали код. Если произошли проблемы во время загрузки кода на плату, то убедитесь, что вы настроили всё именно так, как было описано в разделе по подготовке к курсу и правильно загрузили прошивку на плату

Чтение цифрового сигнала

Чтение сигнала нужно, чтобы получить информацию от внешнего устройства, подключенного к определенному пину МК. Таким устройством может быть кнопка или любой датчик, формирующий высокий или низкий уровень сигнала в зависимости от ситуации. Получив сигнал, мы можем как-то на него отреагировать: включить светодиод, издать звук, запустить двигатель и даже отправить SMS-сообщение, если это необходимо.

Сделать это можно с помощью функции digitalRead(<номер_пина>). Она всегда возвращает либо HIGH, либо LOW:

  • Значение HIGH возвращается, если уровень сигнала превышает примерно половину опорного напряжения (на плате VBCore это 1.6 В). В программе HIGH соответствует логической 1.
  • Значение LOW получаем при низком уровне сигнала (меньше 1.6 В). В скетче этому сигналу соответствует значение константы LOW (логический 0).

Чтобы понять номер пина, к которому подключена кнопка, снова воспользуемся схемой выводов модуля. Найдите на ней синий блок под названием USR Button (он находится в левом нижнем углу) и пин, к которому этот блок подключен (должен быть PC13). Мы видим, что другой конец блока подключен к земле (GND). Это означает, что, когда кнопка нажата, мы будем получать значение LOW.

Давайте напишем программу, которая при нажатии на кнопку зажигает светодиод LED2:

#include <VBCoreG4_arduino_system.h>

void setup() {
// инициализировать цифровой вывод PA5 в качестве выхода
pinMode(PA5, OUTPUT);
// назначить вывод PC13 входом
pinMode(PC13, INPUT);
}

void loop() {
// считывание и инвертирование входного пина
int buttonState = !digitalRead(PC13);
// вывести состояние кнопки
digitalWrite(PA5, buttonState);
delay(10);
}

Переписывать комментарии не обязательно, но прочитать их нужно, чтобы понять, что делает программа. Скомпилируйте код и загрузите его на микроконтроллер. Давайте проверим, как работает программа. Мы видим, что когда кнопка нажата, то светодиод горит, но когда мы кнопку отпускаем, то светодиод продолжает гореть, но более тускло, моргает или вообще ведет себя непредсказуемо. В чём дело? Почему программа не работает?

Чтобы разобраться в этом, откроем электрическую схему платы. Найдите на ней нашу кнопку, которая обозначена как S1, и изучите её цепь подключения к микроконтроллеру. Мы видим, что одним концом кнопка подключена к земле GND. Цепь другого конца называется NC10, но при этом как будто обрывается. В разных электрических цепях часто можно встретить такое. На самом деле это не обрыв, а ссылка. Чтобы не загружать схему излишними линиями, схемотехники просто дают обозначение для цепей. И чтобы понять, куда идет нужная цепь, необходимо найти другую с точно таким же обозначением. В нашем случае, эта цепь идет к ножке 2 микросхемы IC5. Под блоком этой микросхемы вы увидите надпись STM32G474RE, а это как раз наш микроконтроллер. При этом ножка 2 на схеме означает пин PC13 микроконтроллера.

Рассмотрим этот участок цепи изолированно от всей остальной схемы:

qj

Рис. 6. Изолированный участок цепи с кнопкой и микроконтроллером

Если мы начнем читать данные, поступающие на пин PC13, то увидим, что при нажатии на кнопку, у нас действительно должен появлиться логический 0, т.к. ножка МК будет прижата к земле. Но если мы отпустим кнопку, то цепь окажется оборвана и схема по сути приобретет такой вид:

qj

Обрыв цепи при отпускании кнопки

Получается, что пин PC13 находится в подвешенном состоянии и при считывании нельзя определенно сказать, высокий на нем уровень напряжения или низкий, так как напряжения на нем в целом нет. Такое состояние еще называют высокоомным, высокоимпедансным или Z-состоянием. При этом провод, соединяющий пин платы с кнопкой, выполняет роль антенны для различных электромагнитных наводок. Именно эти наводки и заставляют контакт вести себя непредсказуемым образом, читая то 0, то 1. Чтобы устранить эту проблему, необходимо сделать так, чтобы в любом состоянии кнопки на пине PC13 было однозначное значение. Для этого нужно скорректировать схему следующим образом — подключить этот пин к источнику питания +3.3В через резистор номиналом 10 кОм:

qj

Рис. 7. Пин PC13 подключен к питанию через подтягивающий резистор.

Теперь, когда кнопка не нажата, можно со 100%-уверенностью говорить о том, что состояние на пине PC13HIGH, так как он подключен к питанию:

qj

Рис. 8. Если кнопка не нажата, то на PC13 поступает сигнал +3.3V

Но если нажать на кнопку, то ток пойдет по пути наименьшего сопротивления и значение на пине PC13 станет LOW:

qj

Рис. 9. Если кнопка нажата, то на PC13 поступает сигнал 0V

Этот добавленный в схему резистор называется подтягивающим, потому что до этого в неопределенном состоянии подтягивает потенциал ко входу +3.3В, делая его определенным — HIGH.

Номинал резистора рассчитывается исходя из максимально протекающего тока. Напомним, что максимальный ток, который способен выдать цифровой пин микроконтроллера STM32 — 40 мА (0,04 А). При напряжении 3.3В, по закону Ома, находим сопротивление участка цепи:

R=UI=>R=3.3В0.04А=82.5ОмR = \frac{U}{I} => R = \frac{3.3 В}{0.04 А} = 82.5 Ом

Таким образом минимально допустимый для использования номинал резистора — 82.5 Ом. В то же время, чтобы подтягивающий резистор, не оказывал влияния на остальные участки цепи при замыкании, рекомендуется выбирать намного больший номинал: от 1 до 10 кОм.

Мы также можем поменять местами питание и землю:

qj

Рис. 10. Схема со стягивающим резистором

В таком случае мы будем получать 0В или LOW, когда кнопка отпущена, и 3.3В или HIGH, когда кнопка нажата. В этой ситуации резистор называют стягивающим.

Вернемся к электрической схеме платы VBCore. Видно, что никакого подтягивающего резистора на ней нет, и может показаться, что разработчики допустили ошибку, создавая эту плату. В действительности никакой ошибки здесь нет. Все дело в том, что у микроконтроллера есть функция использования встроенного подтягивающего резистора, который подключается к выбранному пину. Чтобы инициализировать пин в режиме работы с подтягивающим резистором, нужно определить его как INPUT_PULLUP. Давайте перепишем программу, определив пин PC13 не как INPUT, а INPUT_PULLUP:

#include <VBCoreG4_arduino_system.h>

void setup() {
// инициализировать цифровой вывод PA5 в качестве выхода
pinMode(PA5, OUTPUT);
// назначить вывод PC13 входом c подтягивающим резистором
pinMode(PC13, INPUT_PULLUP);
}

void loop() {
// считывание и инвертирование входного пина
int buttonState = !digitalRead(PC13);
// вывести состояние кнопки
digitalWrite(PA5, buttonState);
delay(10);
}

Загрузите новый вариант программы и проверьте её работоспособность. Теперь всё должно функционировать, как мы задумали изначально.

Связь с компьютером

Описание интерфейса

При создании проектов часто требуется иметь возможность пересылать на компьютер какие-либо данные о состоянии датчиков или статусе работы программы. Также возникает необходимость принимать с компьютера данные, например, команды на выполнение определенных функций. Одним из самых популярных способов для передачи данных между электронными устройствами является протокол UART. Эта аббревиатура расшифровывается как Universal Asynchronous Receiver-Transmitter или Универсальный асинхронный приёмопередатчик. Часто его называют просто последовательным портом. Как правило все микроконтроллеры имеют встроенный узел связи UART, и STM32 не является исключением. Обмен данными происходит посредством USB, проходя через USB-UART мост, встроенный в программатор. Т. е. компьютер взаимодействует именно с USB-UART, а напрямую с микроконтроллером.

При подключении программатора к компьютеру, в системе Windows создаётся новый COM-порт (от англ. communication port). Вы можете узнать номер COM-порта, который присваивается модулю с помощью Диспетчера устройств. Чтобы его открыть, нажмите кнопку Win и начните печатать «Диспетчер устройств». Когда появится соответствующий ярлык, кликните по нему. В дереве диспетчера устройств раскройте список «Порты (COM и LTP)» и если модуль VBCore подключен, то вы увидите пункт STMicroelectronics STlink Virtual COM Port. Это и есть ваша подключенная плата. В названии в скобках будет указан номер COM-порта.

dispetcher

Рис. 11. Окно Диспетчера устройств, содержащее информацию о модуле VBCores.

Чтобы работать с портом на стороне компьютера, понадобится монитор порта - программа, которая умеет отправлять и читать данные с COM-порта. Таких программ много и подойдёт любая, но в Arduino IDE есть свой встроенный монитор порта, что очень удобно. Чтобы начать работу, нужно выбрать порт в меню Tool->Port (тот же, что был выбран для загрузки кода) и открыть монитор нажатием на кнопку с иконкой лупы в правом верхнем углу окна программы. Снизу должна отобразиться вкладка с окном Serial Monitor.

dispetcher

Рис. 12. Расположение кнопки включения Serial Monitor.

В окне монитора есть несколько важных элементов:

  • Поле ввода – служит для ввода данных, отправляемых на микроконтроллер
  • Конец строки – символ, который будет добавляться в конце отправляемого текста
  • Скорость – скорость связи. На обоих устройствах этот параметр должен совпадать. Самые популярные значения – это 9600 и 115200.
  • Принятый текст – текст, полученный с микроконтроллера.
dispetcher

Рис. 13. Элементы управления Serial Monitor.

Для работы с портом на стороне микроконтроллера мы будем использовать библиотеку Serial. Она позволяет читать и отправлять данные.

к сведению

Все возможности библиотеки Serial можно посмотреть в документации.

Передача данных

Напишем пример, который с микроконтроллера на компьютер передает фразу Hello, World.

В начале выполнения программы необходимо инициализировать и настроить связь с помощью функции Serial.begin(baudrate), где baudrate – скорость передачи данных. Отправка данных производится с помощью методов print(любые данные) и println(любые данные) - первый просто печатает данные, второй печатает и автоматически переносит строку, добавляя в конце символ \n. Общий текст самой программы представлен ниже.

#include <VBCoreG4_arduino_system.h>

void setup() {
// инициализация связи на скорости 115200 бод
Serial.begin(115200);
}

void loop() {
// отправка строки
Serial.println("Hello, World!");
// ожидание 100 мс
delay(100);
}

Здесь, как вы видите, в функции setup() производится инициализация последовательного порта, а затем в функции loop() происходит циклическая отправка фразы Hello, World! с интервалом в 100 мс. Загрузите программу на микроконтроллер, откройте Serial Monitor и убедитесь в её работоспособности.

Методов print() и println() поддерживают отправку не только текстовых, но и числовых данных. Напишем программу, которая отправляет на компьютер состояние кнопки USR Button.

#include <VBCoreG4_arduino_system.h>

void setup() {
// запуск связи на скорости 115200 бод
Serial.begin(115200);
// назначить вывод PC13 входом c подтягивающим резистором
pinMode(PC13, INPUT_PULLUP);

}

void loop() {
// считывание и инвертирование входного пина
int buttonState = !digitalRead(PC13);
// отправка состояния кнопки
Serial.println(buttonState);
// ожидание 100 мс
delay(50);
}

Запустите программу. Если вы нажмете на кнопку, то в терминале увидите 1. Когда вы её отпустите – начнут приходить 0.

Прием данных

Теперь напишем программу для чтения данных с компьютера. Программа должна будет делать следующее: читать данные, принятые с ПК, и затем их же отправлять обратно. Обычно такой вид программ называют «Эхо». Их часто используют для тестирования и настройки каналов связи.

Для проверки наличия входящих данных используется метод available() – он возвращает количество входящих байт. Благодаря нему можно проверять, что имеется как минимум один байт для чтения. Пока данные не прочитаны, они будут ожидать в приемном буфере на стороне МК. Если буфер переполнится, то новые входящие данные будут потеряны.

Для приема данных служит метод Serial.read(). Он возвращает только тип int. Поэтому использовать его напрямую в нашей программе не получится, так как вместо отправленных символов в терминале, мы будем получать их численное значение в таблице ASCII. Чтобы отправлять обратно именно символы, нужно преобразовать чтение к символьному типу с помощью (char)Serial.read(). Ниже представлен текст программы «Эхо».

к сведению

ASCII — это таблица, которая связывает числа и символы, чтобы компьютер мог работать с текстом. Каждой букве, цифре и знаку препинания соответствует свой номер (например, A — 65, пробел — 32). ASCII включает только латинские символы и лежит в основе большинства современных текстовых кодировок. Подробнее о том, какому символу соответствует нужное число, можно ознакомиться по ссылке.

#include <VBCoreG4_arduino_system.h>

void setup() {
// запуск связи на скорости 115200 бод
Serial.begin(115200);
}

void loop() {
// проверка наличия входящих данных
if (Serial.available()) {
// отправка принятых символов
Serial.print((char)Serial.read());
}
}

Загрузите программу и проверьте её. Обратите внимание, что здесь важна настройка конца строки в окне монитора порта - если включить NL (New Line), то каждая отправка будет выводиться на новой строке, т.к. символ переноса будет отправляться обратно в монитор и переносить строку. Если отключить - всё отправленное будет выводиться в одну строку.

В текущей реализации программы «Эхо» текст принимается и отправляется посимвольно. Но у библиотеки Serial есть возможность читать весь полученный текст целиком в виде строки. Это можно сделать с помощью метода readString(). При вызове он собирает строку посимвольно, ожидая поступления новых символов. Если после получения символа происходит тайм-аут, то передача считается завершенной и возвращается строка. По умолчанию значение тайм-аута установлено в 1000 мс, но его можно настроить с помощью метода Serial.setTimeout(ms). Давайте перепишем программу, используя построчное чтение данных:

#include <VBCoreG4_arduino_system.h>

void setup() {
// запуск связи на скорости 115200 бод
Serial.begin(115200);
// установка таймаута
Serial.setTimeout(50);
}

void loop() {
// проверка наличия входящих данных
if (Serial.available()) {
// чтение строки
String s = Serial.readString();
// отправка строки
Serial.println(s);
}
}

В качестве заключительной задачи напишем программу, которая зажигает светодиоды LED1 и LED2 с помощью команд с ПК. Введем следующие идентификаторы команд:

  • #LD1_x – команда для изменения статуса светодиода LED1,
  • #LD2_x – команда для изменения статуса светодиода LED2.

В обеих командах вместо x будет 0, если нужно потушить светодиод, и 1 – если нужно зажечь. Мы уже работали со светодиодом LED2. Он подключен к ножке контроллера PA5. Если вы посмотрите на схему платы, то увидите, что светодиод LED1 подключен к ножке PD2.

Для чтения данных будем использовать еще один метод Serial.readStringUntil(символ). Он работает аналогично readString(), но ждет не таймаута, а терминирующего символа, т.е. читает посимвольно до тех пор, пока не встретит указанный символ. С помощью него можно читать строки без задержки. В качестве терминирующего символа примем \n. Текст программы приведен ниже:

#include <VBCoreG4_arduino_system.h>

void setup() {
// запуск связи на скорости 115200 бод
Serial.begin(115200);

// инициализировать цифровой вывод PA5 в качестве выхода
pinMode(PA5, OUTPUT);
pinMode(PD2, OUTPUT);
}

void loop() {
// проверка наличия входящих данных
if (Serial.available()) {
// чтение строки до терминирующего символа '\n'
String s = Serial.readStringUntil('\n');
// поиск индекса символа '_'
int index = s.indexOf('_');

// если такой символ не найден, то выдаем ошибку
if (index == -1) {
Serial.println("Команда не известна");
}
else {
// выделяем идентификатор команды в отдельную строку
String cmd_id = s.substring(0, index);
// выделяем действие: 0 или 1
int cmd = s.substring(index + 1).toInt();
// если получена команда #LED1, то выставляем 0 или 1 на LED1
if (cmd_id == "#LED1")
digitalWrite(PD2, cmd);
// если получена команда #LED2, то выставляем 0 или 1 на LED2
if (cmd_id == "#LED2")
digitalWrite(PA5, cmd);
// информируем о получении и обработке команды
Serial.println(s+"_ack");
}
}
}

Изучите предложенный код. В нём вы можете встретить две новые функции:

  • substring(begin, end) – выделить подстроку из строки начиная с символа с индексом begin и заканчивая символом end;
  • toInt() – переводит string в int.

После изучения кода, загрузите его на МК и протестируйте программу.

Заключение

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

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

Задания для самостоятельной работы

  1. Сделайте так, чтобы светодиод LED2 моргал с последовательностью:

    Светодиод включен
    Ждем 200 мс
    Светодиод выключен
    Ждем 500 мс
    Светодиод включен
    Ждем 400 мс
    Светодиод выключен
    Ждём 200 мс
    Светодиод включен
    Ждем 800 мс
    Светодиод выключен
    Ждем 500 мс

    Выведите на компьютер информацию о статусе светодиода.

  2. Сделайте так, чтобы период моргания светодиода LED2 постепенно увеличивался со 100 мс до 1 с, а затем постепенно уменьшался с 1 с до 100 мс, и так до бесконечности. Проще всего это сделать с помощью циклов for или while. Если вы еще не знакомы с ними, то вам необходимо самостоятельно разобраться с базовым синтаксисом языка C++.

  3. Выполните предыдущее упражнение для светодиода LED1.

  4. Сделайте следующую программу:
    При подаче питания светодиод LED1 моргает с периодом 200 мс. Каждый раз при нажатии на кнопку USR_BTN начинает моргать другой светодиод. Т.е. нажатие на кнопку переключает активный светодиод с LED1 на LED2 и наоборот.

  5. Доработайте предыдущую программу так, чтобы можно было задавать активный светодиод с помощью компьютера.