«Как зеницу ока...» или делаем простенькую охранную систему на базе микроконтроллера (Canny или Arduino) и Raspberry PI

  • Tutorial
Во время подготовки статьи, про распознавание микроконтроллеров с помощью TensorFlow и OpenCV мне одновременно на глаза попались Craftduino, Canny 3 tiny и Raspberry PI, после чего я решил, что будет здорово еще раз объединить их в одной статье. Я долго думал, о чем писать, а потом стыдно признаться, вспомнил, что я здоровый дядька, а еще ни разу не подключал ничего по UART. «В жизни надо попробовать всё» — подумал я. Но писать только про подключение к UART скучно, поэтому незамедлительно были заказаны всякие «игрушки», среди которых были новенькая Arduino, и пара датчиков.

Итак, сегодня мы будем делать охранную систему для моей любимой ручки. Вы удивлены почему именно ручка? Секрет прост, я весьма неопытен во всяких там вопросах электроники и поэтому, когда заказывал датчик давления думал, что он будет действовать по всей площади, а оказалось, что он работает только для определенной контактной площадки. Как ни странно, но во всём доме не оказалось ничего достаточно увесистого, устойчивого и подходящего по размерам, кроме этой ручки. Ну и кроме моего пальца, но экспериментировать с ним я был не готов .

В статье я поделюсь своим опытом подключения датчика давления и доплеровского датчика движения, к микроконтроллерам. Сами контроллеры через проводной интерфейс UART подключим к GPIO Raspberry PI 3. Затем напишем на Python простенькую программку для отображения статуса охранной системы, а в конце подключим смартфон к «малине» с помощью VNC, чтобы следить за охранной системой на удалении от компьютера.

Хотите оставить Индиану Джонса не у дел? Тогда милости прошу под кат.



Как всегда вначале поясню, что я сам новичок в вопросах DIY электроники и потихоньку учусь от статьи к статье. Поэтому не стоит воспринимать, то что я напишу, как истину в последней инстанции. Наверняка всё можно сделать лучше.

Вот о чем пойдет речь сегодня:

Часть I: Введение
Часть II: Подключение схемы и программа для Canny 3 tiny
Часть III: Подключение схемы и программа для Arduino Uno
Часть IV: Raspberry PI и программа для мониторинга на Python
Часть V: Заключение

Часть I: Введение


Внимательный читатель может задать вопрос: «А почему ты купил Arduino, если до этого упоминал CraftDuino?», все весьма банально. CraftDuino опять сломалась. Один раз DrZugrik мне её починил, а сейчас «самоизоляция», да и не хотелось мне человека беспокоить по пустякам.

Вот так, мы плавно подошли к материальной базе. Для этой статьи я использовал:

  1. Резистор давления FSR402:


  2. Доплеровский датчик движения RCWL-0516:


    В магазине, где я покупал оба датчика в описании на сайте было написано, что они для Arduino, но на практике оказалось, что никаких специальных библиотек не надо и на Canny всё запустилось без проблем.
  3. Микроконтроллер Arduino Uno:


  4. Микроконтроллер Canny 3 Tiny — версия с клеммой колодкой и кабельным жгутом:


  5. Одноплатный компьютер Raspberry PI 3 Model B:

  6. Прочее: макетные платы Breboard, провода и зажимы «крокодилы», адаптер питания для «Малины»

Перейдем к делу.

Часть II: Подключение схемы и программа для Canny 3 tiny


В интернете есть много примеров, как подключить Arduino по UART, про Canny примеров существенно меньше, поэтому начнем с него.
Чтобы не раздувать объем статьи и не повторяться, напомню, что самые основные вопросы, того, как работать с Canny и средой разработки CannyLab я рассмотрел в этой статье, а пример подключения датчиков к аналого-цифровому преобразователю (АЦП) и передачу сообщения через Virtual COM-порт, я разобрал в этой статье.

Для тех, кто не станет это читать, а сразу попробует подключить датчики к АЦП, есть важное замечание. Не повторяйте мою ошибку, для того, чтобы выходы контроллера № 5 и №6, смогли работать в режиме АЦП надо поставить перемычки, как на картинке ниже. Это не сложно, даже я справился.


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

Для этой статьи нам хватило бы и одной перемычки, но, если уж достали паяльник, зачем мелочиться?

Обратите внимание на клеммную колодку, в стандартной комплектации для этой версии контроллера идет родной кабельный жгут, он жесткий и наверняка удобный если использовать внутри автомобиля, а вот для опытов за столом — не очень. Я придумал ноу-хау, заменил родной жгут на жгуты, которые часто идут в комплекте с компьютерной техникой, ну или продаются в магазинах, торгующих DIY электроникой и это оказалось очень удобно. Они не плохо сидят в колодке, мягкие и при этом дают дополнительное удлинение.

Перейдем к схеме подключения:


Всё достаточно просто и не потребует каких-то особых навыков, думаю практически любой справится.

Вначале разберемся с питанием платы. «землю» мы возьмем с выхода «-» контроллера, а вот с плюсом все не так однозначно. На первый взгляд логичным кажется, подключится к клемме «+», но на практике это видимо клемма для ВХОДА +5В. Поэтому вместо нее мы настроим один из выходов, как вывод +5В, подав на него логическую единицу и подтянув к «плюсу». Я решил взять выход № 3.

Датчик давления подключается очень просто. По сути — это резистор. К одной его «ноге» подводим питание, а от второй «ноги» заводим провод на вход контроллера, подключенный к АЦП (либо № 5 либо № 6). Я выбрал № 6.

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

Датчик движения подключается не намного сложней, в гнездо «Vin» подводим +5В с платы, в гнездо «GND» соединяем с «землей» на макетной плате, а гнездо OUT соединяем с любым цифровым входом контроллера, я соединил с выходом № 5 (мы не будем переключать его в режим АЦП).

Осталось подключить контроллер к «Малине» через UART. Для этого выход № 2 контроллера, который в режиме «UART» у нас становится выходом «TX», надо подключить к входу GPIO RX «Малины», также надо соединить «землю» на плате и GPIO «GND» Raspberry PI.

Многие советуют согласовать уровень напряжения до 3.3 В, и я даже пробовал подключать Canny через делитель, напряжения, но с ним работает хуже чем без него (или вообще не работает), поэтому в данном случае я подсоединился к UART «Малины» напрямую. Вроде ничего не сгорело. Все работает.


Возможно, у вас возникла мысль: «Почему он подключается» проводами к UART, когда можно по Bluetooth?». Действительно, в сети есть много примеров подключения Arduino через UART к модулю HC-06. Если верить форуму, то Canny тоже подключается к нему без проблем. Но я еще сам не пробовал. Мне хотелось подключиться с помощью проводов, а подключение по Bluetooth я решил отложить до следующего раза.

Вот как схема выглядит в сборе:


Перейдем к программе для контроллера (диаграмме):


В блоке «Установка параметров», мы включаем режим АЦП для канала (входа) №6, канал № 3 переводим в режим дискретного выхода и подаем туда логическую единицу (+5В в нашем случае) практически всё разбирали в этой статье.

Незнакомы нам только параметры настройки UART. Благо тут всё просто. У Canny 3 tiny всего 1 интерфейс UART (например, у Canny 7 их два). При включения режима UART выход № 1 становится RX, выход № 2 TX. Мы выберем привычную многим скорость передачи 9600 бод, а вот режим передачи данных ограничен. Доступное количество бит данных только 8 байт и 1 стоповый бит(у «старших» моделей контроллеров выбор побольше), Для того, чтобы включить UART необходимо в соответствующий регистр «Регистр установки конфиг UART1» записать заранее заданную константу:


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

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

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

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

В блоке «Периодическая отправка по UART и VCP»
Мы с помощью генератора ШИМ задаем отправку 1 раз в 2 секунды для того, чтобы в течение секунды контроллер не забивал канал постоянной отправкой сообщения, мы используем «Детектор заднего фронта». Который сработает только один раз в момент переключения с единицы на ноль, если контроллер готов в этот момент передать сообщение по UART, то на вход блока логического умножение придут две единицы на выходе соответственно тоже буде «1», которая даст команду контроллеру отправить сообщение через UART, а также на всякий случай для отладки в USB-COM порт (об этом я подробно писал в прошлой статье).

В блоке «Индикация» все совсем просто, если значения с датчика давления меньше определённого порога и при этом датчик движения сработал (даст «1» на выход), то мы включим зеленый светодиод контроллера как сигнал о тревоге.

Было бы круто, если бы система работала как в кино:



Но мы ограничимся только включением светодиода.

Вот наглядная демонстрация:


Остался последний блок «Формирование сообщения»

Мы получаем данные с АЦП, разрешение АЦП от 0 до 1023. ПО UART мы посылаем символы, а значит показания от датчика давления, надо преобразовать в строку. Поскольку максимальное число 1023 (4 цифры) значит нам потребуется 4 байта. «Конвертер числа в строку» на выходах выдает пару символов, у нас будет 2 пары символов, каждую из них мы отправим в регистры установки сообщения UART и VCP. Дальше нам надо записать разделитель, чтобы показания не сливались, рас уж CannyLab использует пару символов, то возьмем в качестве разделителя два символа «пробел». Аналогичным образом преобразуем показания датчика движения, он дискретный выдает либо 00 либо 01, значит нам нужна только одна пара символов. В самом конце сообщения запишем символы перевода каретки и новой строки.

Как я уже писал в статье про фоторезистор, у Canny нет своего монитора COM-порта, но можно использовать любой сторонний, а рас уж мы чуть позже будем использовать Arduino IDE, то воспользуемся встроенным в него монитором COM-порта.

Вот, я давлю пальцем на датчик давления и попутно двигаюсь:



Диаграмму, как и весь код ниже можно скачать с GitHub.

Теперь переедем к Arduino.


Часть III: Подключение схемы и программа для Arduino Uno


Про Arduino я не буду, так подробно рассказывать, ибо всё достаточно тривиально.

Схема подключения:



Обратите внимание! Поскольку у Arduino выход RX/TX работа на напряжении 5В, а у Raspberry PI на 3.3 В, люди советуют, подключать Arduino к UART «Малины» с помощью специальных модулей или хотя бы с помощью делителя напряжения. Модуля специального у меня нет, а вот делитель напряжения — всегда пожалуйста. Я взял 3 резистора номиналом 1000 Ом. И сделал отвод после второго резистора, на котором упадет 2/3 напряжения. Если округлить питание по USB до 5 В, то как раз получается 5*0.66=3.3 В.

Хотя напрямую Arduino к UART Raspberry PI я тоже подключал и вроде все работало.

Датчик давление подключим к «+» и к аналоговому входу «А1». Датчик движения к питанию и цифровому входу № 5.

Вот так схема выглядит в сборе:



Вот код скетча для Ardino:

byte photoPin = A0;

void setup() {
Serial.begin(9600);
pinMode(photoPin, INPUT);
pinMode(5, INPUT);
pinMode(13, OUTPUT);
}

void loop() {
int adjustment = 250;
int pressure_sensor = analogRead(A1) - adjustment;
int motion_sensor = digitalRead(5);

Serial.print(pressure_sensor);
Serial.print(" ");
Serial.println(motion_sensor);
if ((pressure_sensor<380) && (motion_sensor==1))
{
digitalWrite(LED_BUILTIN, HIGH);
}
else {
digitalWrite(LED_BUILTIN, LOW);
}
delay(1000);
}


Код простой, единственное, что стоит объяснить это переменную «adjustment». Дело в том, что при подключении к Arduino датчик давления, даже без нагрузки временами показывал не нулевые значения, и я ничего лучше не придумал, как вычесть усредненное значение «шума», для унификации показаний с Canny.

Также, как и в прошлом случае, мы реализовали индикацию встроенным светодиодом, в том случае если датчики сработали:




Часть IV: Raspberry PI и программа для мониторинга на Python


Для начала, надо включить UART, а также SSH и VNC, чтобы потом подключаться к «Малине» с помощью смартфона

Зайдите в настройки Raspberry PI и включите SSH, VNC, UART, как на картинке:



Еще я на всякий случай отключил Bluetooth.

Напишем простую программу на Python, я использовал встроенную IDE и никаких дополнительных модулей Python не устанавливал. У меня был образ Raspbian with desktop, средний по размеру, который занимает примерно 1,1 Гб.

В нашей программе для мониторинга, мы будем использовать для вывода информации как консоль, так и графический интерфейс. Для реализации GUI я решил использовать Tkinter. Я правда пользуюсь им второй раз в жизни, но мне и надо было всего пару текстовых полей и диалоговое окно.

Вот код программы:

import serial
import time
from tkinter import *
from tkinter import ttk
from tkinter import messagebox

serialport = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1.0) 

window = Tk()  
window.title("Security system for my pen")  
window.geometry('400x170')
#Presure sensor label
lbl_ps = ttk.Label(window, text="Pressure sensor", font=("Arial Bold", 20))
lbl_ps.grid(column=0, row=0)
lbl_ps_status = ttk.Label(window, text=" ",  font=("Arial Bold", 20))
lbl_ps_status.grid(column=1, row=0)
#Motion sensor label
lbl_ms = ttk.Label(window, text="Motion sensor", font=("Arial Bold", 20))
lbl_ms.grid(column=0, row=1)
lbl_ms_status = ttk.Label(window, text=" ", font=("Arial Bold", 20))
lbl_ms_status.grid(column=1, row=1)

while True:
   counter = 0
   rcv = serialport.readline().decode('utf-8').replace("\r\n","").split('  ')
   if (len(rcv)==2):
       ps=rcv[0]
       ms=rcv[1]
       print (ps+ " " +ms)
       if (int(ps)<380):
           lbl_ps_status.config(text = " Warning!")
           counter += 1
       else:
           lbl_ps_status.config(text = " Ok")

       if (int(ms)>0):
           lbl_ms_status['text']=" Warning!"
           counter += 1
       else:
           lbl_ms_status['text']=" Ok"  
       window.update_idletasks()  
       window.update()
       if (counter == 2):
            messagebox.showinfo("Alarm!", "Сheck your pen!")     
       time.sleep(1)


Импорт библиотек я, пожалуй, пропущу.

После импорта мы задаем установки для UART, сам порт, скорость и время ожидания.

serialport = serial.Serial("/dev/ttyS0", baudrate=9600, timeout=1.0) 


Дальше размещаем по табличной верстке (по сетке) текстовые поля (Label)
У нас будет 4 поля из них 2 неизменных, а в двух других будет отображен статус датчика.

window.title("Security system for my pen")  
window.geometry('400x170')
#Presure sensor label
lbl_ps = ttk.Label(window, text="Pressure sensor", font=("Arial Bold", 20))
lbl_ps.grid(column=0, row=0)
lbl_ps_status = ttk.Label(window, text=" ",  font=("Arial Bold", 20))
lbl_ps_status.grid(column=1, row=0)
#Motion sensor label
lbl_ms = ttk.Label(window, text="Motion sensor", font=("Arial Bold", 20))
lbl_ms.grid(column=0, row=1)
lbl_ms_status = ttk.Label(window, text=" ", font=("Arial Bold", 20))
lbl_ms_status.grid(column=1, row=1)


Далее создадим бесконечный цикл.
В начале цикла будем обнулять метку тревоги counter .
Затем прочитаем, данные из последовательного порта.
Чтобы не смотреть на всяике записи типа “\x00”, перекодируем сообщение в UTF-8.
Затем уберем начало и конец строки, чтобы остались только цифры.
Далее разделим строку, обратите внимание разделитель 2 пробела, а не 1.
Чтобы программа не вылетала при некорректном сообщении дальнейший код, который завязан на получение сообщение запихнем в условную конструкцию, которая сработает, только если сообщение можно разделить на 2 части.
Ну и выведем в консоль показания датчика давления и датчика движения.

while True:
   counter = 0
   rcv = serialport.readline().decode('utf-8').replace("\r\n","").split('  ')
   if (len(rcv)==2):
       ps=rcv[0]
       ms=rcv[1]
       print (ps+ " " +ms)


Проверяем сработал датчики, если всё нормально, то система пишет «ОК», если один из датчиков сработал счетчик увеличивается на 1 и выдается предупреждение.


       if (int(ps)<380):
           lbl_ps_status.config(text = " Warning!")
           counter += 1
       else:
           lbl_ps_status.config(text = " Ok")

       if (int(ms)>0):
           lbl_ms_status['text']=" Warning!"
           counter += 1
       else:
           lbl_ms_status['text']=" Ok"  


В последнем блоке мы обновляем элементы формы Tkinter, после чего проверяем, сколько датчиков сработало. Если в цикле сработало оба датчика то появляется модальное окно с сообщением о тревоге.


       window.update_idletasks()  
       window.update()
       if (counter == 2):
            messagebox.showinfo("Alarm!", "Сheck your pen!")     
       time.sleep(1)


Здесь важно отметить, что датчик движения держит на выходе «1» в течение двух секунд с момента фиксации движения. Так, что как правило система успевает сработать.

Ниже снимки экрана, демонстрирующие работу программы:

Все датчики спокойны:



Сработал один из двух:



Сработали оба, система ждет квитирования оператором:



Вроде всё как и планировали.


Заключение


В заключение рассмотрим подключение к Raspberry PI со смартфона. В принципе сложного ничего нет, если вы можете подключиться с компьютера, то и с телефона сможете. Вам надо знать только IP «Малины», имя пользователя и пароль. На своём смартфоне под управлением ОС Android я установил VNC Viewer, но наверняка можно и другой клиент.

Пользоваться, не очень удобно, но работает:


Еще раз напомню, что весь код можно скачать с GitHub.

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

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

UPD:
Похоже, что у меня получился небольшой цикл статей, поэтому для вашего удобства я оставлю ссылки на другие статьи по теме:


  1. «Раз, два, три – ёлочка гори!» или мой первый взгляд на контроллер CANNY 3 tiny.
  2. «У Предназначения масса обличий...» или автоматизируем управление автолампой с помощью CANNY 3 tiny и фоторезистора.
  3. «Каких Марин?» или управляем контроллером через bluetooth с помощью мобильного приложения на Xamarin (Android).
AdBlock похитил этот баннер, но баннеры не зубы — отрастут

Подробнее
Реклама

Комментарии 12

    0

    Это не охранная система, разве что. Датчик давления может служить элементом охранной системы, если решить вопросы установки в корпус, монтажа, согласования уровней сигнала (для длинных проводов)…

      0
      Ну это же «игрушка». В статье речь не шла о серьезной системе. Датчик давления тоже выполняет охранную функцию, сняли предмет сработала тревога, его думаю можно было заменить концевиком, но это не принципиально. Ну а допоеровский датчик улавливает движения если человек потянется к объекту.
      0
      Всегда недоумеваю, когда вижу использование ардуины и Raspberry в одном проекте…
      Можно использовать Arduino + enc28j60 (или W5100/W5500) и воспользоваться внешним API для отправки сообщений куда-либо (Или сделать свой API для опроса самой ардуины с другого устройства по сети).
      Можно и esp32 использовать, если нужна вафля.

      Но зачем цеплять ардуину к одноплатнику? Raspberry и так умеет всё тоже, что и ардуина: SPI, i2c, GPIO, ADC/DAC… Почему бы не реализовать всё на нём? Но в данном случае — это лиш лишний размер и потребление энергии. Про отвод тепла — вообще больная тема.
        +1
        ADC/DAC
        Этого нет в Raspberry, только внешние.
          0
          А, пардон, спутал с PWM.
          Ну всё равно — это вопрос одной внешней микрухи.

          Но зачем в данной задаче распик, если ардуина или esp32 тут будет уместнее (Меньше размеры, энергопотребление, тепло и т.д.)
            0

            Это трэнд в последнее время.


            Все время встречаются статьи "как зажечь лампочку с помощью arduino + малина + питон".


            Я конечно утрирую, но на мой взгляд, такая примитивная задача как опрос двух датчиков и API в сеть не стоит ни такого подробного описания ни использования такого сочетания как микроконтроллер и одноплатный комп с Linux.
            И это никак не образец инженерного решения. Скорее анти паттерн решения.


            И да. Авторы таких статей, как правило очень обидчивы.


            На резонное замечание об использование, например, того же ESP32 следует как правило: "я так вижу" "художника всяк норовит обидеть" "это же учебная задача" и пр.

              0
              Все очень просто, есть материалы для начинающих, есть материалы для специалистов, это материал для начинающих, я думаю если вы ребенку лет 10 дадите учебник по математике за 9 класс, а потом скажете, что он не правильно решил дифференциальное уравнение, он тоже обидится. Этот материал не несет в себе практической ценности для профессионального сообщества, но он может быть полезен тем кто не понял 10 других примеров (включая документацию) и отхватил озарение только на 11-м. В статье несколько раз было упомянуто, что это не лучший пример и что есть пространство для творчества. Никто не мешает усложнить задачу, в данном случае показаны несколько базовых приемов взаимодействия. И еще один момент. Если статей о подключении ардуино к «малине» полно, то материалов о подключении canny к «малине», существенно меньше.
              Так что если вы закрываете нишу с более качественными и продуманными решениями, ну вы — молодец, Вас остаётся, только поблагодарить за Ваш труд и вклад в подготовку грамотных специалистов.
                0

                Есть материалы плохие и есть материалы хорошие. Материалы, которые учат складывать 2+2, решая дифференциальное уравнение плохи, ибо излишнее усложнение любой конструкции ведёт к ухудшению надёжности. И не важно что это Just For Fun.

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

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

        +1
        И чего люди не нагородят, лишь бы на Си не программировать )))
          0
          Си мне показался сложным в свое время, все никак не соберусь с духом освоить)

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

        Самое читаемое