Это было неизбежно. Увлекшись электроникой, я должен был рано или поздно дойти и до программирования микроконтроллеров. А что может быть проще программирования AVR-микроконтроллеров в устройствах Arduino? Не удивительно, что начать я решил именно с них. Что же из этого получилось — читайте далее.

Примечание: Описанные далее действия производились под Linux, на Arduino Uno и, соответственно, используемом в этом устройстве микроконтроллере ATmega328P. Однако все написанное далее справедливо и для других моделей Arduino, а также мало отличаться в случае, если вы используете другую ОС.

Настройка Arduino IDE

Подключаем Arduino к компьютеру через USB порт и определяем при помощи dmesg имя соответствующего устройства. У меня это ttyACM0. Если увидели что-то вроде:

usb 1-1: new full-speed USB device number 59 using xhci_hcd
usb 1-1: Device not responding to setup address.
usb 1-1: device not accepting address 59, error -71
usb usb1-port1: unable to enumerate USB device

… значит проблема в USB-кабеле, используйте другой.

Смотрим, какие права стоят на это устройство:

ls -la / dev / ttyACM0

В разных дистрибутивах результат немного отличается. В Arch Linux я увидел:

crw-rw—- 1 root uucp 166, 0 Jan  1 21:34 /dev/ttyACM0

То есть, для доступа к устройству пользователя нужно добавить в группу uucp:

sudo usermod -a -G uucp eax

В Ubuntu название группы будет другим, а именно «dialout». После добавления пользователя в группу скорее всего придется перелогиниться. В выводе id должны видеть, что ваш пользователь теперь состоит в группе.

Качаем Arduino IDE отсюда и распаковываем куда-нибудь:

cd ~ / temp
tar —xz -xvf arduino-1.8.0-linux64.tar.xz
mkdir ~ / opt
mv arduino-1.8.0 ~ / opt / arduino

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

После запуска IDE в Tools → Port выбираем /dev/ttyACM0. Затем жмем Files → Examples → Basics → Blink. Откроется следующий код:

void setup ( )
{
pinMode ( LED_BUILTIN, OUTPUT ) ;
}

void loop ( )
{
digitalWrite ( LED_BUILTIN, HIGH ) ;
delay ( 1000 ) ;
digitalWrite ( LED_BUILTIN, LOW ) ;
delay ( 1000 ) ;
}

Используемый в Arduino язык программирования, как не сложно заметить, является диалектом C/C++. Эта программа просто мигает встроенным в Arduino светодиодом. Вы тут все программисты, поэтому разжевывать, как именно работает код, полагаю, не требуется. Жмем Upload (Ctr+U) и… я лично получил такую ошибку:

libtinfo.so.5: cannot open shared object file: No such
file or directory

Лечится так:

sudo pacman -S ncurses
sudo ln -s / usr / lib / libncursesw.so / usr / lib / libtinfo.so.5

Если все было сделано правильно, теперь после нажатия Ctr+U Arduino начнет мигать желтым светодиодом с подписью L. Бывает так, что программа Blink уже была залита в Arduino заранее. В этом случае попробуйте изменить в коде частоту мигания и перезалить программу.

Работа без IDE

Arduino IDE довольно убога, как текстовый редактор, плюс я заметил в ней неприятные глюки при сохранении файлов. Мне, знаете ли, нравится писать код в Vim . Вам может нравиться Sublime Text или другой текстовый редактор. Так давайте же разберемся, как программировать Arduino в текстовом редакторе или IDE по вкусу.

Говорим и заодно сразу прописываем в ~/.bashrc:

export ARDUINODIR = / home / eax / opt / arduino

Далее нам понадобится файл arduino.mk, который доступен здесь . Однако не спешите его качать. Мне этот файл пришлось во многих местах подправить, чтобы он заработал с последней Arduino IDE. Детали скучны, поэтому я не буду вас ими грузить. Просто берите пропатченную мною версию . Если вам вдруг интересно, что именно я поменял, измененные строчки помечены вот так:

# patched by afiskon

Создаем файл Makefile такого содержания:

TARGET := main
SOURCES := main.cpp
BOARD := uno
include arduino.mk

… а также main.cpp:

#include <Arduino.h>

/* Номера пинов, к которым подключены аноды RGB-светодиода */
const int RLED = 9 ;
const int GLED = 11 ;
const int BLED = 10 ;

/* Номера пинов, к которым подключены кнопки */
const int RBUTTON = 2 ;
const int GBUTTON = 4 ;
const int BBUTTON = 6 ;

/* Номер аналогового входа, подключенного к фоторезистору */
const int LIGHT = 0 ;

/* Как часто считывать состояния кнопок, в мс */
const int DELAY = 10 ;

/* Как часто выводить уровень освещенности, в мс */
const int LIGHT_REPORT_PERIOD = 1000 ;

/* Текущая яркость RGB-светодиода */
int rval = 120 ;
int gval = 0 ;
int bval = 250 ;

/*
* Была ли отпущена соответствующая кнопка.
*
* Эти переменные нужны, чтобы одно нажатие кнопки
* не считалось за несколько.
*/

bool rbutton_released = true ;
bool gbutton_released = true ;
bool bbutton_released = true ;

/* Как долго не выводили уровень освещенности, в мс */
int silent_time = 0 ;

void setup ( )
{
pinMode ( RLED, OUTPUT ) ;
pinMode ( GLED, OUTPUT ) ;
pinMode ( BLED, OUTPUT ) ;

pinMode ( RBUTTON, INPUT ) ;
pinMode ( GBUTTON, INPUT ) ;
pinMode ( BBUTTON, INPUT ) ;

Serial. begin ( 9600 ) ;
}

void loop ( )
{
/* Обработка нажатия первой кнопки */
if ( digitalRead ( RBUTTON ) == HIGH )
{
if ( rbutton_released )
{
rbutton_released = false ;
rval + = 10 ;
if ( rval > 255 )
rval = 0 ;
Serial. println ( «rval = » + String ( rval ) ) ;
}
} else
rbutton_released = true ;

/* То же самое для второй кнопки */
if ( digitalRead ( GBUTTON ) == HIGH )
{
if ( gbutton_released )
{
gbutton_released = false ;
gval + = 10 ;
if ( gval > 255 )
gval = 0 ;
Serial. println ( «gval = » + String ( gval ) ) ;
}
} else
gbutton_released = true ;

/* То же самое для третьей кнопки */
if ( digitalRead ( BBUTTON ) == HIGH )
{
if ( bbutton_released )
{
bbutton_released = false ;
bval + = 10 ;
if ( bval > 255 )
bval = 0 ;
Serial. println ( «bval = » + String ( bval ) ) ;
}
} else
bbutton_released = true ;

/* Задаем уровень ШИМ-сигнала на анодах RGB-светодиода */
analogWrite ( RLED, rval ) ;
analogWrite ( GLED, gval ) ;
analogWrite ( BLED, bval ) ;

/* Небольшая задержка */
delay ( DELAY ) ;
silent_time + = DELAY ;

/* Выводим освещенность, если долго ее не выводили */
if ( silent_time >= LIGHT_REPORT_PERIOD )
{
int light_val = analogRead ( LIGHT ) ;
Serial. println ( «light_val = » + String ( light_val ) ) ;
silent_time = 0 ;
}
}

Как видите, программа стала сложнее. Этот код мы разберем подробнее чуть ниже. Если хотите, можете пока что оставить код программы Blink. Главное — не забудьте добавить в начале строчку:

#include <Arduino.h>

Для загрузки программы говорим make upload . Для просмотра сообщений от Arduino говорим make monitor . В последнем случае будет использован screen . Как альтернативный вариант, можно воспользоваться программой minicom:

sudo pacman -S minicom
minicom -D / dev / ttyACM0 -b 9600

Если подзабыли количество бод, указанное в программе, можно сказать:

stty -F / dev / ttyACM0

Теперь, когда с настройкой рабочего окружения покончено, давайте разберемся, как работает приведенная программа.

Немного матчасти и разбор кода

Приведенная программа управляет RGB-светодиодом, а также считывает данные с трех кнопок и фоторезистора:

RGB-светодиод — это по сути три светодиода в одном корпусе с общим катодом или анодом, которому соответствует наиболее длинная ножка из четырех. У меня был RGB-светодиод с общим катодом, то есть самую длинную ножку я подключал к минусу. Такой светодиод интересен тем, что его цвет со временем можно менять. Как видите, на фото светодиод светится фиолетово-розовым цветом. Если у вас нет RGB-светодиода, вы можете с тем же успехом использовать три отдельных светодиода.

Фоторезистор представляет собой резистор, чье сопротивление меняется в зависимости от того, как много света на него падает. Тот, что есть у меня, имеет сопротивление около 400 Ом при ярком свете и более 2 МОм (максимум, который может померить мой мультиметр) в полной темноте. Используя его в качестве одного из резисторов в делителе напряжения , можно оценить яркость света вокруг. Если у вас нет фоторезистора, можете с тем же успехом подключить обычный потенциометр.

У Arduino Uno есть 14 цифровых пинов, 6 аналоговых входов, а также пины с 5 В напряжения, 3.3 В и землей. В программе Blink мы использовали 13-ый пин со встроенным светодиодом. Подавая на него высокое и низкое напряжение, можно заставить светодиод мигать. Также цифровые пины позволяют считывать напряжение. В приведенной выше программе пины 2, 4 и 6 используются для чтения состояния кнопок. Пока это все не сильно отличается от уже знакомых нам GPIO пинов в Raspberry Pi .

Часть цифровых пинов помечены тильдой (~). У меня таких пинов 6, с номерами 3, 5, 6, 9, 10 и 11. Это означает, что пин может подавать ШИМ-сигнал (Широтно-Импульсная Модуляция или PWM, Pulse-Width Modulation). В данном контексте ШИМ всего лишь означает, что на пин будет подаваться сигнал с заданным коэффициентом заполнения . В Arduino коэффициент заполнения задается от 0 до 255. Например, если указать 127, то половину времени будет подаваться высокий сигнал, а половину — низкий. Если же указать 0, то сигнал будет все время низким. Частота ШИМ-сигнала в Arduino разная на разных пинах и отличается от модели к модели. В Arduino Uno частота составляет примерно 980 Гц на пинах 5 и 6, и примерно 490 Гц на остальных ШИМ-пинах.

ШИМ позволяет аппроксимировать подачу напряжения между 0 и 5 В. В приведенной программе нажатия на кнопки увеличивают ШИМ-сигнал на соответствующих анодах RGB-светодиода. В результате тремя кнопками регулируется яркость и цвет светодиода.

Наконец, аналоговые входы предназначены для более точного считывания напряжения, чем просто «высокий сигнал» и «низкий сигнал». В приведенном примере аналоговый вход A0 подключен к делителю напряжения из фоторезистора и резистора сопротивлением 10 кОм. Вызов analogRead(LIGHT) возвращает значение около 800 при ярком свете, 125 при свете от настольной лампы, 0 в полной темноте и около 960, если посветить на фоторезистор лазерной указкой. В целом диапазон возможных возвращаемых значений лежит от 0 до 1023. Плюс к этому, аналоговые входы можно использовать точно так же, как и цифровые пины (без ШИМ), например:

pinMode ( A1, OUTPUT ) ;
digitalWrite ( A1, HIGH ) ;

Fun fact! Фактически, теперь вы знаете, как сделать лазерную сигнализацию. Также с помощью светодиодов или ИК-светодиодов и фоторезистора можно сделать датчик движения (бесконтактный выключатель?) вроде того, что используется в сушилках для рук. Также помимо фоторезистора можно использовать фототранзистор, представляющий собой обычный транзистор, ток базы которого определяется интенсивностью света. Если желаете, можете реализовать эти проекты в качестве домашнего задания.

Заключение

С Arduino мне понравилось работать намного больше, чем с Raspberry Pi. У последней, насколько мне известно, аналоговых входов нет совсем, да и с ШИМ все как-то не слишком удобно. Плюс Arduino Uno — это всего лишь микроконтроллер ATmega328P, на котором нет этой бесполезной операционной системы и который при желании можно извлечь и впаять прямо в изготовленную по ЛУТ плату . В общем, для занятия электроникой это устройство куда интереснее.

Исходники к этой заметке вы найдете на GitHub . Как обычно, буду рад вашим вопросам и дополнениям.

Дополнение: Как собрать Arduino прямо на макетной плате

admin

Share
Published by
admin

Recent Posts

Консоль удаленного рабочего стола(rdp console)

Клиент удаленного рабочего стола (rdp) предоставляет нам возможность войти на сервер терминалов через консоль. Что…

1 месяц ago

Настройка сети в VMware Workstation

В VMware Workstation есть несколько способов настройки сети гостевой машины: 1) Bridged networking 2) Network…

1 месяц ago

Логи брандмауэра Windows

Встроенный брандмауэр Windows может не только остановить нежелательный трафик на вашем пороге, но и может…

1 месяц ago

Правильный способ отключения IPv6

Вопреки распространенному мнению, отключить IPv6 в Windows Vista и Server 2008 это не просто снять…

1 месяц ago

Ключи реестра Windows, отвечающие за параметры экранной заставки

Параметры экранной заставки для текущего пользователя можно править из системного реестра, для чего: Запустите редактор…

1 месяц ago

Как управлять журналами событий из командной строки

В этой статье расскажу про возможность просмотра журналов событий из командной строки. Эти возможности можно…

1 месяц ago