Как сделать датчик движения на камеру
Перейти к содержимому

Как сделать датчик движения на камеру

  • автор:

Делаем детектор движения, или OpenCV — это просто

Надо оправдывать название компании — заняться хоть чем-то, что связано с видео. По предыдущему топику можно понять, что мы не только чайник делаем, но и пилим «умное освещение» для умного дома. На этой недели я был занят тем, что ковырял OpenCV — это набор алгоритмов и библиотек для работы с компьютерным зрением. Поиск обьектов на изображениях, распознание символов и все такое прочее.

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

Сразу говорю: в статье может встретиться страшнейший быдлокод, который может вас напугать или лишить сна до конца жизни.

Если вам еще не страшно — то добро пожаловать дальше.

Введение

Собственно, в чем состояла идея. Хотелось полностью избавится от ручного включения света. У нас есть квартира, и есть люди, которые по ней перемещаются. Людям нужен свет. Всем остальным предметам в квартире свет не нужен. Предметы не двигаются, а люди двигаются(если человек не двигается — он или умер, или спит. Мертвым и спящим свет тоже не нужен). Соответственно, надо освещать только те места в квартире, где наблюдается какое-то движение. Движение прекратилось — можно через полчаса-час выключить свет.
Как определять движение?

О сенсорах

Можно определять вот такими детекторами:

Называют они PIR — Пассивный Инфракрасный Сенсор. Или не пассивный, а пироэлектрический. Короче, в основе его лежит, по сути, единичный пиксель тепловизора — та самая ячейка, которая выдает сигнал, если на нее попадает дальний ик.

Простая схема после нее выдает импульс только если сигнал резко меняется — так что на горячий чайник он сигналить не будет, а вот на перемещающийся теплый объект — будет.
Такие детекторы устанавливают в 99% сигнализаций, и вы их все думаю, видели — это те штуки, которые висят под потолком:

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

И в пирометрах, тех же термометрах, но с бОльши диапазоном:

Хотя я что-то отвлекся. Такие сенсоры, конечно, штука хорошая. Но у них есть минус — он показывает движение во всем обьеме наблюдения, не уточняя где оно произошло — близко, далеко. А у меня большая комната. И хочется включать свет только в той части, где работает человек. Можно было, конечно поставить штук 5 таких сенсоров, но я отказался от этой идеи — если можно обойтись одной камерой примерно за такую же сумму, зачем ставить кучу сенсоров?

Ну и OpenCV хотелось поковырять, не без этого, да. Так что я нашел в закромах камеру, взял одноплатник(CubieBoard2 на A20) и поехало.

Установка

Естественно, для использования OpenCV сначала надо поставить. В большинстве современных систем(я говорю про *nix) она ставится одной командой типа apt-get install opencv. Но мы же пойдем простым путем, да? Да и например в системе для одноплатника, которую я использую ее нету.
Исчерпывающее руководство по установке можно найти вот тут, поэтому я не буду очень подробно останавливаться на ней.
Ставим cmake и GTK(вот его я как раз со спокойной совестью поставил apt-get install cmake libgtk2.0-dev).
Идем на офсайт и скачиваем последнюю версию. А вот если мы полезем на SourceForge по ссылке из руководства на Robocraft, то скачаем не последнюю версию(2.4.6.1), а 2.4.6, в которой абсолютно неожиданно не работает прием изображения с камеры через v4l2. Я этого не знал, поэтому 4 дня пытался заставить работать эту версию. Хоть бы написали где-то.
Дальше — стандартно:

tar -xjf OpenCV-*.tar.bz2 && cd OpenCV-* && cmake -D CMAKE_BUILD_TYPE=RELEASE -D CMAKE_INSTALL_PREFIX=/usr/local ./ && make && make install 

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

cd samples/c/ && chmod +x build_all.sh && ./build_all.sh 

Собственно, большая часть моего кода взята из примера под названием motempl — это как раз и есть программа, реализующая функционал определения движения в кадре. Выглядит это вот так:

Допилка

Работает, но как это применить для включения света? Он показывает движение на экране, но нам-то надо, чтобы об этом узнал контроллер, который у нас управляет освещением. И желательно, чтобы он узнал не координаты точки, а место, в котором надо включить свет.

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

#include #include #include #include int main(int argc, char* argv[]) < CvCapture* capture = cvCaptureFromCAM(0);// Создаем обьект CvCapture(внутреннее название для обьекта, в который кладутся кадры с камеры), который называется capture. Сразу подключаем его к камере функцией cvCaptureFromCAM, 0 в параметрах которой означает, что видео надо брать с первой подвернувшейся камеры. IplImage* image = cvQueryFrame( capture ); // Создаем обьект типа изображение(имя image) и кладем туда текущий кадр с камеры cvNamedWindow("image window", 1); //Создаем окно с названием image window for(;;) //запускаем в бесконечном цикле < image = cvQueryFrame( capture ); //получаем очередной кадр с камеры и записываем его в image cvShowImage("image window", image);//Показываем в созданном окне(image window) кадр с камеры, который мы получили в предыдущем пункте cvWaitKey(10); //ждем 10 мс нажатия кнопки. Тут оно без надобности, но без этого окно не создается. Я не против, если кто-то, более понимающий в этом, объяснит такое поведение. >> 

Эту программу можно скопировать в файл test.c и собрать его вот так:

gcc -ggdb `pkg-config --cflags opencv` -o `basename test.c .c` test.c `pkg-config --libs opencv` 

Опять же, честно говоря, я не совсем понимаю, что именно делает эта команда. Ну собирает. А почему именно такая?

Оно запустится, и покажет вам видео с камеры. Но из него даже не получится выйти — программа застряла в бесконечном цикле и только Ctrl+C прервет ее бессмысленную жизнь. Добавим обработчик кнопок:

char c = cvWaitKey(10); //Ждем нажатия кнопки и записываем нажатую кнопку в переменную с. if (c == 113 || c == 81) //Проверяем, какая кнопка нажата. 113 и 81 - это коды кнопки "q" - в английской и русской раскладках. < cvReleaseCapture( &capture ); //корретно освобождаем память и уничтожаем созданные обьекты. cvDestroyWindow("capture"); //я тебя породил, я тебя и убью! return 0; //выходит из программы. >
CvFont font; //создаем структуру "шрифт" cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 1.0, 1,1,8); //Инициализуем ее параметрами - название шрифта, размеры, сглаживание struct timeval tv0; //Что-то связаннное с временем. int fps=0; int fps_sec=0; char fps_text[2]; int now_sec=0;//Создаем переменные . gettimeofday(&tv0,0); //Получаем текущее время now_sec=tv0.tv_sec; //Получаем из него секунды if (fps_sec == now_sec) //Сравниваем, совпадает ли текущая секунда с той, в которой вы считаем фпс < fps++; //если совпадает, то прибавляем еще один кадр(это все крутится в цикле, который рисует кадры.) >else < fps_sec=now_sec; //если не совпадает, то обнуляем секунду snprintf(fps_text,254,"%d",fps); //формируем текстовую строку с FPS fps=0; // обнуляем счетчик >cvPutText(image, fps_text, cvPoint(5, 20), &font, CV_RGB(255,255,255));//выводим в текущий кадр(image) в место с координатами 5х20, белым цветом, тем шрифтом, что мы задали ранее, переменную, в которой записан текущий фпс. 

Полный текст программы

#include "opencv2/video/tracking.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc_c.h" #include #include #include #include #include #include #include #include int main(int argc, char** argv) < IplImage* image = 0; CvCapture* capture = 0; struct timeval tv0; int fps=0; int fps_sec=0; int now_sec=0; char fps_text[2]; CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 1.0, 1,1,8); capture = cvCaptureFromCAM(0); cvNamedWindow( "Motion", 1 ); for(;;) < IplImage* image = cvQueryFrame( capture ); gettimeofday(&tv0,0); now_sec=tv0.tv_sec; if (fps_sec == now_sec) < fps++; >else < fps_sec=now_sec; snprintf(fps_text,254,"%d",fps); fps=0; >cvPutText(image, fps_text, cvPoint(5, 20), &font, CV_RGB(255,255,255)); cvShowImage( "Motion", image ); if( cvWaitKey(10) >= 0 ) break; > cvReleaseCapture( &capture ); cvReleaseImage(&image); cvDestroyWindow( "Motion" ); return 0; >

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

int dig_key=0;//переменная, хранящее нажатую кнопку int region_coordinates[10][4]; //координаты регионов, в которых надо определять движение. . char c = cvWaitKey(20); //Ждем нажатия кнопки и записываем нажатую кнопку в переменную с. if (c = 48) //Проверяем, относится ли нажатая кнопка к цифрам < dig_key=c-48; //key "0123456789" //если относится, то записываем в переменную номер кнопки. >cvSetMouseCallback( "Motion", myMouseCallback, (void*) image); //говорим, что нам надо выполнить подпрограмму myMouseCallback при событиях, связанных с мышью в окне Motion и с изображением image if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] == 0 && region_coordinates[dig_key][3] == 0) //Рисуем прямоугольник. Если есть в переменной только одни координаты - рисуем точку по этим координатам. cvRectangle(image, cvPoint(region_coordinates[dig_key][0],region_coordinates[dig_key][1]), cvPoint(region_coordinates[dig_key][0]+1,region_coordinates[dig_key][1]+1), CV_RGB(0,0,255), 2, CV_AA, 0 ); if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] != 0 && region_coordinates[dig_key][3] != 0) //А если в переменной двое наборов координат - рисуем полностью прямоугольник. cvRectangle(image, cvPoint(region_coordinates[dig_key][0],region_coordinates[dig_key][1]), cvPoint(region_coordinates[dig_key][2],region_coordinates[dig_key][3]), CV_RGB(0,0,255), 2, CV_AA, 0 ); void myMouseCallback( int event, int x, int y, int flags, void* param) //описываем что нам надо будет делать при событиях, связанных с мышью < IplImage* img = (IplImage*) param; //получаем картинку. Видимо, ему это надо для определение координат switch( event )< //вбираем действие в зависимости от событий case CV_EVENT_MOUSEMOVE: break; //ничего не делаем при движении мыши. А можно, например, кидать в консоль координаты под курсором: printf("%d x %d\n", x, y); case CV_EVENT_LBUTTONDOWN: //при нажатии левой кнопки мыши if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] == 0 && region_coordinates[dig_key][3] == 0) //если это второе нажатие(заполнена первая половина координат - х и у верхнего угла региона), то записываем в переменную вторую половину - х и у нижнего угла региона < region_coordinates[dig_key][2]=x; //dig_key - определяет, какой регион устанавливается сейчас. А меняется он нажатием цифровых кнопок. region_coordinates[dig_key][3]=y; >if (region_coordinates[dig_key][0] == 0 && region_coordinates[dig_key][1] == 0)//если это первое нажатие(не заполнена первая половина координат ), то записываем в переменную первую половину. < region_coordinates[dig_key][0]=x; region_coordinates[dig_key][1]=y; >break; > > 

Вот как оно работает:

Регионы переключаются цифровыми кнопками.

Полный текст программы

 #include "opencv2/video/tracking.hpp" #include "opencv2/highgui/highgui.hpp" #include "opencv2/imgproc/imgproc_c.h" #include #include #include #include #include #include #include #include int dig_key=0; int region_coordinates[10][4]; void myMouseCallback( int event, int x, int y, int flags, void* param) < IplImage* img = (IplImage*) param; switch( event )< case CV_EVENT_MOUSEMOVE: //printf("%d x %d\n", x, y); break; case CV_EVENT_LBUTTONDOWN: //printf("%d x %d\n", region_coordinates[dig_key][0], region_coordinates[dig_key][1]); if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] == 0 && region_coordinates[dig_key][3] == 0) < region_coordinates[dig_key][2]=x; region_coordinates[dig_key][3]=y; >if (region_coordinates[dig_key][0] == 0 && region_coordinates[dig_key][1] == 0) < region_coordinates[dig_key][0]=x; region_coordinates[dig_key][1]=y; >break; case CV_EVENT_RBUTTONDOWN: break; case CV_EVENT_LBUTTONUP: break; > > int main(int argc, char** argv) < IplImage* image = 0; CvCapture* capture = 0; struct timeval tv0; int fps=0; int fps_sec=0; int now_sec=0; char fps_text[2]; CvFont font; cvInitFont(&font, CV_FONT_HERSHEY_COMPLEX_SMALL, 1.0, 1.0, 1,1,8); capture = cvCaptureFromCAM(0); cvNamedWindow( "Motion", 1 ); for(;;) < IplImage* image = cvQueryFrame( capture ); gettimeofday(&tv0,0); now_sec=tv0.tv_sec; if (fps_sec == now_sec) < fps++; >else < fps_sec=now_sec; snprintf(fps_text,254,"%d",fps); fps=0; >cvSetMouseCallback( "Motion", myMouseCallback, (void*) image); if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] == 0 && region_coordinates[dig_key][3] == 0) cvRectangle(image, cvPoint(region_coordinates[dig_key][0],region_coordinates[dig_key][1]), cvPoint(region_coordinates[dig_key][0]+1,region_coordinates[dig_key][1]+1), CV_RGB(0,0,255), 2, CV_AA, 0 ); if (region_coordinates[dig_key][0] != 0 && region_coordinates[dig_key][1] != 0 && region_coordinates[dig_key][2] != 0 && region_coordinates[dig_key][3] != 0) cvRectangle(image, cvPoint(region_coordinates[dig_key][0],region_coordinates[dig_key][1]), cvPoint(region_coordinates[dig_key][2],region_coordinates[dig_key][3]), CV_RGB(0,0,255), 2, CV_AA, 0 ); cvPutText(image, fps_text, cvPoint(5, 20), &font, CV_RGB(255,255,255)); cvShowImage( "Motion", image ); char c = cvWaitKey(20); if (c = 48) < dig_key=c-48; //key "0123456789" >> cvReleaseCapture( &capture ); cvReleaseImage(&image); cvDestroyWindow( "Motion" ); return 0; > 

Но не будем же мы каждый раз при запуске программы устанавливать регионы наблюдения вручную? Сделаем сохранение в файл.

FILE *settings_file; FILE* fd = fopen("regions.bin", "rb"); //открываем файл. "rb" - чтение бинарных данных if (fd == NULL) < printf("Error opening file for reading\n"); //если файл не нашли FILE* fd = fopen("regions.bin", "wb"); //пытаемся создать if (fd == NULL) < printf("Error opening file for writing\n"); >else < fwrite(region_coordinates, 1, sizeof(region_coordinates), fd); //если получилось - записываем туда нулевые координаты fclose(fd); //закрываем файл printf("File created, please restart program\n"); >return 0; > size_t result = fread(region_coordinates, 1, sizeof(region_coordinates), fd); //читаем файл if (result != sizeof(region_coordinates)) //если прочитали количество байт не равное размеру массива printf("Error size file\n"); //вываливаем ошибку fclose(fd); //закрываем файл FILE* fd = fopen("regions.bin", "wb"); //открываем файл. "wb" - запись бинарных данных if (fd == NULL) //если на нашли файл printf("Error opening file for writing\n"); //ругаемся fwrite(region_coordinates, 1, sizeof(region_coordinates), fd); //читаем файл в массив fclose(fd); //закрываем файл 

Привязываем эти функции, например на кнопки w и r, и при нажатии их сохраняем и открываем массив.

Осталась самая малость — собственно, определение в каком регионе произошло движение. Переносим наши наработки в исходник motempl.с, и находим куда нам можно вклиниться.
Вот функция, которая рисует круги на месте обнаружения движения:

cvCircle( dst, center, cvRound(magnitude*1.2), color, 3, CV_AA, 0 );

А координаты центра определяются вот так:

center = cvPoint( (comp_rect.x + comp_rect.width/2), (comp_rect.y + comp_rect.height/2) );

Вставляем в этот кусок свой код:

int i_mass; //создаем переменную цикла for (i_mass = 0; i_mass = region_coordinates[i_mass][0] && comp_rect.y + comp_rect.height/2 = region_coordinates[i_mass][1] ) //проверяем, принадлежит ли точка, в которой обнаружено движение нашему прямоугольнику-региону. < cvRectangle(dst, cvPoint(region_coordinates[i_mass][0],region_coordinates[i_mass][1]), cvPoint(region_coordinates[i_mass][2],region_coordinates[i_mass][3]), CV_RGB(0,0,255), 2, CV_AA, 0 ); //если текущая точка принадлежит региону, то рисуем этот регион синим прямоугольником, показывая, что в нем произошло срабатывание. printf("Detect motion in region %d\n",i_mass); //и ругаемся в консоль с номером региона >> 

Осталось немного: направлять вывод не в консоль, а в UART, подключить к любому МК реле, которые будут управлять светом. Программа обнаруживает движение в регионе, отправляет номер региона контроллеру, а тот зажигает назначенную ему лампу. Но об этом — в следующей серии.

Исходник проекта я выложил на github, и буду не против, если кто-нибудь найдет время для исправления ошибок и улучшения программы:
github.com/vvzvlad/motion-sensor-opencv

image

Напоминаю, если вы не хотите пропустить эпопею с чайником и хотите увидеть все новые посты нашей компании, вы можете подписаться на на странице компании(кнопка «подписаться»)
И да, я опять писал пост в 5 утра, поэтому приму сообщения об ошибках. Но — в личку.

  • Блог компании AVI
  • Работа с видео

ИК датчик движения на STM32

Приветствую, в этой статье вы узнаете: как сделать датчик движения с использованием ИК диода и ИК приемника на STM32 с минимальным использованием ядра (т.е. с максимальной загрузкой периферии) на регистрах, используя таймеры.

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

Оглавление:

Общая картина

Используются два устройства: передатчик ИК сигнала и приемник ИК сигнала.

Общий принцип работы следующий: передатчик ИК сигнала излучает сигнал инфракрасного диапазона длин волн, а приемник ИК сигнала их принимает. Между этими устройствами образуется «луч», пересечение которого каким-либо объектом фиксируется приемным устройством.

В качестве ИК диода используется TSAL6200, в качестве ИК приемника – TSOP4856.

TSAL6200 TSOP4856

Схемы устройств

Опустим цепи питания и другие элементы реальных устройств и рассмотрим только необходимые.

Передатчик ИК сигнала состоит из микроконтроллера STM32L151C8T6, полевого транзистора 2N7002, резистора 1 Ом и ИК диода TSAL6200. Ниже представлена электрическая схема передатчика.

Транзистор необходим для усиления тока, протекающего через ИК диод, так как выходной ток с пина МК ограничен (выходной ток с пина МК STM32L151C8T6 не более 25 мА, максимальный постоянный ток через ИК диод TSAL6200 100 мА).

Выбор транзистора на ваше усмотрение. Здесь выбран транзистор 2N7002, потому что он дешевый и его характеристик достаточно для моего использования. Стоит выбирать транзистор с меньшим пороговым напряжением затвора (Gate Threshold Voltage), так как на затвор вы сможете подать напряжение не более напряжения питания без дополнительных цепей, в нашем случае 3.3 В.

Точный расчет величины сопротивления резистора является трудным, конечно, существуют специальные формулы, но я предлагаю подобрать резистор опытным путем. Так в моем случае используется резистор 1 Ом, амплитуда тока цепи составляет 20 мА, дальность связи при таком токе достигает 14 м в зависимости от конфигурации передаваемого сообщения (количество импульсов в пачке, скважность, об этом ниже). Если вам требуется большая дальность, следует или подобрать резистор поменьше, или увеличить напряжение питания для диода, или выбрать транзистор с меньшим пороговым напряжением и меньшим падением напряжения на сток-истоке.

Приемник ИК сигнала состоит из микроконтроллера STM32L151C8T6, ИК приемника TSOP4856, резистора 100 Ом и конденсатора 0.1 мкФ. Ниже представлена электрическая схема приемника.

Работа ИК диода и ИК приемника

При протекании тока через диод TSAL6200 излучается ИК сигнал с длиной волны 940 нм. Это излучение необходимо промодулировать меандром с частотой 56 кГц (приемник настроен на данную частоту, см. даташит). Передавать следует пачки таких импульсов с определенной скважностью.

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

Остается только запрограммировать работу передатчика и приемника.

Код передатчика ИК сигнала

Будем использовать таймеры для формирования пачек импульсов с выводом сигнала на конкретный пин. Таким образом, ядро МК только инициализирует эти таймеры, а дальше может заниматься какой-нибудь другой работой.

Выбор пина должен быть обоснован. Необходимо выбирать такой пин, к которому может быть подключен какой-либо канал (кроме четвертого) любого General-purpose таймера. В нашем случае выбран пин PB6, к нему подключается первый канал TIM4. Приемник же будет подключен к пину PB7, второй канал TIM4.

Будем использовать два таймера: TIM4 будет генерировать меандр с частотой 56 кГц, TIM2 будет управлять таймером TIM4, т.е. создавать пачки из меандра. TIM2 будет работать в режиме Master, TIM4 – Slave. Почему именно таймер TIM2? Он выбран исходя из таблицы даташита подключений таймеров друг к другу.

Приступим к написанию функции инициализации таймеров Tim_Init_Transmitter(). Код написан для пустого проекта. Сначала объявляем функцию, в теле main её инициализируем, а после мэйна прописываем уже саму функцию.

#include "main.h" void Timer_Init_Transmitter(void); int main(void) < RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable Timer_Init_Transmitter(); while(1) < >> void Timer_Init_Transmitter(void)

RCC->ICSCR |= RCCICSCRMSIRANGE_6 — эта строчка просто устанавливает частоту 4.194 МГц МК. У вас может быть любая другая частота.

Настраиваем пин. Включаем тактирование, включаем альтернативную функцию, выбираем скорость пина повыше (это не является необходимым), выбираем какую именно альтернативную функцию хотим подключить к пину. Под спойлерами описано все подробно.

Подробнее про включение тактирования

В даташите находим регистр RCC_AHBENR. Нужно прописать «1» в поле GPIOBEN.

Для этого выбираем в библиотеке CMSIS строчку RCC_AHBENR_GPIOBEN , которая ставит данный бит в единицу.

И изменяем регистр AHBENR следующим образом:

RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable

Подробнее про включение альтернативной функции

В даташите находим регистр GPIOx_MODER. Нужно прописать «10» в поле MODER6 (для пина PB6).

Для этого выбираем в библиотеке CMSIS строчку GPIO_MODER_MODER6_1 , которая ставит второй бит в единицу.

В дальнейшем все такие обозначения будут браться аналогично.

И изменяем регистр MODER следующим образом:

GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable

Включение высокой скорости для пина делается аналогично включению альтернативной функции.

Подробнее про выбор альтернативной функции

Обозначение альтернативных функций представлено на картинке ниже.

Нам нужна альтернативная функция для TIM4 – это AF2.

Стоит отметить, что существует два регистра для выбора альтернативных функций: нижний GPIOx_AFRL для пинов с номерами от 0 до 7 и верхний GPIOx_AFRH для пинов с номерами от 8 до 15. Однако, в библиотеке CMSIS определен сдвоенный регистр AFR[2], прописав в скобки «0», мы выбираем нижний регистр, прописав «1», выбираем верхний регистр.

В даташите находим регистр GPIOx_AFRL.

Нам нужно прописать «0010» в поле AFRL6, для этого нам нужно число в шестнадцатеричной форме 0x2000000, «2» седьмая справа для пина PB6, потому что первые шесть цифр для пинов с номерами от 0 до 5.

И изменяем регистр AFRL следующим образом:

GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable

Получили следующий код для настройки пина внутри нашей функции:

void Timer_Init_Transmitter (void) < //Settings for GPIO PB6 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable > 

Теперь перейдем к настройке TIM4.

Нам нужно выбрать прескейлер PSC (делитель частоты), рассчитать значения для регистров CCR1 (длительность импульса) и ARR (период импульсов), выбрать режим работы таймера ШИМ, выбрать входной управляющий сигнал от таймера TIM2, выбрать режим для Slave и подать выходной сигнал таймера на пин PB6.

Включение тактирования осуществляется аналогично включению тактирования GPIO.

Подробнее про выбор прескейлера PSC и расчет CCR1 и ARR

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

И изменяем регистр PSC следующим образом:

TIM4->PSC = 0; //Prescaler value

Перейдем к расчету ARR.

Для расчета ARR нам нужно поделить тактовую частоту таймера 4.194 МГц (у вас своя) на 56 кГц. Получаем 74,89, округляем до целого. Я округлил до 75. И вписываем в регистр ARR:

TIM4->ARR = 75 //Auto-reload value

Осталось рассчитать CCR1.

Так как у нас простой меандр, то в регистр CCR1 при режиме ШИМ нужно указать половину от значения ARR:

TIM4->CCR1 = 37; //Capture/Compare 1 value

Подробнее про выбор режима работы ШИМ таймера

Так как у нас первый канал, то используем регистр CCMR1. Нас интересует в этом регистре поле OC1M. Режим ШИМ позволяет настраивать длительность импульса при фиксированном периоде.

Выберем PMW mode 1, вписав две единицы во второй и третий биты, т.е. «110»:

TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1

Подробнее про настройку подачи выходного сигнала на пин PB6

В регистр CCER в поле CC1E нужно вписать «1», включив подачу выходного сигнала на пин.

Вписываем следующую строчку:

TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding pin

Подробнее про выбор управляющего сигнала и режима Slave

Для управления TIM4 таймером TIM2 нужно выбрать входной сигнал ITR1. Для этого нужно вписать в поле TS регистра TIMx_SMCR «001». Также выберем режим для Slave, вписав «101» в поле SMS. В этом режиме пока входной сигнал ITR1 будет высоким, то TIM4 будет работать и выдавать меандр на пин, как только ITR1 станет низким, TIM4 выключается.

Для этого вписываем:

TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1

TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode

Добавим к уже существующему коду, и получим:

void Timer_Init_Transmitter (void) < //Settings for GPIO PB6 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable //Settings for TIM4 - Slave RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable TIM4->PSC = 0; //Prescaler value TIM4->ARR = 75; //Auto-reload value TIM4->CCR1 = 37; //Capture/Compare 1 value TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1 TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable > 

Включение TIM4 можно производить, а можно и нет, так как управляющий сигнал с TIM2, всё равно включит его.

Теперь перейдем к настройке TIM2.

Необходимо подать тактирование на таймер, рассчитать PSC, CCR1 и ARR, выбрать режим работы таймера ШИМ, выбрать какой сигнал будет выходным (входным управляющим для TIM4) и включить таймер.

Включение тактирования аналогично, как и для таймера TIM4.

RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable

Подробнее про расчет PSC, CCR1 и ARR для TIM2

Так как по даташиту на диод в пачке следует использовать не менее 10 импульсов (на самом деле можно и меньше, но качество работы может быть не очень хорошим), то выберем тактирование таймера TIM2 в десять раз меньше, чем TIM4.

Как видим в формуле для расчета частоты тактирования таймера в знаменателе уже есть «+1», т.е. нам нужно записать в регистр PSC «9», чтобы получить частоту в 10 раз меньшую, чем частоту МК.

TIM2->PSC = 9; //Prescaler value

Теперь рассчитаем значение для CCR1: отправлять будем 10 импульсов, следовательно, нам нужно взять значение ARR для TIM4 (период одного импульса, это 75) и умножить на 10, т.е. получаем 750, однако, у нас есть прескейлер, который делит частоту на 10, т.е. нам нужно поделить 750 на 10, в итоге получаем снова 75 (как и в TIM4, но уже с другим прескейлером). Запишем это значение в регистр CCR1 таймера TIM2.

TIM2->CCR1 = 75; //Capture/Compare 1 value

Перейдём к расчету ARR: тут всё просто, допустим, хотим «стрелять» пачками со скважностью 11.2, при этом период излучения пачек будет около 2 мс (из расчета, что 1 мс это 4194000/1000 = 4194 тика, и умножаем на 2, получаем округлённо 8400, а с прескейлером 10, получаем 840 тиков), умножаем длительность пачки 75 на 11.2 и получаем 840, как видите, значения совпадают. Запишем это в регистр ARR.

TIM2->ARR = 840; //Auto-reload value

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

Режим работы таймера TIM2 точно такой же, как и у TIM4 — ШИМ.

TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable

Подробнее про выбор выходного сигнала TIM2 (управляющего для TIM4)

Найдем регистр TIMx_CR2.

Нам нужно подать сигнал с первого канала (мы же используем CCR1), на выход с таймера TIM2. Этим сигналом является OC1REF. Ниже на картинке можно найти комбинацию битов для этого сигнала – «100».

В поле MMS необходимо вписать «1» в третий бит.

TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO)

Теперь осталось включить TIM2, записав следующую строчку:

TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable

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

Добавим эти строчки к предыдущим и получим:

void Timer_Init_Transmitter (void) < //Settings for GPIO PB6 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable //Settings for TIM4 - Slave RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable TIM4->PSC = 0; //Prescaler value TIM4->ARR = 75; //Auto-reload value TIM4->CCR1 = 37; //Capture/Compare 1 value TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin TIM4->SMCR &= ~TIM_SMCR_TS; //clear bits TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1 TIM4->SMCR &= ~TIM_SMCR_SMS; //clear bits TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable //Settings for TIM2 - Master RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable TIM2->PSC = 9; //Prescaler value TIM2->ARR = 840; //Auto-reload value TIM2->CCR1 = 75; //Capture/Compare 1 value TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO) TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable > 

Теперь у нас ИК диод будет излучать пачки по 10 импульсов, у которых частота 56 кГц, со скважностью 11.2, т.е. с периодом следования пачек в 2 мс. Заметим, что момент пересечения каким-либо объектом внутри периода пачек не определен, т.е. мы можем судить о пересечении ИК луча только по отсутствию следующей пачки. Таким образом, погрешность измерения момента времени пересечения луча составляем 2 мс.

Код приемника ИК сигнала

Для приема ИК сигнала снова будем использовать таймеры, а точнее всего один. В микроконтроллерах STM32 таймеры могут быть не только Master или Slave, а могут быть Master/Slave, т.е. они могут управлять сами собой.

В разделе статьи «Код передатчика ИК сигнала» мы уже выбрали пин PB7 для приемника ИК сигнала. Схему подключения см. выше. К этому пину подключается второй канал TIM4.

Ниже на картинке представлена схема устройства таймера.

Из схемы видно, что у каждого канала есть вход и выход, у таймера есть входной управляющий сигнал TRGI, также показаны тактирование и устройство Trigger controller.

Принцип работы для нашего проекта заключается в следующем: пусть наш таймер будет просто считать время, допустим, равное 5 периодам излучаемых пачек ИК сигнала, следовательно, в ARR будет число, равное 5 периодам пачек, т.е. 840 * 5 = 4200. Настроим таймер так, чтобы при приеме каждой пачки таймер перезагружался и начинал считать заново. При достижении таймером числа в регистре ARR таймер выдает прерывание, которое означает, что на вход уже как 5 периодов не приходит пачка, следовательно, луч пересекается каким-то объектом. Вот и вся работа таймера. Осталось настроить TIM4.

Создадим новый проект и функцию инициализации таймера:

#iclude "main.h" void Timer_Init_Receiver(void); int main(void) < RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable Timer_Init_Receiver(); while(1) < >> void Timer_Init_Receiver(void)

Необходимо настроить пин PB7: включить тактирование порта B, настроить альтернативную функцию пина, настроить скорость и выбрать какую конкретную альтернативную функцию подключить к пину. Всё, как и в предыдущем случае.

void Timer_Init_Receiver(void) < //Settings for GPIO PB7 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7 GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable > 

Все настройки аналогичны, как и для передатчика, только альтернативная функция немного отличается, «2» нужно вписать уже на восьмое место справа. Еще необходимо подтянуть пин к плюсу прописав строчку:

Теперь настроим TIM4.

Включим тактирование таймера. Так как у нас второй канал, то будем использовать CCR2. Прескейлер приравняем к 9, чтобы частота тактирования таймера была как у TIM2 передатчика. Для приемника можно приравнять CCR2 и ARR. Как уже рассчитали ранее, вписываем в эти регистры 4200.

RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable

TIM4->PSC = 9; // Prescaler value

TIM4->ARR = 4200; // Auto-reload value

TIM4->CCR2 = 4200; // Capture/Compare 2 value

Далее настроим режим работы таймера.

Нам нужно, чтобы он просто считал, и всё. Для этого в даташите находим TIMx_CCMR1 и в поле OC2M вписываем «000», что соответствует Frozen mode. Изменим регистр, обнулив все биты:

TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable

Настроим канал на выход, обнулив биты поля CC2S (более подробно написано в даташите), впишем нули в эти биты:

Теперь обратимся к картинке со схемой устройства таймера (см. выше). Нам необходимо, чтобы входной сигнал с пина PB7 был управляющим для таймера TIM4, таким сигналом является TI2FP2. Проследите путь этого сигнала от TIMx_CH2 до TRGI. Чтобы выбрать данный сигнал в качестве управляющего, необходимо в регистр TIMx_SMCR в поле TS вписать «110». Сразу же выберем режим для Slave: Reset mode, вписав «100» в поле SMS. Для этого пропишем строчки:

TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2

TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode

Теперь нам нужно определиться, что будет являться триггером обновления таймера: передний или задний фронт входных импульсов (на самом деле не особо важно, но лучше выбрать по переднему фронту, в нашем случае, это фронт спада напряжения). Для этого нужно использовать пару битовых полей регистра CCER: CC2P и CC2NP, они работают в паре, более подробно написано о них в даташите.

Для нашего случая вписываем «1» в CC2P и «0» в CC2NP. Делаем это так:

TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P.

TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge

Разрешим прерывание по переполнению. Для этого в регистре TIMx_DIER в поле CC2IE впишем «1».

Для этого впишем строчку:

TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable

Включаем таймер строчкой:

TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable

Не забываем разрешить глобальное прерывание:

NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable

Наша функция инициализации таймера выглядит следующим образом:

void Timer_Init_Receiver(void) < //Settings for GPIO PB7 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7 GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable //Settings for TIM4 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable TIM4->PSC = 9; // Prescaler value TIM4->ARR = 4200; // Auto-reload value TIM4->CCR2 = 4200; // Capture/Compare 2 value TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P. TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2 TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable > 

Теперь напишем обработчик прерываний:

Первое что нужно сделать, это снять флаг в регистре статуса TIMx_SR:

Далее можем делать, что хотим. Хоть ставить какой-нибудь флаг, хоть зажигать диод. Допустим будем зажигать светодиод. Настроим пин PB15 на выход, прописав в мэйне:

GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode

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

void TIM4_IRQHandler(void) < TIM4->SR &= ~TIM_SR_CC2IF; GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on > 

Готово! Теперь при пересечении ИК луча каким-либо объектом, на приемнике будет зажигаться светодиод.

Полный код

Код передатчика ИК сигнала

void Timer_Init_Transmitter(void); int main(void) < RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable Timer_Init_Transmitter(); while(1) < >> void Timer_Init_Transmitter(void) < //Settings for GPIO PB6 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; //GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER6_1; //Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR6_1; //High speed GPIOB->AFR[0] |= 0x2000000; //Pin PB6 TIM4 alternative function AF2 enable //Settings for TIM4 - Slave RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; //TIM4 clock enable TIM4->PSC = 0; //Prescaler value TIM4->ARR = 75; //Auto-reload value TIM4->CCR1 = 37; //Capture/Compare 1 value TIM4->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable TIM4->CCER |= TIM_CCER_CC1E; //OC3 signal is output on the corresponding output pin TIM4->SMCR &= ~TIM_SMCR_TS; //clear bits TIM4->SMCR |= TIM_SMCR_TS_0; //choosing ITR1 TIM4->SMCR &= ~TIM_SMCR_SMS; //clear bits TIM4->SMCR |= TIM_SMCR_SMS_0 | TIM_SMCR_SMS_2; //Gated Mode TIM4->CR1 |= TIM_CR1_CEN; //TIM4 enable //Settings for TIM2 - Master RCC->APB1ENR |= RCC_APB1ENR_TIM2EN; //TIM2 clock enable TIM2->PSC = 9; //Prescaler value TIM2->ARR = 840; //Auto-reload value TIM2->CCR1 = 75; //Capture/Compare 1 value TIM2->CCMR1 |= TIM_CCMR1_OC1M_1 | TIM_CCMR1_OC1M_2; //Output compare PMW mode 1 enable TIM2->CR2 |= TIM_CR2_MMS_2; //OC1REF signal is used as trigger output (TRGO) TIM2->CR1 |= TIM_CR1_CEN; //TIM2 enable > 

Код приемника ИК сигнала

#include “main.h” void Timer_Init_Receiver(void); int main(void) < RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode Timer_Init_Receiver(); while(1) < >> void Timer_Init_Receiver(void) < //Settings for GPIO PB7 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7 GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable //Settings for TIM4 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable TIM4->PSC = 9; // Prescaler value TIM4->ARR = 4200; // Auto-reload value TIM4->CCR2 = 4200; // Capture/Compare 2 value TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P. TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2 TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable > void TIM4_IRQHandler(void) < TIM4->SR &= ~TIM_SR_CC2IF; GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on > 

Дополнительно

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

Нужно добавить глобальную переменную, например, написав между «инклюдами» и мэйном такую строчку:

int StatusDiode = 0; // 0 — diode is off, 1 — diode is on

Эта переменная необходима для запоминания статуса светодиода: выключен или включен.

Далее в функции инициализации таймера нужно изменить строчку с разрешением прерывания по переполнению на разрешение прерывания по триггеру, такой строчкой:

TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable

И последнее: изменим обработчик прерываний.

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

Если диод был включен, делаем все наоборот: снимаем соответствующий флаг, выключаем диод, выключаем разрешение прерывания по переполнению, включаем разрешение прерывания по триггеру и изменяем статус диода.

Стоит помнить, что счетчик не останавливается, если не выключить таймер, однако, при прерывании по переполнению он перезагружается (обновляется регистр CNT), а при прерывании по триггеру обновления не происходит, поэтому мы его и обнуляем.

Получим такой обработчик прерываний:

void TIM4_IRQHandler(void) < if (StatusDiode == 0) < TIM4->SR &= ~TIM_SR_TIF; GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on TIM4->DIER &= ~TIM_DIER_TIE; // Trigger interrupt disable TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable TIM4->CNT = 0; StatusDiode = 1; > else < TIM4->SR &= ~TIM_SR_CC2IF; GPIOB->ODR &= ~GPIO_ODR_ODR_15; // Led red off TIM4->DIER &= ~TIM_DIER_CC2IE; // Capture/Compare 2 interrupt disable TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable StatusDiode = 0; > > 

Полный код для приемника ИК сигнала

#include “main.h” void Timer_Init_Receiver(void); int main(void) < RCC->ICSCR |= RCC_ICSCR_MSIRANGE_6; // MSI 4.194 MHz enable GPIOB->MODER |= GPIO_MODER_MODER15_0; // PB15 output mode Timer_Init_Receiver(); while(1) < >> void Timer_Init_Receiver(void) < //Settings for GPIO PB7 RCC->AHBENR |= RCC_AHBENR_GPIOBEN; // GPIO port B clock enable GPIOB->MODER |= GPIO_MODER_MODER7_1; // Alternative function mode enable GPIOB->OSPEEDR |= GPIO_OSPEEDER_OSPEEDR7_1; // High speed GPIOB->PUPDR |= GPIO_PUPDR_PUPDR7_0; // pull-up PB7 GPIOB->AFR[0] |= 0x20000000; // Pin PB7 TIM4 alternative function AF2 enable //Settings for TIM4 RCC->APB1ENR |= RCC_APB1ENR_TIM4EN; // TIM4 clock enable TIM4->PSC = 9; // Prescaler value TIM4->ARR = 4200; // Auto-reload value TIM4->CCR2 = 4200; // Capture/Compare 2 value TIM4->CCMR1 &= ~TIM_CCMR1_OC2M; // Frozen mode enable TIM4->CCMR1 &= ~TIM_CCMR1_CC2S; // Output mode TIM4->CCER &= ~TIM_CCER_CC2NP; // This bit is used in conjunction with CC2P. TIM4->CCER |= TIM_CCER_CC2P; // Inverted/falling edge TIM4->SMCR |= TIM_SMCR_TS_1 | TIM_SMCR_TS_2; // Choosing TI2FP2 TIM4->SMCR |= TIM_SMCR_SMS_2; // Reset mode TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable TIM4->CR1 |= TIM_CR1_CEN; // TIM4 enable NVIC_EnableIRQ(TIM4_IRQn); // TIM4 global Interrupt enable > void TIM4_IRQHandler(void) < if (StatusDiode == 0) < TIM4->SR &= ~TIM_SR_TIF; GPIOB->ODR |= GPIO_ODR_ODR_15; // Led red on TIM4->DIER &= ~TIM_DIER_TIE; // Trigger interrupt disable TIM4->DIER |= TIM_DIER_CC2IE; // Capture/Compare 2 interrupt enable TIM4->CNT = 0; StatusDiode = 1; > else < TIM4->SR &= ~TIM_SR_CC2IF; GPIOB->ODR &= ~GPIO_ODR_ODR_15; // Led red off TIM4->DIER &= ~TIM_DIER_CC2IE; // Capture/Compare 2 interrupt disable TIM4->DIER |= TIM_DIER_TIE; // Trigger interrupt enable StatusDiode = 0; > > 

Заключение

Таким образом, разработали датчик движения, основанный на работе пересечения каким-либо объектом ИК луча. Система состоит из двух устройств, имеет минимум элементов, проста в реализации, имеет низкую стоимость и высокое быстродействие. При этом ядро МК свободно и может использоваться для других нужд.

Как своими руками сделать WiFi камеру слежения (ESP32-CAM)

К старту курса по разработке на С++ рассказываем, как самостоятельно собрать IP-камеру с обнаружением движения. За подробностями приглашаем под кат, где вы найдёте много фотографий и видео на Youtube-канале автора, за которым наблюдают более 30 000 человек.

Хотя не все хорошие WiFi камеры наблюдения дороги, большинство из них стоят немало, особенно если брать для дома сразу несколько. Сегодня мы за небольшие деньги (около 20 долларов, цена зависит от того, что у вас уже есть) сделаем беспроводную камеру с модулем ESP32-CAM AI thinker WiFi (одной из лучших макетных плат для камер), чтобы наблюдать за происходящим в доме или снаружи.

Введя уникальный IP-адрес в браузере, с этой камеры можно войти на веб-сервер и просматривать видео, а также менять настройки на боковых панелях управления. Благодаря коду, когда что-то или кто-то движется перед камерой, начинается запись, а записанные видеофайлы .MJPEG сохраняются на SD-карту. В камере слежения есть ещё много функций, но о них позже. А сейчас приступим к её сборке. Вот ссылка на видео проекта на YouTube.

Что нам потребуется

  • модуль ESP32-CAM с датчиком камеры OV2640 на 2 Мпикс;
  • конвертер с USB-порта FTDI на последовательный (для программирования) + соединительные провода между гнёздами;
  • карта microSD на 4 Гб (карта памяти TF);
  • антенна с фиксатором;
  • литий-ионный зарядный модуль TP4056 на 1 ячейку;
  • батарея 18650 3,7 В 2600 мАч (2 шт.);
  • ползунковый мини-переключатель SPDT (лучше тумблер 3 A);
  • провода диаметром 0,51 мм;
  • красный светодиод 3 мм;
  • резистор на 220 Ом;
  • цилиндрический пластиковый контейнер (выбор корпуса камеры — за вами);
  • крепление камеры к стене для GoPro.

1. Программирование ESP32-CAM

Загружаем код ESP32-CAM_MJPEG2SD в ESP32-CAM (спасибо пользователю s60sc на GitHub: он выложил последнюю версию кода). Всю информацию о коде смотрите по ссылке.

Чтобы запрограммировать модуль камеры, соединяем его с конвертером FTDI, работающим с USB и последовательным портом, как показано на схеме выше. Здесь подключаем пин GPIO 0 к GND, что позволяет программировать ESP. Нажимаем кнопку сброса на задней части платы модуля камеры, чтобы включить режим флеш-памяти перед загрузкой.

2. ESP32.json

Прежде чем переходить к коду, добавим во вкладку Preferences («Предпочтения») в Arduino IDE ссылку ESP32 .json, дающую доступ к примерам кода, библиотекам и так далее:

3. Заполнение параметров в коде

Открываем загруженный код камеры слежения ESP32-CAM_MJPEG2SD:

Раскомментируем строку CAMERA_MODEL_AI_THINKER, если у вас эта плата:

Вводим необходимые параметры, такие как модель камеры, а также учётные данные WiFi:

Дополнительно вводим данные FTP, чтобы получать записанные видео удалённо:

4. Загрузка кода на плату

Выбираем плату, скорость загрузки, частоту и режим флеш-памяти, схему разделов, основной уровень отладки и COM-порт:

Нажимаем Upload («Загрузить»). Загрузка на плату небыстрая: чуть подождём:

5. Подготовка ESP32-CAM и получение IP-адреса

Обязательно отсоединяем провод от IO0 к GND:

И нажимаем кнопку сброса:

Вставляем в слот модуля карту MicroSD. Минимум 4 Гб:

И получаем уникальный IP-адрес с монитора порта. Нужная кнопка в правом верхнем углу Arduino IDE.

6. Веб-сервер ESP32-CAM

После ввода IP-адреса в веб-браузер при включённой камере появится такая страница:

Нажав кнопку Start Stream («Начать трансляцию»), начинаем просмотр видеопотока:

Последняя версия кода даёт возможность начинать и останавливать запись вручную. Ранее запись запускалась лишь при обнаружении движения.

7. Сборка камеры

Для корпуса выбираем контейнер или материал, с которым легко работать. С вставкой железа в сплющенную трубу из ПВХ (показана ниже) возникли проблемы, поэтому используем цилиндрический пластиковый контейнер. Подробнее об этом читайте далее.

На картинке не совсем те детали, что использовались.

Для сборки понадобится

  • ESP32-CAM;
  • плата для заряда батарей TP4056 1S;
  • Li-Ion батарея 18650 3,7 В;
  • ползунковый мини-переключатель SPDP или тумблер 3 A;
  • красный светодиод 3 мм;
  • резистор мощностью 1/4 Вт 220 Ом;
  • антенна;
  • провод диаметром 0,51 мм;
  • крепёжный винт GoPro.

8. Подключение платы для внешней антенны

Выпаиваем резистор 0 Ом, соединяющий ESP с его антенной на плате:

И припаиваем его, подключая ESP к порту внешней антенны:

Этот этап нужен, чтобы увеличить диапазон для подключения собственной антенны.

9. Подключение источника питания ESP32-CAM

Подключаем к батарее зарядную плату TP4056 4,2 В (соединения B+ и B– от платы к батарее показаны выше):

К клеммам батареи подключаем входы платы рядом с портом Micro USB:

10. Работа с соединениями компонентов

Выпаиваем штыревые разъёмы ESP32-CAM с обеих сторон и удлиняем их, припаивая обратно с проводами.

Добавляем индикатор питания (красный светодиод):

Чтобы не запутаться, подбираем цвета проводов по их назначению:

11. Схема соединений

По этой простой схеме подключений должна получиться домашняя камера слежения со всем её железом.

12. Выбор батарей и корпуса

Сначала был плоский Li-Ion аккумулятор, я заменил его на батареи, более компактные для нового, цилиндрического корпуса:

Чтобы камера работала хорошо, лучше использовать батарею ёмкостью более 2000 мА·ч:

В итоге параллельно использовали 2 батареи 18650 по 3,7 В и 2600 мА·ч, что дало в сумме 5200 мА·ч. Приличная ёмкость.

13. Подготовка железа к установке в корпус

Отмечаем и сверлим отверстия для выступающих из корпуса частей:

Выбираем корпус для камеры, состоящий из двух частей: с таким легко работать. Лучше распечатать его на 3D-принтере.

14. Установка в корпус

Клеим двусторонний скотч или ленту на батареи и модуль ESP32-CAM (сверху и снизу):

Вставляем их в корпус:

Места с выступающими компонентами герметизируем термоклеем:

15. Защита от воды

Крепим детали к корпусу термоклеем, если нужно:

Чтобы вода не попала внутрь, место стыка половинок заклеиваем изолентой:

Нарезаем кусочки резины и вставляем в любые зазоры/отверстия, например порт Micro USB сзади и слот SD-карты спереди вверху:

16. Тестирование камеры

Вставляем карту MicroSD в слот камеры, а кусочек резины обратно, включаем камеру переключателем сзади, и находим веб-сервер IP-камеры (см. этапы 5 и 6):

Процедура запуска камеры и поиска её веб-сервера та же, но без нажатия кнопки сброса, ведь снова программировать камеру не нужно:

В меню веб-сервера камеры нажимаем кнопку Start Stream («Начать трансляцию») и получаем видеопоток в реальном времени:

17. Панель видеопотока

На этой панели есть вся подробная информация о ходе записи, освещённости (в ночное время), свободном месте на карте памяти, а также о дате и о температуре камеры. Здесь даже кнопкой переключается светодиод на плате ESP, отображается движение, обнаруженное ИИ, меняется чувствительность определённых функций и т. д.:

Чтобы менять разрешение записи (не только просмотра), открываем вкладку разрешения и выбираем более низкое или даже более высокое (наибольшее — 1600 × 1200). Во вкладке Get Folder («Получить папку») просматриваем записанные видео, нажимая кнопку Start Stream:

18. Крепление к стене

Можно взять держатель или кронштейн для крепления камеры к стене или любой другой поверхности. Здесь используется комплект креплений для экшн-камеры:

19. Включение камеры через USB

Подключаем источник питания на 5 В к зарядному модулю Micro USB (с кабелем от зарядника телефона) в задней части камеры:

Прикреплённая к стене камера должна работать постоянно:

Так идёт подзарядка батарей и непрерывное питание ESP32-CAM.

Батарея пригодится, если нужно снимать там, где нет розетки. Но на всю ночь её не хватит.

20. Очистка

Заполненную карту microSD извлекаем, подключаем к компьютеру и просматриваем файлы .MJPEG в проигрывателе:

21. Запись

В левой части экрана телефона отображается состояние Recording («Запись»):

Когда в кадре есть движение, камера записывает, когда его нет — прекращает запись.

22. Заключение

Теперь у вас есть собственная классная WiFi камера слежения:

Она сделает ваш дом ещё безопаснее:

В репозитории на GitHub есть код с расширениями, дополнительной информацией, характеристиками и возможностями ESP32-CAM MJPEG2SD.

Видео

Продолжить погружение в IT вы сможете на наших курсах:

  • Профессия C++ разработчик
  • Профессия Этичный хакер

Другие профессии и курсы

Data Science и Machine Learning

  • Профессия Data Scientist
  • Профессия Data Analyst
  • Курс «Математика для Data Science»
  • Курс «Математика и Machine Learning для Data Science»
  • Курс по Data Engineering
  • Курс «Machine Learning и Deep Learning»
  • Курс по Machine Learning

Python, веб-разработка

  • Профессия Fullstack-разработчик на Python
  • Курс «Python для веб-разработки»
  • Профессия Frontend-разработчик
  • Профессия Веб-разработчик

Мобильная разработка

  • Профессия iOS-разработчик
  • Профессия Android-разработчик

Java и C#

  • Профессия Java-разработчик
  • Профессия QA-инженер на JAVA
  • Профессия C#-разработчик
  • Профессия Разработчик игр на Unity

От основ — в глубину

  • Курс «Алгоритмы и структуры данных»
  • Профессия C++ разработчик
  • Профессия Этичный хакер

А также

Как сделать датчик движения на камеру

ESP32-CAM датчик движения HC-SR501 Телеграм

В этом примере я покажу как совместить датчик движения HC-SR501 с камерой на ESP32-CAM, делать фотографии при обнаружении движения и отправлять их в Телеграм.
Так как видео про камеру на ESP32 набирают на моём канале больше всего просмотров и комментариев, я продолжу эту тему. И у меня есть ещё как минимум 5-6 нестандартных примеров использования ESP32-CAM. И пока просмотры не иссякнут я буду делать про неё видео.

Приветствую всех моих подписчиков и гостей канала.
В этом видео я покажу как можно сделать фотоловушку. И не важно на кого вы охотитесь, на невинных птичек и животных или собрали охранную систему для того чтобы знать, что было, пока вас не было. А поможет нам в этом ESP32-CAM – это модуль на основе платы ESP32 с камерой OV2640 и датчик движения HC-SR501.
Кстати в одном из следующих видео я покажу как сделать Face Detect, то есть камера найдёт лицо в кадре и если оно есть в базе, то определит кому оно принадлежит.

Это продолжение вот этих видео, и поэтому если вам что-то не понятно или вы не знаете как установить модуль с камерой, то посмотрите эти видео там вы найдёте ответы на все вопросы.

А мы продолжим.
В этом примере я покажу как совместить датчик движения с камерой и делать фотографии при обнаружении движения. Фотографии не будут сохраняться на SD карте, как это было в прошлых примерах, а сразу будет отправляться в чат бот в телеграм. Вот для этого я и сделал 2 видео как создать канал и бот в Телеграм. Жалко что его так мало посмотрели. Ну всё равно, если вам что-то не понятно то посмотрите их. Там рассказано как получить Токен и ID канала. Они нам сегодня понадобятся.

Принцип работы программы такой. Модуль ждёт сигнала от датчика движения. Вначале при подаче питания возможно он сработает несколько раз. Это обусловлено тем, что датчик движения настраивается и это может занять время до 1 минуты. Если вам, что не понятно или вы не знаете как работает датчик движения, то обязательно посмотрите это видео, там рассказано про различные виды подключения датчика. Как с Ардуиной так и без неё. Датчик может работать самостоятельно. Как только датчик движения обнаруживает что что-то зашевелилось, то он подаёт сигнал плате ESP32. Этим сигналом будет 3.3 вольта с выхода датчика которые поступят на 13 вход ESP.

В предыдущем видео я ошибочно сказал, что вы можете отключить работу светодиода. Это возможно только при работе программы без использования SD карты. Светодиод на плате установлен на GPIO4 и для работы SD также нужен этот вывод. Включается он не для того чтобы работать как подсветка, а он показывает что идёт запись на карту. Так что если хотите сделать систему не видимой, не используйте SD карту, а отправляйте фото на сервер, почту или как сейчас в телеграм, или просто выпаяйте светодиод.

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

Схема соединения очень простая. Нам всего лишь надо подать 5 вольт питания на датчик движения и на плату ESP. Именно 5 вольт, не больше и не меньше. Хоть сама плата питается от 3,3 вольт, но было замечено, и не только мной, что при питании 3,3 вольта плата работает не стабильно. Я много читал об этом на форумах, так что если не хотите проблем, то лучше подавать именно 5 вольт.

Ну и на сладкое я оставил разбор скетча. Хотя до сих пор не понимаю зачем это делаю, всё равно это никто не смотрит.
В первых строчках как всегда подключаем библиотеки. Возможно у вас не будет установлена библиотека WiFIClientSecure тогда вам придётся её установить.
Затем идут настройки подключения к WIFI Надо указать название сети и пароль.
Теперь замените мой токен своим и Id канала тоже установите свой. Как их найти я рассказывал раньше.
Выход датчика движения подключаем к GPIO 13.

Теперь немного поговорим про камеру. У меня камера OV2640, и подключена к модулю AI-THINKER. Распиновка контактов вот такая.
У вас же может быть другая. В примере с библиотекой ESP32 есть пример Camera WebServer и в нём прописаны самые распространённые типы моделей, вам всего лишь надо будет раскомментировать свою. Контакты подключения прописаны в файле camera_pins.h Который так же как библиотеки подключается в скетче. Видите, здесь перечислены все модели что в главном файле и для каждой прописаны свои контакты. Если у вас что-то не так, то вы можете поправить значения здесь.

Функция setup у нас сегодня большая, здесь будет много строк кода.
ESP будет работать как станция, то есть мы не будем ничего выводить на станицу, иначе мы бы использовали сервер.

Соединяемся с WIFI сетью. Используя цикл WHILE мы будем ждать пока не соединимся с сетью, или пока не пройдёт 10 секунд, и по команде break не выйдем из цикла. Если всё прошло удачно, то вы увидите IP адрес который вам присвоили.

Если вы вылетели по break, то ESP перезагрузится и снова начнёт подключаться к сети. Если всё прошло хорошо, светодиод мигнёт 5 раз и программа продолжит работу дальше.
Конфигурацию и инициализацию камеры мы делали уже много раз ,поэтому пропускаем, если что не понятно, смотрите 2 предыдущих видео, или я думаю всё будет понятно и по комментариям в коде.

Цикл loop у нас небольшой. Если обнаружено движение, мы вызываем функцию отправки фото в телеграм и передаём ей два значения, это токен и id канала. И останавливаем работы скетча на 10 секунд, что бы не было бесконечных отправок фотографий.

Эту функцию я построчно объяснять не буду. Главное просто понять, что она делает. В ней происходят разные проверки, например на работу камеры. Но главное в ней это проверить есть ли подключение и если есть, то сформировать текст сообщения по правилам API телеграм.

И наконец мы добрались до функции отправки сообщения в Телеграм. Из предыдущей функции мы получили все необходимые данные для отправки сообщения. Проверяем подключение к серверу API телеграм и по протокол https используя порт 443 передаём нашу фотографию используя метод пост. Ждём 10 секунд чтобы сообщение было доставлено и разрываем соединение. Снова переходим в loop и ждём когда будет новое движение. Надеюсь, что понятно объяснил.

На этом думаю, что можно закончить это видео. А как скоро выйдет новое – это всё зависит от вас.

Видеонаблюдение на даче, которому не нужно электричество, а устанавливается оно за 10 минут

Дачу тесть купил где-то в 1995. Не прошло и года, как к нам забрались воры. Красть было особо нечего — они расстроились и взломали дом соседа. Помню, как дознаватель ходил по его участку и собирал окурки как улики. Думаю, он им обрадовался, поскольку тогда мало кто курил сигареты Sovereign. Мой тесть сильно расстроил дознавателя, когда сообщил, что негодяи как раз у него похитили блок таких сигарет. Воров, конечно, не нашли, но было подозрение, что участковый отлично знал, кто из местных «бомбит» дачи… Пришли сытые 2000-е, народ зажил чуть лучше, набеги на садоводства вроде как прекратились. Но вопрос охраны и через 25 лет остается более чем актуальным. Поставить на даче полноценную систему охраны — лучший, но не всем доступный по затратам вариант. У моего друга очень приличная дачка в СНТ — он ограничился муляжом сигнализации.

Тем не менее когда начинается дачный сезон, появляется спонтанное желание поставить систему видеонаблюдения. Но это дорогая затея, и надо обладать минимумом знаний, чтобы грамотно развести ветку на несколько камер и организовать удаленный доступ. Я часто читаю на форумах разговоры из серии «поссорился с соседом, поставил камеру и засудил его за то, что мой урожай крал». И постоянно думаю: какую же систему можно легко и быстро использовать для видеонаблюдения?

Вы думали об установке видеонаблюдения на даче?

Вы думали об установке видеонаблюдения на даче?

Главная закавыка — питание этой системы. Как правило, оно идет от сети, а на среднестатистической даче нередко отключают электричество, то есть надо делать резервное питание. Ставить, например, бесперебойники, но и это не спасет… Но недавно на рынке охранных сигнализаций появились автономные видеокамеры, которые передают картинку на смартфон. Они позволяют в любой момент глянуть, что происходит на объекте. На мой взгляд, это самое доступное решение для организации удаленного видеонаблюдения. Я решил рассказать об эксплуатации такого прибора со слов реального пользователя.

Автономная поворотная видеокамера с удаленным доступом со смартфона и датчиком движения. Фото с канала Alie GID

Автономная поворотная видеокамера с удаленным доступом со смартфона и датчиком движения. Фото с канала Alie GID

Поворотная автономная видеокамера Gadian 4G

Эта камера подключается к сети Интернет через сотового оператора. Для работы ей нужна сим-карта. Камера комплектуется солнечной батареей с контроллером заряда аккумуляторов. Аккумуляторами прибор не комплектуется — надо докупать 6 аккумуляторов типа 18650. При тестировании зимой камера заряжалась днем при –15°С и нормально держала заряд ночью.

Cбоку, под солнечной батареей, есть разъем micro-USB для быстрой зарядки аккумуляторов. С противоположной стороны находится кнопка включения камеры, она защищена резиновой заглушкой.

Кнопка включения солнечной батареи и гнездо быстрой зарядки находятся под резиновыми заглушками. Фото с канала Alie GID

Кнопка включения солнечной батареи и гнездо быстрой зарядки находятся под резиновыми заглушками. Фото с канала Alie GID

Кнопка включает панель, и аккумуляторы заряжаются. У камеры две антенны, одна подключена к Wi-Fi-модулю, другая — 4G. Камера может раздавать Интернет по Wi-Fi и работать как роутер. Вопрос, можно ли к ней подключить еще одну Wi-Fi-камеру, остается открытым. Теоретически такая возможность есть.

На самой камере — герметичная крышка. Откручиваем винт, снимаем крышку. Под ней находятся два слота — один для сим-карты, второй для карты памяти microSD.

Чтобы вставить СИМ-карту и карту памяти, надо снять крышку, которая находится с задней стороны. Фото с канала Alie GID

Чтобы вставить сим-карту и карту памяти, надо снять крышку, которая находится с задней стороны. Фото с канала Alie GID

Камера поддерживает карту памяти до 128 ГБ, этого хватит для записи целого архива видео. Запись видеокамера ведет циклично, при переполнении памяти новое видео записывается на самое старое. При подключении питания — не тестирует себя и не «разговаривает», как другие, это не дает возможности ее обнаружить. В описании камеры есть QR-коды для скачивания приложения UBox для смартфона. Приложение — на русском языке и позволяет легко разобраться в настройках.

Камера для теста установлена на одиноком старом сарае в поле. Электричества нет. Связь плохая, а картинка, которую передает камера, хорошая. Фото с канала Alie GID

Камера для теста установлена на одиноком старом сарае в поле. Электричества нет. Связь плохая, а картинка, которую передает камера, хорошая. Фото с канала Alie GID

Кронштейн, на котором висит камера, крепится к доске двумя саморезами.

Камера передает картинку (видео) на смартфон. Фото с канала Alie GID

Камера передает картинку (видео) на смартфон. Фото с каналаAlie GID

Матрица 2-мегапиксельная, камера снимает в формат Full HD — 1920×1080 пикселей. Объектив дает угол обзора около 80°. Камера оснащена светосенсором, который переключает ее в ночной режим. Для ночной съемки у нее есть два мощных ИК-диода.

Картинка днем, картинка ночью. Фото с канала Alie GID

Картинка днем, картинка ночью. Фото с канала Alie GID

Диоды обеспечивают подсветку на расстоянии до 20 метров. У камеры есть еще 4 мощных фонаря, благодаря которым она может снимать видео в цвете ночью. Если включать светодиодную подсветку при срабатывании датчика движения, это теоретически может спугнуть злоумышленников.

На фронтальной стороне камеры размещен микрофонm, датчик освещенности, четыре ярких светодиода, два ИК-диода и датчик движения. Фото с канала Alie GID

На фронтальной стороне камеры размещены микрофон, датчик освещенности, четыре ярких светодиода, два ИК-диода и датчик движения. Фото с канала Alie GID

Принцип работы

Камеру можно установить где угодно: она энергонезависима. Для экономии заряда аккумуляторов находится в спящем режиме. При срабатывании датчика движения камера «просыпается» и начинает снимать, одновременно присылая вам оповещение на смартфон. Главное — чтобы была сотовая связь.

Датчик срабатывает, если обнаруживает движение на расстоянии до 20 метров. При получении сигнала переходим в приложение и на смартфоне видим, что происходит в зоне видимости прибора. Запись может вестись в облачное хранилище или на внутреннюю SD Card, причем просматривать файлы с нее можно удаленно. Кроме видео, прибор записывает и звук: у него есть очень чувствительный микрофон. А сзади встроен достаточно мощный динамик, так что у вас есть шанс пообщаться со случайными гостями.

Есть опция поворота камеры — вы со смартфона можете повернуть камеру нажатием на виртуальный джойстик и осмотреться. Прибор поворачивается на 350° по горизонтали и на 90° по вертикали, обеспечивая практически круговой обзор.

Нажимая на виртуальный джойстик на смартфоне вы поворачиваете камеру. Фото с канала Alie GID


Нажимая на виртуальный джойстик на смартфоне, вы поворачиваете камеру. Фото с канала Alie GID

Программа позволяет настроить работу камеры для ваших задач, установить чувствительность датчика движения, установить время съемки после срабатывания датчика — функций много. И описание — на русском языке.

Настроек в приложении к камере много, меню на русском языке. Разобраться несложно. Фото с канала Alie GID

Настроек в приложении к камере много, меню — на русском языке. Разобраться несложно. Фото с канала Alie GID

Доступ к камере можно разрешить шести пользователям. Настройки интуитивно понятны, при желании включаете запись прямо в свой смартфон. Full HD уже не самое лучшее разрешение, которое может дать охранная камера. Но оно позволит вам оценить ситуацию на объекте.

Как сделать датчик движения для камеры

Специальные электронные приборы, реагирующие на перемещение в зоне действия их чувствительного элемента, пользуются все большей популярностью у рядового потребителя. С их помощью удается не только защищать важные объекты от проникновения посторонних лиц, но и управлять работой подключенного к ним оборудования (осветителей, в частности). Прежде чем изготовить датчик движения своими руками, потребуется ознакомиться с существующими разновидностями этих приборов, а также со схемами их включения.

Виды датчиков

Датчики движения различными способами определяют появление объекта на контролируемой территории

В соответствии с используемым принципом формирования контрольного сигнала все датчики движения делятся на следующие типы:

  • Ультразвуковые чувствительные элементы (УЗ).
  • Радиочастотные приборы (РЧ).
  • Инфракрасные устройства (ИК).
  • Лазерные датчики.

В каждом из этих приборов используется свой вид излучения, регистрируемый чувствительным элементом. Первая разновидность реагирует на УЗ сигнал, отраженный от движущегося объекта, а вторая работает по тому же принципу, но уже в радиочастотном спектре.

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

Лазерные датчики реагируют на отраженный сигнал в диапазоне волн, соответствующих частоте накачки.

По своему назначению все эти изделия делятся на следующие виды:

  • охранные;
  • включатели освещения;
  • коммутаторы бытовых приборов.

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

При выборе схемы самодельного чувствительного прибора обычно исходят из простоты ее реализации.

Самодельные датчики движения

Схема датчика движения для включения света

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

  • световой датчик;
  • емкостный датчик;
  • тепловой прибор, собранный на основе комплекта «Arduino»

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

Датчик, собранный на основе конструктора «Arduino», срабатывает при изменении картины теплового излучения.

Самостоятельное изготовление

Самостоятельное изготовление светового чувствительного прибора начинается с подготовки необходимого инструмента и материала. Для его сборки потребуются:

  • электрический паяльник;
  • измерительный прибор — мультиметр;
  • бокорезы и пинцет;
  • транзисторный фотоэлемент;
  • операционный усилитель (ОУ);
  • набор деталей: конденсатор, резисторы и реле РЭС55;
  • готовый блок питания, обеспечивающий подачу напряжения в схему.

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

Фотоэлемент можно изготовить самостоятельно, взяв за основу любой старый транзистор (П416, например). Для этого нужно взять бокорезы, а затем с их помощью «выкусить» крышку транзистора, оставив площадку с тремя ножками. Под воздействием света кристаллическая основа вскрытого триода будет работать как фотоэлемент, имеющий чуть меньшую чувствительность.

Порядок сборки

Берется старый, но работающий блок питания от 4,5 до 12-ти Вольт, от него отрезается питающий разъем. Отвод оформляется в виде двух проводников (плюса и минуса), которые удобно впаивать в схему. Определиться с полярностью электропитания можно с помощью мультиметра.

Все последующие операции выглядят так:

  1. Из подготовленных деталей собирается несложная схема приемника светового луча от лазерной подсветки.
  2. Сама она подключается к блоку питания, для чего придется воспользоваться паяльником.
  3. Собранная часть с приемным элементом помещается в подходящую по размерам коробку; при этом шляпка светочувствительного элемента выводится наружу.

По завершении сборочных операций следует перейти к монтажу самодельного датчика и последующему его подключению.

Монтаж и подключение

Различные схемы подключения

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

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

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

Реле герконовое рэс-55А (5 вольт)

Для включения и срабатывания схемы используется реле типа РЭС 55A, на обмотку которого напряжение подается с исполнительной части. Порядок работы самодельного устройства:

  1. Под действием светового луча в нормальном (не включенном) состоянии через фоторезистор протекает ток, приводящий к его отрыванию.
  2. На подключенном к выходу конденсаторе накапливается заряд, создающий на его обкладках определенный потенциал (система находится в равновесии).
  3. При появлении преграды в виде человека приемник-фоторезистор закрывается, а накопленный на обкладках заряд стекает через подсоединенное параллельно сопротивление.
  4. Это приводит к снижению потенциала в контрольной точке ОУ практически до нуля, в результате чего низковольтное напряжение поступает на обмотку реле.

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

Изготовление и настройка микроволнового датчика

Принципиальная схема микроволнового датчика движения

Для изготовления микроволнового датчика потребуется опыт работы с генераторными устройствами высоких частот. За основу взята любительская схема транзисторного генератора на полевой структуре. Приемник выполнен по трансформаторной избирательной схеме с ключевым каскадом на транзисторе КТ315, нагруженным на детекторный диод.

  1. B отсутствие движущегося объекта амплитуды сигналов генератора и приемника примерно равны и взаимно компенсируются.
  2. По этой причине на входе ключа и детектора напряжение равно нулю и подключенное к выходу реле не срабатывает.
  3. При появлении в зоне чувствительности человека баланс сигналов нарушается и как следствие на выходе схемы появляется напряжение.
  4. Оно подается на обмотку реле, при срабатывании которого 220 Вольт через его контакты поступают на светильник.

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

Монтаж видеонаблюдения

Если запись осуществляется только по детектору движения и эти движения достаточно редки на всех камерах регистратора, то некоторые жесткие диски в период простоя «засыпают». При появлении движения диск начинает раскручиваться и только после этого начинается запись. Мы имеем два негативных момента — частое засыпание и раскручивание диска негативно влияют на надежность диска. В таких условиях диски живут полгода-год в зависимости от условий эксплуатации. Во время раскрутки диска запись не производится, соответственно кроме пункта 1 мы еще теряем запись на это время, обычно это 2-3 секунды.

Что такое детекция движения

Детекция наличия движения – функция, решающая задачу оперативного визуального обнаружения тревожных событий на охраняемом объекте. Без неё сотрудники службы безопасности вынуждены были бы неотрывно следить за множеством изображений с камер на множестве мониторов. Автоматическое же обнаружения движения позволяет исключить человеческий фактор из процесса обработки тревожных событий, тем самым повышая общую эффективность всей системы видеонаблюдения и безопасности.

Типы детекторов движения

Детекторы движения (по изображению) принято делить на т.н. программные и встроенные в IP-камеры. Под программной понимают функцию детектирования, присутствующую в ПО видеонаблюдения. Встроенной называют функцию детектирования движения, реализованную в «прошивке» IP-камеры. На самом деле и то, и другое – детекция программная, т.к. она происходит по некоему математическому алгоритму обработки изображения, и термин «встроенный» следует понимать как «с помощью ПО, работающего в самой камере».

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

Какая же разница между детекторами в камерах и детекторами в ПО? Разница заключается в следующем:

в камерах работа происходит с «сырым», необработанным, несжатым изображением. Детекторы в ПО имеют дело с дважды преобразованным (сжатие в камере –> декодирование в «софте») изображением;

детектору в ПО требуется минимум два кадра чтобы «увидеть» наличие движения. Детектору в камере вообще необязательно работать с кадрами – он может оценивать изменение освещенности непосредственно светочувствительных элементов матрицы;

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

Т.к. в силу специализации мы имеем дело прежде всего с детекцией в ПО видеонаблюдения, то дальше мы немного поговорим об особенностях программной детекции движения.

Особенности программной детекции движения

Ещё раз уточним, что речь идёт о функции детектирования движения в ПО видеонаблюдения, работающим на видеосервере. Теперь по порядку:

Детекция движения всегда производится на преобразованном изображении
Да, очевидно, что для работы с «картинкой» эту самую картинку надо получить, распаковав приходящий с камеры сжатый видеопоток. Т.к. при сжатии всегда происходит ухудшение качества изображения (пусть даже и незаметно для глаза), то и эффективность работы детектора должна быть ниже (по сравнению с детектором в камере). На практике, впрочем, разница редко заметна.

Детекция движения значительно нагружает платформу видеосервера
Прежде всего нагрузка ложится на центральный процессор видеосервера. В основе детекции движения по видеоизображению довольно сложный алгоритм со множеством операций. В дополнении к этому изображение обязательно нужно распаковать (в отличие, например, от процесса записи в архив, при котором распаковка не требуется).
Часто, с целью снижения нагрузки на платформу, в ПО видеонаблюдения для работы детектора используются не все приходящие от камеры кадры, а только опорные, т.н. I-кадры. Положительный эффект от этого действительно есть и сильная зависимость эффективности детекторов движения от параметров входящего видеопотока.

ПО оценивает изменения контрастности, но могут использоваться и другие методы
Утверждение, честно говоря, нельзя считать проверенным т.к. производители не спешат заявлять о подробностях, объявляя их коммерческой тайной. Остаётся надеяться, что кто-нибудь из разработчиков ПО приоткроет тайну и расскажет о своих «нестандартных» методах хотя бы в комментариях к этой статье.

ПО может использовать «камерный» детектор
Да, действительно, многие ПО видеонаблюдения, даже имея собственные функции детектирования, могут уметь работать напрямую с собственными детекторами движения камер. Считается, что при этом повышается точность и оперативность обнаружения детектора (почему – рассказано выше в разделе «Типы детекторов движения»). Возможно даже одновременно использовать и «камерный», и встроенный в ПО детектор. Вряд ли кому-то такое потребуется на практике, но сама по себе такая возможность интересна.

В разных ПО — разные алгоритмы работы детекторов
К сожалению, мало что известно о принципах работы программных детекторов, т.к. производители считают эти принципы коммерческой тайной. Но наши тесты показывают, что разные ПО по-разному нагружают платформу (при сходных требованиях к функции обнаружения движения) — и это косвенно говорит о разнице в алгоритмах.

Итак, мы рассмотрели теоретические моменты – и далее перейдём к моментам практическим и более интересным.

Проблематика детекторов движения

Детекторы движения работают неидеально. И это нередко становится неприятным открытием для начинающих специалистов охранного видеонаблюдения. Все недостатки, «подводные» камни» и нарекания на работу детекции движения можно поделить на две категории:

Детектор плохо обнаруживает движение — велика вероятность пропуска цели;

Детектор обнаруживает слишком много движения — большое количество ложных срабатываний.

Давайте разберём их по порядку.

Детектор плохо обнаруживает движение

Как мы уже сказали, в основе детекции лежит поиск изменений на изображении, поиск изменения контрастности на соседних пикселях. Очевидно, что чем больше два разных кадра отличаются друг от друга, тем вероятнее сработает детектор. Но и наоборот — если изменения незначительны, то реакции детектора не будет. Неужели возможно такое, что движение объекта на самом деле есть, а изменений на изображении нет? Да, возможно по следующим причинам:

Объект по цвету, освещенности и прочим свойствам не отличается от обстановки, в которой он движется. Белый медведь на снегу, человек в зеленой одежде на траве, чёрная кошка в тёмной комнате — против них программный детектор будет бессилен.

Объект движется медленно, очень медленно. Настолько, что изменения контрастности пикселов сопоставимы с цветовым и яркостным «шумом», вызванным колебаниями освещённости, тепловыми процессами в матрице камеры и т.п. Если детектор не реагирует на эти шумы – не среагирует и на объект. Поэтому не стоит использовать детекторы движения для обнаружения весеннего половодья или движения ледников в горах.

В этих условиях возникает риск пропуска цели. При известной настойчивости всё-таки есть шанс настроить оборудование на обнаружение движения в этих условиях — понизив пороговые значения критериев, по которым определяется факт наличия/отсутствия движения. Но при этом возрастёт риск столкнуться со следующей, рассмотренной ниже проблемой.

Детектор обнаруживает слишком много движения

Иногда говорят, что «реагирует на всё подряд» или «срабатывает постоянно». То есть нарушителей и злоумышленников в поле зрения нет – а уведомления о движении идут непрерывным потоком. Да, конечно, при наступлении тревожного события детектор отреагирует – но его реакция растворится среди множества прочих уведомлений и останется незамеченной. Почему такое может происходить? Причина в итоге всего одна:

  • В поле зрения камеры всегда происходит какие-то изменения. Шевелятся листья, переливаются бликами стекла, летают насекомые, ездят автомобили и т.д. и т.п. Такое может быть на любом наружном объекте, где присутствует деревья и кустарники. Или в помещении, когда камера видит фрагмент окна, а через окно – уличную суету.

Хорошо, если возможно убрать постоянно «шевелящийся» объект из поля зрения камеры или повернуть камеру так, чтобы колеблющаяся ветка, кусок окна или постоянно работающий рекламный экран вышли из поля зрения камеры. Если такой возможности нет — надо смотреть на возможность как-нибудь настроить параметры детектора. Далее об этом и поговорим.

Возможности настроек детекторов движения

Даже самые простые детекторы имеют возможность регулировать параметры их работы. Смысл этих регулировок: максимально снизить количество ненужных, «ложных» срабатываний. Разные производители ПО видеонаблюдения предлагают разные наборы параметров, доступные пользователю для настройки. Но все эти параметры в итоге можно поделить на следующие типы:

Расскажем о каждом параметре для настройки подробнее.

Настройки чувствительности

В большинстве ПО имеется возможность установки определенного значения степени изменения контрастности, фактическое превышение которого детектор будет считать движением. Конкретный смысл и механизм влияния этого параметра производители раскрывают крайне редко (ссылаясь на коммерческую тайну), предоставляя пользователю задавать чувствительность в процентах или условных единицах. При установке нулевого значения детектор практически ни на что не будет реагировать – при выборе 100-процентного значения детектор будет реагировать на малейшие, порой не различимые взглядом изменения «картинки». Подразумевается, что подходящее значения будет подбираться опытным путём.

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

Высокая чувствительность программного детектора движения. Детектор реагирует на все подряд.

Настройка размера

Здесь уже и проще, и понятнее. Пользователь задаёт размер области изображения (в пикселах или процентах от размера кадра) – и, если, количество пикселей, у которых изменилась контрастность меньше, чем заданное количество (как правило в %), то детектор проигнорирует это изменение. Таким образом можно исключить срабатывания на всякую «мелочь» вроде листвы, бликов, капель дождя, травы и т.п.

Настройки зоны

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

«зона детекции»
Зона, в которой программный детектор движения следит за наличием движения. Все, что происходит вне этой зоны не будет вызывать срабатывание детектора. Зоны детекции полезны прежде всего в случаях, когда по факту движения требуется подавать уведомление оператору, т.к. позволяет следить за каким-то конкретным объектом.

«зона исключения»/«маска детектора»
Зоны, или даже зоны, в которых детектор будет игнорировать движение, реагируя только на события вне заданной области. Зоны исключения чаще всего используются для настройки ведения записи по срабатываниям детектора, т.к. даёт возможность исключить запись архива по заведомо ненужным событиям.

Зона детекции движения в ПО видеонаблюдения.

Зона исключения детектирования движения в ПО видеонаблюдения.

Пример использования маски детектора:

Детекция производится по всему кадру.

В зоне исключения детекция движения не производится.

На картинке слева детекция работает по всему кадру, что вызывает ложные срабатывания. На картинке справа наложены зоны исключения, в которых детекция не производится — нет ложных срабатываний.

Настройки перемещения

Довольно редко встречаемая категория настроек. Здесь имеется в виду возможность указать скорость перемещения и/или направление движения объекта. В теории это должно позволять исключить срабатывание детектора на слишком медленные или слишком быстрые перемещения либо наоборот – заставить детектор реагировать на эти перемещения. Настройки направления должны в результате давать возможность реагировать (или наоборот – не реагировать) на перемещения объектов в указанных направления.

По факту такие возможности используются довольно редко, т.к. если на объекте реально требуется следить за перемещениями объектов, то используется на порядок более эффективная и «продвинутая» видеоналитика трекинга объектов.

Как мы уже сказали выше – разные производители ПО предлагают разные возможности настроек детекторов движения. Настало время посмотреть конкретно: что именно будет доступно при выборе того или иного ПО.

Возможности работы с детекторами в ПО разных производителей

Дальше мы посмотрим, что предлагают производители ПО в плане настроек детекторов движения в базовой поставке ПО (т.е. без учета возможностей дополнительных модулей аналитики). Т.к. все существующие на рынке программные продукты в пределах одной статьи рассмотреть невозможно, мы остановились на наиболее известных и распространённых продуктах.

Контраст, размер, зоны исключения.

Возможности настройки параметров детектора движения в ПО Axxon Next

Контраст, размер, скорость и направление движения, зоны детекции*, зоны исключения. Индивидуальная настройка зон

Возможности настройки параметров базового детектора движения в ПО Интеллект

Возможности настройки параметров зоны детектора движения в ПО Интеллект

Контраст, количество изменившихся в кадре пикселов, зоны исключения

Возможности настройки параметров детектора движения в ПО Milestone Xprotect

Размер, зоны исключения. Индивидуальная настройка зон.

Возможности настройки параметров детектора движения в ПО Macroscop

Размер, зоны детекции. Индивидуальная настройка зон.

Возможности настройки параметров детектора движения в ПО Trassir

* в ПО Интеллект понятие зоны отличается от общепринятого: зона – не выделяемый регион изображения, а набор условий для выполнения особых реакций, которые всегда работают со всей областью изображения (подробнее см. документацию к ПО Интеллект).

Как используются детекторы движения

Задача любого детектора движения – дать уведомления о возникновении движения в наблюдаемой зоне. Как и где использовать полученное уведомление – определяется возможностями конкретного ПО. В базовый набор возможностей обычно входит:

Фиксация уведомления в журнале событий;

Включение видеозаписи по срабатыванию детектора;

Вывод уведомления оператору на экран.

Не всегда, но очень часто присутствуют и другие возможности:

Отправка уведомления по e-mail;

Вывод камеры, с которой пришло уведомление, на тревожный монитор;

Включение видеозаписи с улучшенными параметрами изображения (скорость, разрешение и пр.), предустановленными именно для тревожных видеозаписей (пример — в нашем справочном пособии);

Замыкание тревожных выходов для управления внешними устройствами.

Однако применение детекторов этим не ограничивается. Существующая видеоаналитика в массе своей использует для работы именно детекторы движения. Детекторы оставленных, унесённых предметов, межкамерный трекинг, распознавание номеров, подсчёт количества объектов – всем этим аналитическим функциям в той или иной мере требуются сведения о факте перемещения объектов в кадре, которые предоставляют детекторы движения.

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

Внимательный читатель может спросит: если ПО может работать с «камерными» детекторами – не снизятся ли в этом случае требования к производительности платформы? Нет, не снизятся. Т.к. далеко не всегда и не все встроенные в камеры детекторы передают информацию об обнаруженном движении в том объёме, в котором она требуется для модулей видеоаналитики. Отсюда — необходимость использования встроенного в ПО детекторов и соответствующие требования к ЦП видеосервера.

Заключение

Обойтись без детекции движения в системе видеонаблюдения невозможно, их роль сложно переоценить. При этом детекторы нельзя просто поделить на два разных типа («камерный» или программный) – следует учитывать принципы работы детекторов в каждом конкретном ПО видеонаблюдения, дабы в итоге получить систему, оптимально подходящую для каждой конкретной задачи и конкретного объекта.

Именно поэтому в нашем автоматизированном сервисе расчёта не только учитываются особенности программных детекторов в разных ПО, но и присутствует опция выбора потока для детектирования и даже вариант использования встроенных детекторов IP-камер.

И, как обычно, наши советы и рекомендации:

Не хватает глубины архива при записи по детекции движения?
В первую очередь обратите внимание на работу и настройки детекторов движения. При настройке важно убедится в работе детектора во всем диапазоне работы камеры, и в первую очередь в сложных условиях — снег, дождь, сложное и недостаточное освещение. Наверняка после этого фактическая глубина архива вырастет, а количество «ложняков» значительно уменьшится. Но не увлекайтесь слишком — увеличится риск пропустить нужное событие.

Сомневаетесь в качестве интеграции камер? Требуется аналитика? В системе камеры разных марок и хочется удобно и единообразно настраивать детекцию?
Тогда очевиден выбор варианта с программным детектором движения.

Подобрали камеры и рассчитали видеосервер, но заказчик просит заменить ПО?
Обязательно рассчитайте видеосервер заново — разница в работе детекторов существенно влияет на требования к платформе.

Не хотите зависеть от параметров потока детекции движения?
Рассмотрите вариант использования «камерных» детекторов. Но не забудьте уточнить их поддержку в выбранном ПО.

Не знаете что всё-таки выбрать — программную детекцию или встроенную в IP-камеры?
Рассмотрите вариант использования части камер — встроенного детектора движения, а для другой части — программного. Программные продукты ведущих производителей позволяют это реализовать.

Хотите знать что предшествовало тревоге, и что было после?
Для этого существуют функции пред- и постзаписи. Первая означает наличие программного буфера, с помощью которого записанное «по движению» видео начинается не с момента регистрации движения, а за несколько секунд до него. Вторая позволяет закончить запись спустя несколько секунд уже после прекращения срабатывания детектора. В результате — при анализе архива — можно увидеть как само тревожное событие, так и ситуацию до и после него.

Как своими руками сделать WiFi камеру слежения (ESP32-CAM)

К старту курса по разработке на С++ рассказываем, как самостоятельно собрать IP-камеру с обнаружением движения. За подробностями приглашаем под кат, где вы найдёте много фотографий и видео на Youtube-канале автора, за которым наблюдают более 30 000 человек.

Хотя не все хорошие WiFi камеры наблюдения дороги, большинство из них стоят немало, особенно если брать для дома сразу несколько. Сегодня мы за небольшие деньги (около 20 долларов, цена зависит от того, что у вас уже есть) сделаем беспроводную камеру с модулем ESP32-CAM AI thinker WiFi (одной из лучших макетных плат для камер), чтобы наблюдать за происходящим в доме или снаружи.

Введя уникальный IP-адрес в браузере, с этой камеры можно войти на веб-сервер и просматривать видео, а также менять настройки на боковых панелях управления. Благодаря коду, когда что-то или кто-то движется перед камерой, начинается запись, а записанные видеофайлы .MJPEG сохраняются на SD-карту. В камере слежения есть ещё много функций, но о них позже. А сейчас приступим к её сборке. Вот ссылка на видео проекта на YouTube.

Что нам потребуется

модуль ESP32-CAM с датчиком камеры OV2640 на 2 Мпикс;

конвертер с USB-порта FTDI на последовательный (для программирования) + соединительные провода между гнёздами;

карта microSD на 4 Гб (карта памяти TF);

антенна с фиксатором;

литий-ионный зарядный модуль TP4056 на 1 ячейку;

батарея 18650 3,7 В 2600 мАч (2 шт.);

ползунковый мини-переключатель SPDT (лучше тумблер 3 A);

провода диаметром 0,51 мм;

красный светодиод 3 мм;

резистор на 220 Ом;

цилиндрический пластиковый контейнер (выбор корпуса камеры — за вами);

крепление камеры к стене для GoPro.

1. Программирование ESP32-CAM

Загружаем код ESP32-CAM_MJPEG2SD в ESP32-CAM (спасибо пользователю s60sc на GitHub: он выложил последнюю версию кода). Всю информацию о коде смотрите по ссылке.

Чтобы запрограммировать модуль камеры, соединяем его с конвертером FTDI, работающим с USB и последовательным портом, как показано на схеме выше. Здесь подключаем пин GPIO 0 к GND, что позволяет программировать ESP. Нажимаем кнопку сброса на задней части платы модуля камеры, чтобы включить режим флеш-памяти перед загрузкой.

2. ESP32.json

Прежде чем переходить к коду, добавим во вкладку Preferences («Предпочтения») в Arduino IDE ссылку ESP32 .json, дающую доступ к примерам кода, библиотекам и так далее:

3. Заполнение параметров в коде

Открываем загруженный код камеры слежения ESP32-CAM_MJPEG2SD:

Раскомментируем строку CAMERA_MODEL_AI_THINKER, если у вас эта плата:

Вводим необходимые параметры, такие как модель камеры, а также учётные данные WiFi:

Дополнительно вводим данные FTP, чтобы получать записанные видео удалённо:

4. Загрузка кода на плату

Выбираем плату, скорость загрузки, частоту и режим флеш-памяти, схему разделов, основной уровень отладки и COM-порт:

Нажимаем Upload («Загрузить»). Загрузка на плату небыстрая: чуть подождём:

5. Подготовка ESP32-CAM и получение IP-адреса

Обязательно отсоединяем провод от IO0 к GND:

И нажимаем кнопку сброса:

Вставляем в слот модуля карту MicroSD. Минимум 4 Гб:

И получаем уникальный IP-адрес с монитора порта. Нужная кнопка в правом верхнем углу Arduino IDE.

6. Веб-сервер ESP32-CAM

После ввода IP-адреса в веб-браузер при включённой камере появится такая страница:

Нажав кнопку Start Stream («Начать трансляцию»), начинаем просмотр видеопотока:

Последняя версия кода даёт возможность начинать и останавливать запись вручную. Ранее запись запускалась лишь при обнаружении движения.

7. Сборка камеры

Для корпуса выбираем контейнер или материал, с которым легко работать. С вставкой железа в сплющенную трубу из ПВХ (показана ниже) возникли проблемы, поэтому используем цилиндрический пластиковый контейнер. Подробнее об этом читайте далее.

На картинке не совсем те детали, что использовались.

Для сборки понадобится

плата для заряда батарей TP4056 1S;

Li-Ion батарея 18650 3,7 В;

ползунковый мини-переключатель SPDP или тумблер 3 A;

красный светодиод 3 мм;

резистор мощностью 1/4 Вт 220 Ом;

провод диаметром 0,51 мм;

крепёжный винт GoPro.

8. Подключение платы для внешней антенны

Выпаиваем резистор 0 Ом, соединяющий ESP с его антенной на плате:

И припаиваем его, подключая ESP к порту внешней антенны:

Этот этап нужен, чтобы увеличить диапазон для подключения собственной антенны.

9. Подключение источника питания ESP32-CAM

Подключаем к батарее зарядную плату TP4056 4,2 В (соединения B+ и B– от платы к батарее показаны выше):

К клеммам батареи подключаем входы платы рядом с портом Micro USB:

10. Работа с соединениями компонентов

Выпаиваем штыревые разъёмы ESP32-CAM с обеих сторон и удлиняем их, припаивая обратно с проводами.

Добавляем индикатор питания (красный светодиод):

Чтобы не запутаться, подбираем цвета проводов по их назначению:

11. Схема соединений

По этой простой схеме подключений должна получиться домашняя камера слежения со всем её железом.

12. Выбор батарей и корпуса

Сначала был плоский Li-Ion аккумулятор, я заменил его на батареи, более компактные для нового, цилиндрического корпуса:

Чтобы камера работала хорошо, лучше использовать батарею ёмкостью более 2000 мА·ч:

В итоге параллельно использовали 2 батареи 18650 по 3,7 В и 2600 мА·ч, что дало в сумме 5200 мА·ч. Приличная ёмкость.

13. Подготовка железа к установке в корпус

Отмечаем и сверлим отверстия для выступающих из корпуса частей:

Выбираем корпус для камеры, состоящий из двух частей: с таким легко работать. Лучше распечатать его на 3D-принтере.

14. Установка в корпус

Клеим двусторонний скотч или ленту на батареи и модуль ESP32-CAM (сверху и снизу):

Вставляем их в корпус:

Места с выступающими компонентами герметизируем термоклеем:

15. Защита от воды

Крепим детали к корпусу термоклеем, если нужно:

Чтобы вода не попала внутрь, место стыка половинок заклеиваем изолентой:

Нарезаем кусочки резины и вставляем в любые зазоры/отверстия, например порт Micro USB сзади и слот SD-карты спереди вверху:

16. Тестирование камеры

Вставляем карту MicroSD в слот камеры, а кусочек резины обратно, включаем камеру переключателем сзади, и находим веб-сервер IP-камеры (см. этапы 5 и 6):

Процедура запуска камеры и поиска её веб-сервера та же, но без нажатия кнопки сброса, ведь снова программировать камеру не нужно:

В меню веб-сервера камеры нажимаем кнопку Start Stream («Начать трансляцию») и получаем видеопоток в реальном времени:

17. Панель видеопотока

На этой панели есть вся подробная информация о ходе записи, освещённости (в ночное время), свободном месте на карте памяти, а также о дате и о температуре камеры. Здесь даже кнопкой переключается светодиод на плате ESP, отображается движение, обнаруженное ИИ, меняется чувствительность определённых функций и т. д.:

Чтобы менять разрешение записи (не только просмотра), открываем вкладку разрешения и выбираем более низкое или даже более высокое (наибольшее — 1600 × 1200). Во вкладке Get Folder («Получить папку») просматриваем записанные видео, нажимая кнопку Start Stream:

18. Крепление к стене

Можно взять держатель или кронштейн для крепления камеры к стене или любой другой поверхности. Здесь используется комплект креплений для экшн-камеры:

19. Включение камеры через USB

Подключаем источник питания на 5 В к зарядному модулю Micro USB (с кабелем от зарядника телефона) в задней части камеры:

Прикреплённая к стене камера должна работать постоянно:

Так идёт подзарядка батарей и непрерывное питание ESP32-CAM.

Батарея пригодится, если нужно снимать там, где нет розетки. Но на всю ночь её не хватит.

20. Очистка

Заполненную карту microSD извлекаем, подключаем к компьютеру и просматриваем файлы .MJPEG в проигрывателе:

21. Запись

В левой части экрана телефона отображается состояние Recording («Запись»):

Когда в кадре есть движение, камера записывает, когда его нет — прекращает запись.

22. Заключение

Теперь у вас есть собственная классная WiFi камера слежения:

Она сделает ваш дом ещё безопаснее:

В репозитории на GitHub есть код с расширениями, дополнительной информацией, характеристиками и возможностями ESP32-CAM MJPEG2SD.

Видео

Похожие публикации:

  1. Какой фрезерный станок по металлу купить
  2. Млн квт час как правильно
  3. Как сделать пульт для телевизора своими руками
  4. Как устанавливать откатные ворота с автоматикой

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *