Программирование микроконтроллеров для управления роботами
Микропроцессоры и архитектуры
Настольные системы (компьютеры, ноутбуки)
● Архитектуры: x86, x86_64● Производители чипов: Intel, AMD● Операционные системы: настольные
дистрибутивы Linux, Mac OS X, Windows XXX● Устройства: стационарные компьютеры,
ноутбуки, серверы
Хай-энд мобильные чипы (планшеты и смартфоны)
● Архитектуры: ARM, MIPS, Intel с X86 тоже что-то пробует
● Операционные системы: Google Android, iOS, мобильная Windows, Windows 10
● Устройства: планшеты, смартфоны; гибридные ноутбуки, серверы с низким энергопотреблением
Мид-энд чипы — хорошая производительность, низкое потребление энергии
(роутеры)
● Архитектуры: MIPS, ARM● Операционные системы: Linux + окружение
BusyBox● Устройства: роутеры, встраиваемые
системы, где нужен Линукс, но не нужна топовая графика или типа того
Микроконтроллеры(стиральные машины)
● Архитектуры: AVR, MIPS, ARM● Производители: Atmel ATmega8 (AVR), Microchip
PIC32 (MIPS), STMicroelectronics STM32 (ARM)● Операционные системы: специализированная
прошивка без ОС, RTOS'ы● Устройства: счетчики, стиральные машины,
бытовая техника, другие встраиваемые системы, не требовательные к ресурсам
Из отечественного
● Эльбрус: своя архитектура и свое производство (тянут десктоп с Linux, военное применение)
● Байкал: лицензия ядра мид-энд MIPS, производство в Азии (высокопроизводительные встраиваемые системы — станки с ЧПУ, планируют массовый рынок)
Платы для разработки
Raspberry Pi (протухший хай-энд ARM, тянет Linux, Android со скрипом)
Raspberry Pi 2(хай-энд ARM посвежее, тянет Android и Windows 10)
Black SWIFT/Unwired One(мид-энд MIPS)
Arduino(микроконтроллер ATmega8 AVR)
Клоны Arduino(тысячи их)
и так далее
Сделать плату
Дома
● ЛУТ (лазерно-утюжная технология)● Фототравление● Фрезерование● Принтеры, печатающие проводящей краской
Фрезерование
Лазерный принтер+утюг
Принтер с проводящими чернилами
На заказ
● Высокая точность, тонкие дорожки, многослойные платы, большой тираж
● Автоматический монтаж компонент (специальный корпус SMD)
● Резонит (Зеленоград), КБ Связь инжиниринг (Дубна), Виптех (Нижний Новгород)
● Китай (с текущим курсом уже не так выгодно)
Сделать чип
Языки описания аппаратного обеспечения HDL (Verilog/VHDL)
● на заказ: Дизайн на HDL → завод в Азии → чип ASIC (специализированная микросхема)
● дома: Дизайн на HDL → ПЛИС● MIPSfpga: исходники промышленного чипа
PIC32MZ для запуска на ПЛИС● opencores.org● Есть линия в Зеленограде
практика
Плата ChipKIT WF32● $70 (~5000руб) на digilentinc.com, microchipdirect.com● Совместима на программном уровне с платформой
Arduino● Программирование на языке Си/С++● WiFi, режимы USB хоста и USB-устройства, SD-карта● Контроллер PIC32MX 80МГц● 512Кб ПЗУ флеш, 128Кб ОЗУ
Порты (ножки или пины) ввода-вывода
● Осуществляют связь между программой и внешним миром
● Пронумерованы от 0 до 41 (на WF32)● Каждый порт может работать в режиме ввода или вывода
● Цифровой режим: для порта определено два значения 1 (HIGH - плюс) и 0 (LOW - минус)
● В режиме вывода программа записывает в указанный порт единицу 1 и на порт подаётся напряжение плюс, при записи 0 подаётся минус (земля/ground/GND)
Среда разработки MPIDE● chipkit.net/started/install-chipkit-software/● Свободное программное обеспечение● Работает на Linux, Mac и Windows● Предварительно необходимо установить
платформу Java: java.oracle.com
Драйвер платы:● в Linux уже всё есть, хотя может потребоваться
дать права на доступ к устройству /dev/ttyUSBX● в Windows 7: драйвер в архиве с MPIDE● в Windows 8: при подключении платы разрешить
искать в интернете
Запускаем среду разработки MPIDE
Меню Tools > Board > chipKIT > chipKIT WF32
Светодиод (LED) и беспаячная макетная плата (breadboard)
Настройка перед стартом: void setup(), установка режима порта pinMode()
Бесконечный цикл void loop(), запись значений в порт digitalWrite()
Загрузка прошивки на плату: наверху вторая слева кнопка Upload
То горит, то не горит
Моторчик с коллекторным двигателем
Без редуктора будет крутиться, но машинка не поедет
Моторчик с редуктором крутится медленнее, но тянет
больше нагрузки
Управление мотором: микросхема-драйвер-усилитель L293D
Микросхема-усилитель L293D
● GND — земля (и заодно теплоотвод)● Vs — питание двигателей: 4,5-36В● Vss — питание микросхемы: 5В● ENABLE1/2 — включить/выключить
левую/правую половину● INPUT1/2/3/4 — слабый сигнал от платы● OUTPUT1/2/3/4 — усиленный сигнал на мотор
(от источника Vs)
Управление мотором
Взад-вперёд
Сервомоторчики: ● Угол поворота 0 — 180 градусов● 3 провода: питание 5В (+), земля (GND/-),
управляющий сигнал
Управление серво-моторчиком:библиотека Servo.h
Повернулись-зафиксировались
Разные датчики
на ardunn.ru
Сенсор звука: всего 3 ножки
● GND — земля● +5V — питание 5В● OUT — значение сенсора: 0 - звук есть,
1 - звука нет
Реагируем на звук: setup
Реагируем на звук: loop
Хлопаем в ладоши
Немного прокатимся
Константы для ножек
Левый мотор: вперёд, назад,
стоп
Правый мотор: вперёд, назад,
стоп
Все ножки в режим
вывода
2 секунды вперёд, 2 секунды
разворачиваемся, ждём секунду;
и так вечно бесконечно
Выключаем штекер от батареек, перемычку J15 переводим из положения EXT в UART
Подключаем плату через USB к компьютеру, прошиваем из MPIDE
ВАЖНО: не подключайте плату через USB к компьютеру, если к
плате подключено внешнее питание — в лучшем случае
лишитесь платы, в худшем — и платы, и пары портов USB на
компьютере
Отключаем USB, возвращаем J15 из UART в EXT, подключаем батарейки
Учимся программироватьс Роботом Машинкой
Задача — ехать по черной линии: ехать прямо по прямой линии и
поворачивать на поворотах
Датчик линии
● У датчика всего три провода: питание Vcc (5В), земля GDN и сигнал OUT
● OUT=HIGH (т.е. логическая единица), если поднести его к поверхности черного цвета, OUT=LOW (т.е. логический ноль), если поднести его к поверхности любого другого цвета.
Трасса без перекрестков, без маркеров, без пересечений: просто замкнутая линия
Робот умеет
● Ехать вперед● Ехать назад● Останавливаться● Поворачивать налево● Поворачивать направо● Определять наличие линии на левом датчике● Определять наличие линии на правом датчике
Алгоритм словами
● Если ни левый, ни правый датчик не видят линии (линия между датчиками), едем вперёд.
● Иначе (линия есть под левым или под правым датчиком или сразу под обоими) проверяем, есть ли линия под правым датчиком.
● Если линия есть под правым датчиком, поворачиваем направо.
● Иначе (значит линия под левым датчиком) поворачиваем налево.
● Повторяем всё сначала
Алгоритм в виде блок-схемы
Блок-схема → код на С++
Блоки действий
команда вперёд
mleft_forward();
mright_forward();
команда назад
mleft_backward();
mright_backward();
Блоки действий
команда налево
mleft_backward();
mright_forward();
команда направо
mleft_forward();
mright_backward();
Блоки действий
команда стоп
mleft_stop();
mright_stop();
Блоки с условиями
if( условие ) {
// действия, если условие выполнено (ветка "да")
...
} else {
// действия, если условие не выполнено (ветка "нет")
...
}
Операторы сравнения — булевы выражения для блоков if
● a == b : если a равно b, ПРАВДА, иначе ЛОЖЬ● a != b : если a не равно b, ПРАВДА, иначе ЛОЖЬ● a < b : если a меньше b, ПРАВДА, иначе ЛОЖЬ● a > b : если a больше b, ПРАВДА, иначе ЛОЖЬ● a <= b : если a меньше или равно b, ПРАВДА,
иначе ЛОЖЬ● a >= b : если a больше или равно b, ПРАВДА,
иначе ЛОЖЬ
Сложные условия из нескольких простых
● a && b (логическое И): если a ПРАВДА И b ПРАВДА, ПРАВДА, иначе ЛОЖЬ
● a || b (логическое ИЛИ): если a ПРАВДА ИЛИ b ПРАВДА, ПРАВДА, иначе ЛОЖЬ
● !a (логическое НЕ): если a ЛОЖЬ, ПРАВДА, иначе ЛОЖЬ
Выражения для блоков условий
ПРАВДА, если левый датчик видит линию
( digitalRead(LINE_SENSOR_L) == 1 )
ПРАВДА, если левый датчик не видит линию
( digitalRead(LINE_SENSOR_L) == 0 )
ПРАВДА, если правый датчик видит линию
( digitalRead(LINE_SENSOR_R) == 1 )
ПРАВДА, если правый датчик не видит линию
( digitalRead(LINE_SENSOR_R) == 0 )
Прошивка для машинки
/**
* Сенсор линии: сенсор подключен к входной ножке и
* подает на нее сигнал:
* 1, если сенсор обнаружил линию (черный цвет),
* 0, если сенсор линию не видит (белый цвет).
*/
#define LINE_SENSOR_L 27
#define LINE_SENSOR_R 28
void setup() {
Serial.begin(9600);
Serial.println("Start Robot Car - the line follower!");
pinMode(MOTOR_LEFT_1, OUTPUT);
pinMode(MOTOR_LEFT_2, OUTPUT);
pinMode(MOTOR_LEFT_EN, OUTPUT);
pinMode(MOTOR_RIGHT_1, OUTPUT);
pinMode(MOTOR_RIGHT_2, OUTPUT);
pinMode(MOTOR_RIGHT_EN, OUTPUT);
// пин сенсора в режим ввода
pinMode(LINE_SENSOR_L, INPUT);
pinMode(LINE_SENSOR_R, INPUT);
// остановить моторы при старте
mleft_stop();
mright_stop();
}
void loop() {
if( digitalRead(LINE_SENSOR_L) == 0 &&
digitalRead(LINE_SENSOR_R) == 0 ) {
//Serial.println("Proverka linii: linii net na 2x datchikah");
// линии нет на обоих датчиках
// едем вперед
mleft_forward();
mright_forward();
} else {
// линия есть хотябы на одном из датчиков
Serial.println("linia na odnom is datchikov");
if( digitalRead(LINE_SENSOR_R) == 1 ) {
// линия под правым датчиком
Serial.println("praviy datchik -> povorot napravo");
// ненадолго остановимся, чтобы собраться с мыслями (для отладки)
mleft_stop();
mright_stop();
delay(1000);
// поворачиваем направо
mleft_forward();
mright_backward();
// поворачиваемся 400 миллисекунд, время получено эмпирически
delay(400);
} else {
// линии нет под правым датчиком, значит она под левым датчиком
Serial.println("leviy datchik -> povorot nalevo");
// ненадолго остановимся, чтобы собраться с мыслями (для отладки)
mleft_stop();
mright_stop();
delay(1000);
// повернуть налево
mleft_backward();
mright_forward();
// поворачиваемся 400 миллисекунд, время получено эмпирически
delay(400);
}
}
}
1i7.livejournal.com
Антон Моисеев