суббота, 5 ноября 2022 г.

Датчик цвета на ESP32-CAM

 Модуль ESP32-CAM (http://alii.pub/69872w) может быть не только обычной дистанционной камерой для просмотра области пространства на которую она направлена но и также выполнять некоторые манипуляции с визуальными данными которые этот модуль получает и также самостоятельно принимать некоторые решения на основе этих данных. Микроконтроллер ESP32 имеет достаточно неплохую производительность (по сравнению с другими микроконтроллерами рассматриваемыми ранее в данном блоге) что позволяет использовать его для обработки изображений и машинного зрения. Ранее, в данном блоге, появилась статья про датчик цвета на основе Raspberry pi 3 и USB камеры - https://electe.blogspot.com/2020/05/usb-raspberry-pi.html. Датчик цвета сделать получилось но работал от крайне медленно. На получение снимка, его обработку, сохранение, конвертирование и всё стальное в сумме уходило более одной секунды что было видно без специальных таймеров замера времени. Если к этой задержке прибавить время более сложной операции, нежели просто усреднение цветов пикселей, то скорость работы наверняка также не порадует. Более быстрой работы устройства можно добиться исключив ненужные действия из процесса. Добиться этого на Raspberry pi c USB камерой будет не просто т.к. придется работать с камерой на более низком программном уровне + добавляются ограничения по скорости передачи данных по USB. Эти проблемы можно было решить применением специальной камеры для Raspberry pi но на тот момент такие камеры стоили гораздо дороже чем USB камеры. Модуль же ESP32-CAM сам по себе не дорогой, имеет небольшие размеры и используя его и среду разработки Arduino IDE можно получить доступ к пикселям изображений делаемых камерой без больших сложностей. Конечно на данный модуль нельзя установить такую тяжёлую библиотеку как opencv но в большинстве случаев её функционал избыточен по тому что не всегда необходимо делать с изображениями все преобразования которые может данная библиотека. Чтобы модуль ESP32-CAM мог показать что он правильно поработал с пикселями и определил цвет, можно дополнить его например RGB светодиодом который будет показывать какой цвет обнаружил модуль. Конечно можно использовать имеющийся в модуле WIFI или bluetooth или даже uart (если совсем лень) но светодиод кажется нагляднее. При этом его не следует направлять в ту сторону куда смотрит камера, иначе модуль будет определять тот цвет который сам же и создает что приведет к положительной обратной связи всей системы и более трудному выводу её из устойчивого состояния. Схема может выглядеть например так:

Рисунок 1 - Схема датчика цвета на ESP32-CAM

Модуль может питаться автономно от пауэрэнка даже без отключения программатора - это может быть удобно т.к. для перепрограммироания нужно делать только одно пересоединение. Скетч не сильно сложный и может быть такой:
В начале, как всегда, подключаются заголовочные файлы. После нужно добавить константы которые копируются из файла с константами примера для камеры. Константы нужно скопировать из блока для используемого модуля, в данном случае для ai thinker. В функции setup() включается последовательный порт для отладки. Далее заполняется структура для настройки и инициализации камеры. После чего имеется необходимая для запуска устройства последовательность строк скопированная из скетча примера. Далее делается инициализация камеры функцией esp_camera_init и проверка этой инициализации. После совершаются настройки. Снижается разрешение кадра чтобы сделать его быстрее и увеличивается насыщенность цвета чтобы датчик лучше различал цвета. Далее пины к которым подключен светодиод настраиваются на выход. В начале основного цикла объявлен указатель на структуру типа camera_fb_t который заполняется функцией esp_camera_fb_get после взятия фотографии от камеры. Если оно прошло неудачно то в последовательный порт передается соответствующее сообщение. Далее обявляются некоторые специальные переменные суть которых отражена в их названиях. Функцией dl_matrix3du_alloc выделяется память для матрицы изображения. Если этого сделать не получилось то оригинальное изображение возвращается функцией esp_camera_fb_return и в последовательный порт передается сообщение о неудаче. Далее заполняются специальные переменные. После чего функцией fmt2rgb888 изображение из камеры преобразуется из формата jpeg в формат rgb888 т.е. в обычный набор пикселей в котором на каждую компоненту цвета выделено по 8 бит. После успешного конвертирования набор пикселей будет доступен через указатель out_buf из которого можно извлекать пиксели так же как из обычного массива (такие особенности языка си) через квадратные скобки. Несмотря на то что в аббревиатуре RGB буква R, обозначающая красный, стоит на первом месте. Извлекать компоненты цвета из out_buf следует в обратном порядке т.е. синяя компонента первого пикселя будет в out_buf[0], зеленая в out_buf[1], красная в out_buf[2], синяя компонента второго пикселя будет в out_buf[3] и т.д. Конец этого хранилища записан в переменной out_len которую можно использовать для завершения цикла перебора пикселей. Для каждой компоненты цвета находиться среднее арифметическое после чего, обычным сравнением, определяется какая компонента преобладает и в соответствии с ней загорается нужный свет RGB светодиода. В конце выделенная память освобождается функцией dl_matrix3du_free. Результат работы датчика можно посмотреть на видео: