Представляю вниманию DIY сканер на базе Android смартфона.
При проектировании и создании сканера, в первую очередь, интересовало сканирование крупных объектов. Минимум – фигура человека в полный рост с точность – хотя бы 1-2 мм.
Данные критерии успешно достигнуты. Успешно сканируются объекты при естественном освещении (без прямого солнечного света). Поле сканирования определяется углом захвата камеры смартфона и расстоянием, на котором лазерный луч сохраняет достаточную для детектирования яркость (днем в помещении). Это фигура человека в полный рост (1.8 метров) с шириной захвата в 1.2 метров.
Сканер был сделан из соображений «а не сделать ли что ни будь более или менее полезное и интересное, когда заняться нечем». Все иллюстрации – на примере «тестового» объекта (выкладывать сканы людей не корректно).
Как показал опыт, для сканера такого типа ПО — это вторично и на него было потрачено меньше всего времени (на окончательный вариант. Не считая эксперименты и тупиковые варианты). Поэтому в статье особенностей ПО касаться не буду (Ссылка на исходные коды в конце статьи.)
Цель статьи – рассказать о тупиковых ветках и проблемах, собранных на пути к созданию окончательной рабочей версии.
Для сканера в окончательной версии используется:
- Телефон Samsung S5
- Красный и зеленый лазеры с линзой для линии (90 градусов линия) на 30 мВт со стеклянной оптикой (не самые дешевые).
- Шаговые двигатели 35BYGHM302-06LA 0.3A, 0.9°
- Драйверы шаговых двигателей A4988
- Bluetooth модуль HC-05
- Плата STM32F103C8t
Драйверы A4988, выставлены на half step, что с редуктором 15->120 дает 400*2*8 шагов на PI.
Выбор технологии сканирования.
Были рассмотрены следующие различные варианты.
LED Проектор.
Вариант был рассмотрен и просчитан. Даже дорогие проекторы не обладают нужным разрешением для достижения необходимой точности. А про дешевые даже говорить смысла нет.
Механическая развертка лазерного луча в сочетании с дифракционной решеткой.
Идея была проверена и сочтена годной. Но не для DIY исполнения, по причинам:
- Нужен достаточно мощный лазер, что бы после дифракции, метки были достаточно яркими (расстояние до объектива смартфона 1..2 метра). А глаза жалко. Лазер-точка уже с 30мВт не полезен.
- Требования к точности механической развертки в 2-х плоскостях – слишком высокие для DIY исполнения.
Стандартная механическая развертка лазер-линии на неподвижный объект сканирования.
В конечном итоге был выбран был выбран вариант с двумя лазерами разного цвета
- Разные цвета лазеров позволяют независимо детектировать их на одном кадре.
- Расположение лазеров по разные стороны камеры позволяет за один проход получить два скана.
- Два скана за раз позволяет объективно оценить качество юстировки сканера (сканы должны сойтись и наложиться друг на друга).
Как оказалось, последний критерий самый важный. Качество скана целиком определяется точностью измерения геометрических размеров и углов сканера. А наличие двух сканов от двух лазеров позволяет сразу оценить качество сканирования:
Облака точек сошлись. Т.е. плоскости захваченные двумя лазерами сошлись на всей поверхности.
Неудачный вариант механической части на 28BYJ-48.
Хотя с самого начала предполагал, что это тупиковый вариант, не обеспечивающий необходимой точности, я все равно его проверил c различными ухищрениями:
- Ось мотора зафиксирована подшипником.
- Добавлен элемент трения и стопор для выборки люфта редуктора.
- Попытка определения «точной позиции» фототранзистором, по засветке лазером
Повторяемость возврата на то же место линии лазера оказалась низка – 2-3 мм на дистанции 1.5 метра. При работе редуктора, несмотря на кажущуюся плавность, заметны рывки в 1-3 мм на расстоянии 1.5 метра.
Т.е. 28BYJ-48 полностью не подходит для более или менее точного сканера крупных объектов.
Требования к развертке, исходя из моего опыта
Обязательным элементом развертки должен быть редуктор.
Не стоит заблуждаться насчет режима 1/x шагов. Опыты показали, что в режиме 1/16 на A4988 микро шаги не равномерные. И на 1/8 эта неравномерность заметна на глаз.
Самым оптимальным решением для редуктора оказалось использование ременной зубчатой передачи. Хотя она получилась довольно громоздкой, но простой в создании и точной.
Точность позиционирования (точнее повторяемость позиционирования начальной положения лазеров для сканирования) лазеров оказалась около 0.5 mm для 5 мм ширины лазерной линии на 4 метра расстояния. Т.е. на расстоянии сканирования (1.2-1.8 метра) это вообще затруднительно измерить.
Позиционирование – оптроны (китайский noname) на прорези в диске под лазерами.
Проблемы с передачей управляющих сигналов с телефона на модуль управления лазерами и шаговыми двигателями.
Узким местом, с точки зрения скорости сканирования оказался управляющий канал. Поскольку это была DIY неторопливая разработка в собственное удовольствие, то были перепробованы все способы коммуникации со смартфоном.
Передача управляющих сигналов через Audio jack (phone Audio jack=> oscilloscope).
Самый тормозной способ для передачи данных в реальном времени. Да еще с плавающим временем. До 500 ms (!) от программной активации передачи аудио данных до фактического появления сигнала в Audio jack.
Эта экзотика была проверена, поскольку, по работе приходилось иметь дело с мобильными ридерами чиповых карт.
Фотодиоды на экране смартфона (кусочек экрана телефона=>фототранзисторы+ STM32F103).
Был ради интереса опробован даже такой экзотический способ, как фототранзисторы матрицей 2x2 в виде прищепки на экран.
Хотя этот способ выдачи информации с телефона оказался самым быстрым, но не настолько принципиально быстрее (10 ms vs 50ms) чем Bluetooth, что бы мирится с его недостатками (прищепка на экран).
IR канал (phone=>TSOP1736->STM32F103).
Практически проверен и способ передачи через IR канал. Даже некую реализацию протокола передачи данных пришлось сделать.
Но IR так же оказался не очень удобен (фотодатчик крепить на телефоне неудобно), и не слишком быстрее чем Bluetooth.
WiFi модуль (phone=>ESP8266-RS232->STM32F103).
Результаты проверки этого модуля оказались совершенно обескураживающими. Время выполнения запрос-ответ (эхо) оказалась непредсказуемо плавающим в диапазоне 20-300 ms (в среднем 150 ms). Почему и что – разбираться не стал. Наткнулся только на статью где рассказывалось о неудачной попытке использовать ESP8266 для обмена данными в режиме реального времени с жесткими требованиями по времени запроса/ответа.
Т.е. ESP8266 со «стандартной» прошивкой TCP -> RS232 не годится для подобных целей.
Выбранный вариант управляющего модуля и передачи сигналов
В конечном итоге, после всех экспериментов, был выбран Bluetooth (HC-05 модуль) канал. Дает стабильное (а это самое главное) время передачи данных запрос-ответ в 40ms.
Время довольно большое и сильно влияет на время сканирования (половина от всего времени).
Но лучшего варианта добиться не удалось.
В качестве управляющего модуля широко распространенная плата c SM32F103C8T.
Методы детектирования линии на кадре.
Самый простой способ выделить линии лазере на кадре – это использовать вычитание кадра с выключенным лазером и кадра с лазером.
В принципе, работает и поиск по кадру без вычитания. Но работает значительно хуже при дневном освещении. Хотя и этот режим был оставлен в ПО ради сравнительных тестов (фото режима ниже. Все остальные фотографии с режимом вычитания кадров).
Практическая ценность варианта без вычитания кадров оказалась низка.
Возможно и можно извлечь сигнал лазера из этой зашумленной информации. Однако возится не стал.
Вариант с вычитанием кадров работает хорошо.
Всякие эксперименты с попытками аппроксимации линии и обработкой всего кадра показали, что чем сложнее алгоритм, чем чаще он «ошибается» да еще и тормозит обработку «на лету». Самым быстрым (и простым) оказался алгоритм поиска лазера (лазерной точки) на горизонтальной линии:
- Для каждой точки линии считается сумма квадратов уровня цвета лазера (RGB) в окне, указанного в конфигурации (13 px – экспериментально оптимальная величина для окна)
- Точка лазера – середина окна с максимальным значением сумм уровней «цвета».
Время на обработку одного кадра поиском «зеленой» и «красной линии» — 3ms.
Облака точек для красного и зеленого лазера считаются отдельно. При правильной механической юстировке сводятся с точностью < 1 мм.
Точность и юстировка.
Точность оказалась в пределах 1 мм на расстоянии 1.2 метров. По большей части обусловлена разрешением камеры телефона (1920x1080) и шириной луча лазера.
Очень важным для получения корректных сканов провести настройку статическую и динамическую. Точность/не точность настройки хорошо заметна при загрузке обоих облаков точек в MeshLab. В идеале облака точке должны сойтись, дополняя друг друга.
Статически параметры, выставляются максимально точно один раз:
- Тангенс угла поля зрения камеры.
- Длинна «плеч» лазеров (от центра объектива до оси вращения).
Ну и конечно же максимальная фокусировка линз лазеров на заданное расстояние сканирования и «вертикальность» линий лазера.
Динамический параметр фактического угла позиции лазеров относительно виртуальной плоскости кадра приходится подстраивать каждый раз заново при смешении телефона в креплении. Для этого сделан режим настройки в ПО. Сведением в центр экрана лазеров и подстройкой величины угла необходимо выставить расчетное расстояние максимально близко к истинному (измеренному) расстоянию для обоих лазеров.
До подстройки:
После подстройки:
Выводы.
Такую конструкцию, пожалуй, может повторить любой. Я все детали вырезал из стеклотекстолита на ЧПУ.
Конечно без ЧПУ фрезера сделать шкив под лазер затруднительно. Но с учетом того что нужен угол поворота максимум в 90 градусов, то при должном терпении шкив можно выпилить и надфилем.
Но лучше все же делать на ЧПУ. Требования к осевому люфту поворотного узла высоки. Качество сканов на 100% определяется точностью изготовления и юстировки.
Сканер делал в фоновом режиме. Временами с перерывами по паре месяцев. Поэтому оценить суммарную трудоемкость его создания не могу.
Общая стоимость конструкции не слишком высока. Как показали мои эксперименты, хотя и до промышленных сканеров крупных объектов далеко, но вполне приличные сканы получить можно.
На качество сканов в первую очередь влияет точность механической части. В этом смысле в DIY бороться с механикой созданной для промышленных сканеров сложно.
Исходный код: github.com/mmMikeKn/ScanerAndroidPhone3D
Автор: mmMike