Привет, Хабр! Хочу предложить реализацию двух подходов разработки программного обеспечения датчика движения, работающего совместно с платой Arduino. Ни датчик движения [1], ни Arduino [2]. в дополнительной рекламе не нуждаются.
Сравним существующие методы программирования с точки зрения простоты и удобства использования. Предлагаем начать статью со знакомства с характеристиками выбранного датчика движения.
Основным датчиком который будем использовать является датчик движения PIR [3].
PIR датчики небольшие, недорогие, потребляют меньше энергии и совместимы с аппаратными платформами, такими как Arduino.
Он использует пару пироэлектрических датчиков, которые обнаруживают инфракрасное излучение. Он имеет радиус действия до 6 метров, что достаточно для проекта.
Кроме того понадобятся светодиоды: зеленый и красный. Шнуры, резисторы и макет: для завершения соединений понадобится пучок проводов и макет. Также понадобятся два резистора на 220 Ом и один 10 кОм.
Следующим составляющим будет плата Arduino: плата Arduino Uno. Для связи платы Arduino с компьютером используем кабель USB.
Прежде чем приступить к работе с аппаратной системой необходимо набросать проект в виде блок схемы. Используем проект с циклом, приведенный на рисунке.
Проект выполняется в цикле, как только обнаружено движение, и выполняются соответствующие действия светодиода:
С помощью единственной инструкции Arduino вы можете включить или выключить светодиод.
Для выполнения операции мигания необходимо будет повторно выполнять действия включения и выключения с временной задержкой между действиями, чтобы выход датчика PIR мог успокоиться.
Будем использовать один и тот же поток при написании кода для обоих методов программирования.
Самым простым способом проектирования аппаратного обеспечения таких проектов является прототипирования. Инструмент, используемый для этой цели, называется Fritzing.
Fritzing активно поддерживает Arduino и другие популярные аппаратные платформы с открытым исходным кодом. Следующий рисунок показывает схему для проекта, разработанного с использованием Fritzing. Компоненты подключаем, как показано на рисунке:
Для завершения сборки схемы выполним следующие шаги:
Ниже приведена принципиальная схема схемы электроники, которую мы разработали ранее. Диаграмма также получена с помощью Fritzing:
Теперь система готова к запуску программы Arduino.
После завершения подключения цепи переходим непосредственно к разделам программирования. Рекомендуется использовать для проверки подключения цепи и проверки состояния датчика.
Предполагаем, что плата Arduino уже снабжена скетчом StandardFirmata. В противном случае необходимо загрузить скетч StandardFirmata на плату Arduino.
Лучший способ проверить реализацию схемы — использовать программу тестирования Firmata, которую была описана в предыдущей статье. Согласно настройке проекта, датчик PIR выдает события на вывод 7 Arduino.
В тестовой программе измените тип вывода 7 на Input и помашите рукой по датчику, и вы сможете увидеть состояние булавки как показано на следующем скриншоте:
Проверим соединения светодиодов, установив контакты 12 и 13 в качестве выходных контактов и переключив кнопки, чтобы установить состояние контактов. Если светодиоды мигают при переключении кнопки, то соединения работают безупречно.
Для запуска проекта выполняем:
Как и любая другая программа Arduino, код имеет две обязательные функции: setup () и loop (). Он также имеет настраиваемую функцию blinkLED () для конкретного действия, которое будет объяснено позже.
В предыдущем фрагменте кода были назначены переменные для вывода Arduino в начале программы. В функции setup () мы сконфигурировали эти переменные для определения как входных или выходных выводов:
Здесь pirPin, redLedPin и greenLedPin являются цифровыми булавками 7, 12 и 13 соответственно. В этой же функции мы также сконфигурировали плату Arduino для последовательного соединения со скоростью 9600 бит /с:
В функции loop ()многократно контролируем входной сигнал с цифрового контакта pirPin для обнаружения движения. Выход этого контакта ВЫСОКИЙ, когда обнаружено движение, и НИЗКИЙ в противном случае.
Эта логика реализуется с помощью простого оператора if-else. Когда это условие выполняется, функция вызывает пользовательскую функцию blinkLED () для выполнения соответствующего действия на светодиодах. Пользовательские функции являются очень важным аспектом любого языка программирования.
Function используются, когда сегмент кода повторно выполняется для выполнения того же действия. Пользователь может создать пользовательскую функцию для организации кода или выполнения повторяющихся действий. Чтобы успешно использовать пользовательскую функцию, пользователь должен вызвать их из обязательных функций Arduino, таких как loop (), setup () или любую другую функцию, которая приводит к этим обязательным функциям:
Ниже приведена настраиваемая функция, которую использовали в коде проекта:
В проекте функция blinkLED () не перенастраивает любое значение, когда оно вызывается из функции loop (). Следовательно, тип возвращаемого значения — void. При вызове функции мы передаем номер булавки и сообщение в качестве параметров:
Эти параметры затем используются в выполненном действии (запись сообщения на последовательный порт и настройка статуса светодиода) с помощью функции blinkLED (). Эта функция также вводит задержку для выполнения мигания с помощью функции delay ().
Спроектированная система была проверена в разделе «Тестирование аппаратного обеспечения» с помощью ручных входов через программу тестирования Firmata. Необходимо убедиться, что проект выполняет объективные задачи автономно и неоднократно.
С портом USB, подключенным к компьютеру, необходимо открыть средство последовательного мониторинга из среды IDEArduino, перейдя в меню «Сервис» | SerialMonitor или нажав Ctrl + Shift + M. На экране последовательного монитора должно появиться сообщение, аналогичное показанному:
При написании функции blinkLED () для выполнения действий мы включили действие для записи строки через последовательный порт. Переместите руку над датчиком PIR таким образом, чтобы датчик PIR мог обнаружить движение.
Это событие должно заставлять систему мигать красным светодиодом и отображать строку, обнаруженную движением, на серийном мониторе. При отсутствии движения некоторое время можно увидеть зеленый светодиод, мигающий, пока не будет обнаружено следующее движение через датчик PIR.
Можно использовать редактор по вашему выбору, но убедитесь, что сохраняются файлы с расширением .py. Скопируем следующие строки кода в новый файл и сохраним его как test.py:
Чтобы запустить этот файл, выполните следующую команду на терминале, где сохранен файл test.py:
Вы должны иметь возможность видеть текст PythonProgramming, напечатанный на терминале. Как вы можете видеть, файл начинается с #! / Usr / bin / python, который является местом установки Python по умолчанию. Добавив эту строку в свой код Python, вы можете напрямую выполнить файл Python с терминала. В операционных системах на основе Unix вам нужно сделать исполняемый файл test.py с помощью следующей команды:
теперь, поскольку ваш файл является исполняемым, вы можете напрямую запустить файл, используя следующую команду:
Теперь создадим новый файл Python со следующим фрагментом кода и запустим его. Обязательно необходимо изменить значение переменной порта в соответствии с вашей операционной системой:
В этом коде есть два основных компонента программирования: методы pyFirmata и функция Python для выполнения мигающего действия. Программа неоднократно обнаруживает события движения и выполняет мигающее действие.
В этом методе мы реализовали оператор while, чтобы поддерживать программу в цикле, пока пользователь не завершит работу вручную. Можно завершить код, используя комбинацию клавиш Ctrl + C.
Работы с платой Arduino и протоколом Firmata необходимо начать с инициализации платы Arduino в качестве переменной. Метод pyFirmata, который позволяет пользователю назначить правление переменной Python, выглядит следующим образом:
Как только значение переменной присвоено, можно выполнять различные действия, такие как чтение пина или отправка сигнала на вывод с использованием этой переменной. Чтобы назначить роль контакту, используется метод get_pin (). В следующей строке кода d представляет цифровой вывод, 7 — номер вывода, а i означает, что тип вывода — это входной вывод:
Как только pin и его роль присваиваются переменной, эта переменная может использоваться для чтения или записи значений на выводе:
Можно напрямую записывать данные на конкретный вывод, как описано в следующем коде:
Здесь метод write (1) посылает сигнал HIGH на вывод.
Функция Python начинается с ключевого слова def, за которым следует имя функции и входные параметры или аргументы. Определение функции заканчивается двоеточием (:) и после этого отступы. Оператор return завершает функцию. Оно также передает это выражение в место вызова функции.
Если оператор return сохраняется без выражения, считается, что оно передало возвращаемое значение None:
Предыдущая структура может быть использована для создания настраиваемых функций для выполнения повторяющихся задач. В нашем проекте у нас есть функция blinkLED (pin, message) для выполнения мигающего светодиода. Эта функция посылает 1 (HIGH) и 0 (LOW) значение на указанный цифровой контакт, а также печатает сообщение на терминале. Он также вводит задержку для имитации мигающего действия:
После запуска кода Python на терминале можно начинать тестирование. Если все идет по проекту, вы должны иметь возможность видеть в терминале следующий вывод:
Вы должны иметь возможность видеть строку обнаружения движения на терминале, когда какое-либо движение обнаружено датчиком PIR. Преимущество использования Python заключается в том, что незначительные изменения, такие как изменение скорости мигания или замена ролей светодиодов, могут быть выполнены путем простого изменения кода Python без участия С помощью Arduino или электрической цепи.
Сравнительный анализ результатов практической реализации проекта двумя методами программирования, которые мы применили в этой работе показывает, что метод который использует только скетч Arduino, представляет традиционную парадигму программирования микроконтроллера. Хотя этот метод более прост в реализации, ему не хватает экстенсивности, достигаемой интерфейсом Python-Arduino. Таким образом, для практического применения мы делаем выбор в пользу метода Python-Arduino.
Сравним существующие методы программирования с точки зрения простоты и удобства использования. Предлагаем начать статью со знакомства с характеристиками выбранного датчика движения.
Основным датчиком который будем использовать является датчик движения PIR [3].
PIR датчики небольшие, недорогие, потребляют меньше энергии и совместимы с аппаратными платформами, такими как Arduino.
Он использует пару пироэлектрических датчиков, которые обнаруживают инфракрасное излучение. Он имеет радиус действия до 6 метров, что достаточно для проекта.
Кроме того понадобятся светодиоды: зеленый и красный. Шнуры, резисторы и макет: для завершения соединений понадобится пучок проводов и макет. Также понадобятся два резистора на 220 Ом и один 10 кОм.
Следующим составляющим будет плата Arduino: плата Arduino Uno. Для связи платы Arduino с компьютером используем кабель USB.
Разработка потока программного обеспечения
Прежде чем приступить к работе с аппаратной системой необходимо набросать проект в виде блок схемы. Используем проект с циклом, приведенный на рисунке.
Проект выполняется в цикле, как только обнаружено движение, и выполняются соответствующие действия светодиода:
С помощью единственной инструкции Arduino вы можете включить или выключить светодиод.
Для выполнения операции мигания необходимо будет повторно выполнять действия включения и выключения с временной задержкой между действиями, чтобы выход датчика PIR мог успокоиться.
Будем использовать один и тот же поток при написании кода для обоих методов программирования.
Проектирование аппаратной системы
Самым простым способом проектирования аппаратного обеспечения таких проектов является прототипирования. Инструмент, используемый для этой цели, называется Fritzing.
Fritzing активно поддерживает Arduino и другие популярные аппаратные платформы с открытым исходным кодом. Следующий рисунок показывает схему для проекта, разработанного с использованием Fritzing. Компоненты подключаем, как показано на рисунке:
Для завершения сборки схемы выполним следующие шаги:
- Подключить VCC (+ 5V) и заземлите от Arduino к макету.
- Подключить анод (длинный провод) красного светодиода к цифровому выводу 12 платы Arduino. Подключить катод (короткий провод) красного светодиода к земле с помощью резисторов на 220 Ом.
- Подключить анод (длинный провод) зеленого светодиода к цифровому выводу 13 платы Arduino. Подключите катод (короткий провод) зеленого светодиода к земле с помощью резисторов на 220 Ом.
- Подключить VDD датчика PIR к VCC на макете. Используйте один и тот же цвет проводки для представления одной и той же категории соединений. Это очень поможет в устранении неисправностей цепи.
- Подключить сигнал (средний вывод) датчика PIR к цифровой оси 7 Arduino с помощью нагрузочного резистора 10 кОм.
Ниже приведена принципиальная схема схемы электроники, которую мы разработали ранее. Диаграмма также получена с помощью Fritzing:
Теперь система готова к запуску программы Arduino.
Тестирование подключений оборудования
После завершения подключения цепи переходим непосредственно к разделам программирования. Рекомендуется использовать для проверки подключения цепи и проверки состояния датчика.
Предполагаем, что плата Arduino уже снабжена скетчом StandardFirmata. В противном случае необходимо загрузить скетч StandardFirmata на плату Arduino.
Лучший способ проверить реализацию схемы — использовать программу тестирования Firmata, которую была описана в предыдущей статье. Согласно настройке проекта, датчик PIR выдает события на вывод 7 Arduino.
В тестовой программе измените тип вывода 7 на Input и помашите рукой по датчику, и вы сможете увидеть состояние булавки как показано на следующем скриншоте:
Проверим соединения светодиодов, установив контакты 12 и 13 в качестве выходных контактов и переключив кнопки, чтобы установить состояние контактов. Если светодиоды мигают при переключении кнопки, то соединения работают безупречно.
Метод 1 — использование автономного скетча Arduino
Для запуска проекта выполняем:
- Открыть Arduino IDE.
- В меню «Файл» открыть новый альбом.
- Скопировать следующий код Arduino в скетч и сохранить его:
Кодint pirPin = 7; //Pin number for PIR sensor int redLedPin = 12; //Pin number for Red LED int greenLedPin = 13; //Pin number for Green LED void setup(){ Serial.begin(9600); pinMode(pirPin, INPUT); pinMode(redLedPin, OUTPUT); pinMode(greenLedPin, OUTPUT); } void loop(){ // Function which blinks LED at specified pin number void blinkLED(int pin, String message){ digitalWrite(pin,HIGH); Serial.println(message); delay(1000); digitalWrite(pin,LOW); d int pirVal = digitalRead(pirPin); if(pirVal == LOW){ //was motion detected blinkLED(greenLedPin, "No motion detected."); } else { blinkLED(redLedPin, "Motion detected."); } } elay(2000); }
- Компилировать и загрузить скетч на доску Arduino.
Как и любая другая программа Arduino, код имеет две обязательные функции: setup () и loop (). Он также имеет настраиваемую функцию blinkLED () для конкретного действия, которое будет объяснено позже.
Функция setup ()
В предыдущем фрагменте кода были назначены переменные для вывода Arduino в начале программы. В функции setup () мы сконфигурировали эти переменные для определения как входных или выходных выводов:
pinMode(pirPin, INPUT);
pinMode(redLedPin, OUTPUT);
pinMode(greenLedPin, OUTPUT);
Здесь pirPin, redLedPin и greenLedPin являются цифровыми булавками 7, 12 и 13 соответственно. В этой же функции мы также сконфигурировали плату Arduino для последовательного соединения со скоростью 9600 бит /с:
Serial.begin(9600);
Функция loop ()
В функции loop ()многократно контролируем входной сигнал с цифрового контакта pirPin для обнаружения движения. Выход этого контакта ВЫСОКИЙ, когда обнаружено движение, и НИЗКИЙ в противном случае.
Эта логика реализуется с помощью простого оператора if-else. Когда это условие выполняется, функция вызывает пользовательскую функцию blinkLED () для выполнения соответствующего действия на светодиодах. Пользовательские функции являются очень важным аспектом любого языка программирования.
Работа с пользовательскими функциями Arduino
Function используются, когда сегмент кода повторно выполняется для выполнения того же действия. Пользователь может создать пользовательскую функцию для организации кода или выполнения повторяющихся действий. Чтобы успешно использовать пользовательскую функцию, пользователь должен вызвать их из обязательных функций Arduino, таких как loop (), setup () или любую другую функцию, которая приводит к этим обязательным функциям:
return-type function_name (parameters){
# Action to be performed
Action_1;
Action_2;
Return expression;
}
Ниже приведена настраиваемая функция, которую использовали в коде проекта:
void blinkLED(int pin, String message){
digitalWrite(pin,HIGH);
Serial.println(message);
delay(1000);
digitalWrite(pin,LOW);
delay(2000);
}
В проекте функция blinkLED () не перенастраивает любое значение, когда оно вызывается из функции loop (). Следовательно, тип возвращаемого значения — void. При вызове функции мы передаем номер булавки и сообщение в качестве параметров:
blinkLED(greenLedPin, "No motion
detected.");
Эти параметры затем используются в выполненном действии (запись сообщения на последовательный порт и настройка статуса светодиода) с помощью функции blinkLED (). Эта функция также вводит задержку для выполнения мигания с помощью функции delay ().
Тестирование
Спроектированная система была проверена в разделе «Тестирование аппаратного обеспечения» с помощью ручных входов через программу тестирования Firmata. Необходимо убедиться, что проект выполняет объективные задачи автономно и неоднократно.
С портом USB, подключенным к компьютеру, необходимо открыть средство последовательного мониторинга из среды IDEArduino, перейдя в меню «Сервис» | SerialMonitor или нажав Ctrl + Shift + M. На экране последовательного монитора должно появиться сообщение, аналогичное показанному:
При написании функции blinkLED () для выполнения действий мы включили действие для записи строки через последовательный порт. Переместите руку над датчиком PIR таким образом, чтобы датчик PIR мог обнаружить движение.
Это событие должно заставлять систему мигать красным светодиодом и отображать строку, обнаруженную движением, на серийном мониторе. При отсутствии движения некоторое время можно увидеть зеленый светодиод, мигающий, пока не будет обнаружено следующее движение через датчик PIR.
Метод 2 — использование Python и Firmata
Можно использовать редактор по вашему выбору, но убедитесь, что сохраняются файлы с расширением .py. Скопируем следующие строки кода в новый файл и сохраним его как test.py:
#!/usr/bin/python
a = "Python"
b = "Programming"
print a + " "+ b
Чтобы запустить этот файл, выполните следующую команду на терминале, где сохранен файл test.py:
$ python test.py
Вы должны иметь возможность видеть текст PythonProgramming, напечатанный на терминале. Как вы можете видеть, файл начинается с #! / Usr / bin / python, который является местом установки Python по умолчанию. Добавив эту строку в свой код Python, вы можете напрямую выполнить файл Python с терминала. В операционных системах на основе Unix вам нужно сделать исполняемый файл test.py с помощью следующей команды:
$ chmod +x test.py
теперь, поскольку ваш файл является исполняемым, вы можете напрямую запустить файл, используя следующую команду:
$. / test.py
Теперь создадим новый файл Python со следующим фрагментом кода и запустим его. Обязательно необходимо изменить значение переменной порта в соответствии с вашей операционной системой:
Заголовок спойлера
# pir_1.py
# Импортировать требуемые библиотеки
import pyfirmata
from time import sleep
# Определить настраиваемую функцию для выполнения действия Blink
def blinkLED(pin, message):
print (message)
board.digital[pin].write(1)
sleep(1)
board.digital[pin].write(0)
sleep(1)
# Связать порт и панель с pyFirmata
port = 'COM3'
board = pyfirmata.Arduino(port)
# Используйте поток итератора, чтобы избежать переполнения буфера
it = pyfirmata.util.Iterator(board)
it.start()
# Define pins
pirPin = board.get_pin('d:7:i')
print(pirPin)
redPin = 12
greenPin = 13
# Check for PIR sensor input
while True:
# Ignore case when receiving None value from pin
value = pirPin.read()
while value is None:
pass
print(value)
if value is True:
# Perform Blink using custom function
blinkLED(redPin, "Motion Detected")
else:
blinkLED(greenPin, "No motion Detected")
# Выключить плату
board.exit()
В этом коде есть два основных компонента программирования: методы pyFirmata и функция Python для выполнения мигающего действия. Программа неоднократно обнаруживает события движения и выполняет мигающее действие.
В этом методе мы реализовали оператор while, чтобы поддерживать программу в цикле, пока пользователь не завершит работу вручную. Можно завершить код, используя комбинацию клавиш Ctrl + C.
Работа с методами pyFirmata
Работы с платой Arduino и протоколом Firmata необходимо начать с инициализации платы Arduino в качестве переменной. Метод pyFirmata, который позволяет пользователю назначить правление переменной Python, выглядит следующим образом:
board = pyfirmata.Arduino(port)
Как только значение переменной присвоено, можно выполнять различные действия, такие как чтение пина или отправка сигнала на вывод с использованием этой переменной. Чтобы назначить роль контакту, используется метод get_pin (). В следующей строке кода d представляет цифровой вывод, 7 — номер вывода, а i означает, что тип вывода — это входной вывод:
pirPin = board.get_pin('d:7:i')
Как только pin и его роль присваиваются переменной, эта переменная может использоваться для чтения или записи значений на выводе:
Value = pirPin.read ()
Можно напрямую записывать данные на конкретный вывод, как описано в следующем коде:
board.digital[pin].write(1)
Здесь метод write (1) посылает сигнал HIGH на вывод.
Работа с функциями Python
Функция Python начинается с ключевого слова def, за которым следует имя функции и входные параметры или аргументы. Определение функции заканчивается двоеточием (:) и после этого отступы. Оператор return завершает функцию. Оно также передает это выражение в место вызова функции.
Если оператор return сохраняется без выражения, считается, что оно передало возвращаемое значение None:
def function_name(parameters):
action_1
action_2
return [expression]
Предыдущая структура может быть использована для создания настраиваемых функций для выполнения повторяющихся задач. В нашем проекте у нас есть функция blinkLED (pin, message) для выполнения мигающего светодиода. Эта функция посылает 1 (HIGH) и 0 (LOW) значение на указанный цифровой контакт, а также печатает сообщение на терминале. Он также вводит задержку для имитации мигающего действия:
defblinkLED(pin, message):
print message
board.digital[pin].write(1)
sleep(1)
board.digital[pin].write(0)
sleep(1)
Тестирование
После запуска кода Python на терминале можно начинать тестирование. Если все идет по проекту, вы должны иметь возможность видеть в терминале следующий вывод:
Вы должны иметь возможность видеть строку обнаружения движения на терминале, когда какое-либо движение обнаружено датчиком PIR. Преимущество использования Python заключается в том, что незначительные изменения, такие как изменение скорости мигания или замена ролей светодиодов, могут быть выполнены путем простого изменения кода Python без участия С помощью Arduino или электрической цепи.
Выводы
Сравнительный анализ результатов практической реализации проекта двумя методами программирования, которые мы применили в этой работе показывает, что метод который использует только скетч Arduino, представляет традиционную парадигму программирования микроконтроллера. Хотя этот метод более прост в реализации, ему не хватает экстенсивности, достигаемой интерфейсом Python-Arduino. Таким образом, для практического применения мы делаем выбор в пользу метода Python-Arduino.