#5 Эксперимент “Умный замок”
На этом занятии мы научимся работать с сервоприводом, познакомимся с понятием “библиотек” и разберём тонкости обмена данных между компьютером и платой Arduino.
Перед выполнением эксперимента прочтите:
Сервопривод – это механический привод, способный совершать поворот на определённый строго заданный угол. Внешне, сервопривод похож на двигатель постоянного тока. Сервопривод управляется по 3-м проводам: “питание”, “земля” и “сигнал”.
СБОРКА УСТРОЙСТВА НА МАКЕТНОЙ ПЛАТЕ
Нам понадобятся следующие компоненты:
- Arduino Uno;
- USB-кабель для подключения к компьютеру;
- Беспаечная макетная плата;
- 1 пьезодинамик;
- 1 светодиод;
- 1 резистор номиналом 220 Ом;
- 1 сервопривод;
- 8 соединительных проводов различных цветов.
Соберите устройство по следующей схеме:
Схема устройства на макетной плате |
Принципиальная схема устройства |
Обратите внимание:
- При подключении сервопривода обращайте внимание на цветовую маркировку его проводов: провод тёмного цвета (коричневый) подключается к “земле”, красного цвета – к пину 5V, жёлтого или оранжевого цветов – к сигнальному пину (в нашем случае это 8-й пин);
- схемы подключения светодиода и пьезодинамика Вам уже знакомы.
Для того, чтобы управлять сервоприводом с помощью Arduino, мы будем использовать библиотеку <Servo.h>, которая есть в Arduino IDE по умолчанию. Эта библиотека содержит все необходимые команды и инструкции для управления сервоприводом. Давайте опробуем повернуть вал сервопривода сначала в положение 0 градусов, затем 90 градусов и наконец в положение 180 градусов, т.е. пройдём его крайние и среднее положения. Напишем программу (комментарии внутри программы):
#include <Servo.h>; // подключаем библиотеку для управления сервоприводом Servo my_servo; // Объявляем переменную типа Servo void setup() { my_servo.attach(8); // инициализируем сервопривод на 8-м пине } void loop() { my_servo.write(0); // поворачиваем вал в положение 0 градусов delay(2000); my_servo.write(90); // поворачиваем вал в положение 90 градусов delay(2000); my_servo.write(180); // поворачиваем вал в положение 180 градусов delay(2000); }
Обратите внимание:
- объявляя переменную типа Servo, мы как-бы даём имя нашему сервоприводу, в нашем случае мы назвали его “my_servo”. В дальнейшем мы обращаемся к этому сервоприводу только через это имя;
- если в Вашей схеме присутствует несколько сервоприводов, то каждому из них нужно “дать имя”, т.е. объявить переменные типа Servo для каждого из сервоприводов;
- в случае с несколькими сервоприводами, инициализировать также нужно каждый из них. Для этого мы используем команду [attach].
- поскольку сервопривод не может повернуть вал мгновенно, необходимо делать некоторую паузу после команды поворота. Если поворот происходит между крайними положениями, т.е. между положениями 0 градусов и 180 градусов, то после команды поворота рекомендуется задать задержку хотя бы в 300 мс.
При работе с сервоприводом есть и свои маленькие нюансы, например:
- после того, как сервопривод завершил поворот, он может начать достаточно ощутимо вибрировать. Это происходит из-за того, что вал сервопривода не смог принять заданное положение и мотор пытается довернуть его. Обычно здесь речь идёт о долях градуса.
- от вибрации можно избавиться несколькими способами. Самый простой – купить сервопривод большей мощности, т.к. данный сервопривод не справляется с заданной нагрузкой. Следующий способ – попробовать уменьшить нагрузку на сервопривод, если он используется в каком-либо механизме. Третий способ – программный. Если Вам не принципиально точное позиционирование вала сервопривода, то его можно просто программно отключать после поворота с помощью команды [detach].
Давайте попробуем вращать сервопривод на случайный угол с последующим его отключением и без отключения, и сравним его поведение в обоих случаях (комментарии к программе находятся внутри кода):
// код поворота без отключения сервопривода #include <Servo.h>; Servo my_servo; void setup() { my_servo.attach(8); //инициализируем сервопривод 1 раз } void loop() { my_servo.write(random(0,181)); // поворот на случайный угол в диапазоне [0..180] delay(300); // задержка, чтобы дать валу повернуться delay(2000); // задержка между поворотами }
// код поворота с отключением сервопривода #include <Servo.h>; Servo my_servo; void setup() { } void loop() { my_servo.attach(8); // вначале каждого цикла инициализируем сервопривод my_servo.write(random(0,181)); // случайный угол поворота в диапазоне [0..180] delay(300); // задержка, чтобы дать валу провернуться my_servo.detach(); // отключаем сервопривод delay(2000); // задержка между поворотами }
Если Ваше сервопривод новый и находится не под нагрузкой, то возможно Вы и не заметите никакой разницы, тем не менее, теперь Вы знаете как избежать нежелательных вибраций.
Для чего можно использовать сервопривод в быту? Помимо элемента роботизированных механизмов, его можно применять для открытия и закрытия жалюзи, дверных замков, вентилей подачи воды и газа. Так-же можно сделать простейший электронный замок своего шкафчика.
Наша задача на этом занятии: создать прототип электронного замка, который вы сможете открыть, подав нужную команду с вашего компьютера. Принцип работы устройства будет заключаться в ожидании сигнала, переданного через последовательный порт. По этому сигналу, программа должна повернуть вал сервопривода в положение 0 градусов (для открытия замка) или в положение 180 градусов (для закрытия замка). При этом, в момент когда замок будет закрыт, пьезодинамик должен издать звуковой сигнал, а светодиод – зажечься. В случае, когда замок будет открыт, пьезодинами также должен издать звуковой сигнал, а светодиод – погаснуть.
Для передачи данных с компьютера в плату Arduino мы будем последовательный порт, к которому подключено наше устройство. На предыдущих занятиях, мы уже принимали данные с Arduino и могли их просматривать в мониторе порта. Сегодня мы попробуем не только принять, но и отправить сигнал в последовательный порт. Для этого, мы будем использовать следующую программную конструкцию:
String mess; // объявляем строковую переменную // для хранения полученных через порт данных void setup() { Serial.begin(9600); // инициализируем подключение к порту на скорости 9600 бод } void loop() { if (Serial.available()>0){ // если в порт пришло сообщение то... mess = Serial.readString(); // сохраняем его в переменной } }
Пояснения к коду:
- String – строковый тип данных, может хранить строку из символов длиной до 255 символов включительно. В нашем случае переменная строкового типа [mess] будет являться хранилищем принятых с компьютера сообщений;
- Отправленные с компьютера данные попадают в буфер микроконтроллера, откуда их можно считать. Команда [Serial.available()>0] проверяет – есть ли данные в буфере. Если данные есть, т.е. значение параметра >0, то можно их прочитать. В нашем случае мы их сохраняем в переменную [mess].
Далее, для управления подключённым к Arduino оборудованием, мы можем сравнивать содержимое переменной [mess], т.е. значения данных, которые пришли в порт и сравнивать их с “кодовыми” словами, которые будут являться сигналом к выполнению тех или иных команд. Сравнивать значения, которые пришли в порт с “кодовыми” значениями, мы будем с помощью оператора [if].
Далее, приведён код программы, способной открывать и открывать наш замок, т.е. поворачивать сервопривод:
#include <Servo.h>; // подключаем библиотеку сервопривода Servo my_servo; // объявляем переменную для сервопривода String mess; // объявляем переменную для хранения данных из порта void setup() { Serial.begin(9600); // инициализируем последовательное соединение pinMode(9, OUTPUT); // назначаем пин со светодиодом на выход } void loop() { if (Serial.available()>0){ // если в порт пришли данные, то... mess = Serial.readString(); // ... сохраняем их в переменную if (mess=="open"){ // если пришло слово open, то... my_servo.attach(8); // инициализируем сервопривод my_servo.write(0); // поворачиваем сервопривод на угол 0 градусов tone(7,200,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс tone(7,400,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс tone(7,500,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс my_servo.detach(); // отключаем сервопривод digitalWrite(9, LOW); // гасим светодиод на 9-м пине Serial.println("Замок открыт"); // посылаем сообщение в порт о том, что замок открыт } if (mess=="lock"){ // если пришло слово lock, то... my_servo.attach(8); // инициализируем сервопривод my_servo.write(180); // поворачиваем сервопривод на угол 180 градусов tone(7,200,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс tone(7,200,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс tone(7,200,50); // коротко пищим пьезодинамиком delay(100); // ждём 100 мс my_servo.detach(); // отключаем сервопривод digitalWrite(9, HIGH); // зажигаем светодиод на 9-м пине Serial.println("Замок закрыт"); // посылаем сообщение в порт о том, что замок закрыт } } }
Загрузите программу в плату Arduino и проверьте её работоспособность. Для этого:
- откройте монитор порта;
- отправьте команду “open”;
- убедитесь, что сервопривод повернулся, светодиод погашен, пьезодинамик проиграл 3 сигнала, а в порт пришло сообщение “Замок открыт”;
- отправьте команду “lock”ж
- убедитесь, что сервопривод повернулся, светодиод зажжён, пьезодинамик проиграл 3 сигнала, а в порт пришло сообщение “Замок закрыт”.
Теперь Вы знаете, как управлять устройствами, подключёнными к Arduino со своего компьютера. Большая часть домашней бытовой техники управляется путём её включения или выключения (электрочайник, обогреватель, компьютер, настольная лампа, вентилятор и т.д.). А это значит, что для их включения и выключения можно использовать реле, которое будет управляться с вашего компьютера.
ЗАДАНИЯ ДЛЯ САМОСТОЯТЕЛЬНОГО ВЫПОЛНЕНИЯ
Задание 1:
Измените программу таким образом, чтобы при получении кодового слова “open”, замок открывался ровно на 5 секунд, а затем закрывался автоматически;
Задание 2*:
Подключите к плате Arduino реле и напишите программу, которая будет включать его по команде “on”, а выключать по команде “off”. При этом, дополните код программы таким образом, чтобы выключение реле происходило и по сигналу с датчика вибрации. Таким образом вы разработаете устройство дистанционного включения и отключения электрического чайника с автоматическим отключением при закипании воды (при закипании, чайник начинает вибрировать, что и будет хорошим сигналом для датчика вибрации).