Последнее время появилось довольно много обзоров тепловизионной приставки к смартфону Seek Thermal. Однако, Seek Thermal не единственный тепловизор доступный широким массам пользователей – всем известная компания FLIR также выпускает свою тепловизионную приставку FLIR One трёх разных поколений. В данной статье речь пойдёт о приставке второго поколения FLIR One Gen 2 для Android, имеющей разрешение болометрической матрицы 160x120 пикселей.
Купил я эту приставку на ebay три месяца назад с надеждой подключить к персональному компьютеру по USB и, надо сказать, моя надежда оправдалась.
Первое, что потребовалось сделать, так это собрать кабель с micro-USB (мама) на USB (папа). Тут проблем не возникнет.
Дальше — интереснее. На форуме eevblog.com tomas123 вскрыл протокол обмена по USB и написал для Linux своё консольное приложение для получения картинки с тепловизионной и обычной камер приставки с использованием libusb. Для Linux мне программа была не интересна, и я попробовал написать свою программу для Windows XP на базе программы tomas123. И вот тут-то и возникла проблема: libusb для Windows отказалась корректно работать, выдавая ошибку
libusb0-dll:err [submit_async] submitting request failed, win error: Параметр задан неверно.
Задав вопрос на форуме eevblog.com, я получил ответ, что я стал третьим, кто пытался безуспешно запустить эту программу для Windows с использованием libusb. Так же выяснилось, что и под Linux далеко не со всеми дистрибутивами FLIR One через libusb работает стабильно – в Ubuntu 10, например, часты ошибки “pipe error”, а в Mageia 5 таких проблем не возникает. Ну что ж, пришлось отложить программу для Windows на будущее.
Следующая ОС, для которой я попытался написать программу, была QNX 6.3. Эту ОС я использую на работе, но я никогда не писал драйвер USB для неё. С помощью форума qnx.org.ru мне всё же удалось написать нечто более-менее корректно работающее по USB с FLIR One. Вот на картинке интерфейс получившейся программы:
Программа для QNX 6.3.
Однако программа работает нестабильно – io-usb очень часто спустя пару-тройку минут погибает в неравном бою с тепловизором. Более того, на некоторых машинах система даже не замечает подключение устройства! Оказалось, что переключив в BIOS работу портов в USB 1, система всё же оживает и начинает обнаруживать устройство и работать с ним, пусть и с пониженным FPS. Я полагаю, что, возможно, FLIR One использует не совсем стандартный USB, и это и приводит к подобным проблемам. Но главное – программа работает и картинка строится.
Дальше настало время вернуться к Windows. С помощью вот этой темы я написал драйвер для Windows XP. Вылетев раз 20 в BSOD в процессе отладки, драйвер ожил, и я получил картинку с тепловизора в программе для Windows XP. Победа! Однако, всё опять-таки, не так радужно, как казалось сначала. На некоторых компьютерах (и даже с разных USB-разъёмов одного и того же компьютера) с Windows XP драйвера просто невозможно установить – система видит FLIR One как составное USB-устройство и совершенно не желает его разделить на три устройства с окончаниями на .iAP, .FileIO и .Frame. Такая же проблема обнаружилась и в Windows 7, что также не позволило мне установить драйвер для этой ОС. Как эту проблему обойти, мне до сих пор неизвестно.
Собственно, в настоящий момент, на этом разработка программ для FLIR One у меня и остановилась.
Программа для Windows XP.
Итак, что же представляет этот тепловизор с точки зрения обмена с ним по USB:
Идентификатор производителя: 0x09CB.
Идентификатор устройства: 0x1996.
Тепловизор имеет три интерфейса:
- iAP с конечными точками: 0x00 (чтение и запись), 0x81 (чтение) и 0x02 (запись);
- FileIO с конечными точками: 0x00 (чтение и запись), 0x83 (чтение) и 0x04 (запись);
- Frame с конечными точками: 0x00 (чтение и запись), 0x85 (чтение) и 0x06 (запись).
Все эти конечные точки имеют тип bulk.
Интерфейс iAP позволяет управлять остальными двумя интерфейсами; посылая в iAP управляющую команду с нужными параметрами (они есть в приложенных файлах программ и драйверов). Чтобы получить тепловое изображение достаточно производить чтение и расшифровку данных из конечной точки 0x85 интерфейса Frame и не забывать читать данные и из конечных точек 0x81 и 0x85, иначе тепловизор может остановить передачу данных через некоторое время.
- Принятые данные выглядят примерно вот так:
- Четыре “магических” байта, отделяющие пакеты друг от друга: 0xEF,0xBE,0x00,0x00;
- Заголовок, в котором указаны размеры данных тепловой и обычной камеры, общий размер кадра и данных состояния устройства.
- Данные кадра тепловой камеры.
- Прочие данные.
Что же именно передаётся во всём кадре, я не изучал; мне было достаточно данных от тепловой камеры.
Принятые данные с тепловой камеры представляют собой массив 14 битных значений показаний АЦП с болометрической матрицы, начинающиеся с заголовков блоков данных для каждых 80 пикселей. Заголовок выглядит так (взято из документации на тепловизионный модуль Lepton 3, используемый в FLIR One Gen 2):
Заголовок блока данных в 80 байт.
Из этого заголовка нас интересует только код CRC, вычисляемый по полиному, указанному в документации.
Чтобы построить красивую картинку достаточно просто найдя максимум и минимум привести полученные показания в диапазон 0-255 (по числу цветов палитры). Собственно, на этом построение красочных картинок и заканчивается. Если же есть желание по данным показаний вычислить температуру, то тут потребуются интересные формулы с набором коэффициентов для конкретной модели тепловизора. К счастью, эти коэффициенты для FLIR One Gen 2 известны.
А формула, согласно документации “FL IR Lepton wi th Radiomet ry Qui cks tar t Guide”, вот какая:
Мда… Хорошо, что tomas123 уже озаботился такими вычислениями и в своей программе написал функцию вычисления температуры объекта. В моей переделке она выглядит вот так:
double PlanckR1=16528.178;
double PlanckB=1427.5;
double PlanckF=1.0;
double PlanckO=-1307.0;
double PlanckR2=0.012258549;
double TempReflected=20;
double Emissivity=0.95;
//---------------------------------------------------------------------------
//вычислить температуру
//---------------------------------------------------------------------------
bool GetTemperature(unsigned short raw14,double &value)
{
if (raw14>0x10000) return(false);
raw14*=4;
double zn=(PlanckR2*(exp(PlanckB/(TempReflected+273.15))-PlanckF));
if (fabs(zn)<EPS) return(false);
double RAWrefl=PlanckR1/zn-PlanckO;
double RAWobj=(raw14-(1-Emissivity)*RAWrefl)/Emissivity;
double lgr=PlanckR1/(PlanckR2*(RAWobj+PlanckO)+PlanckF);
if (lgr<=EPS) return(false);
value=PlanckB/log(lgr)-273.15;
return(true);
}
Здесь TempReflected – температура болометрической матрицы, а Emissivity- коэффициент излучения измеряемой поверхности. Константы PlanckR1, PlanckB, PlanckF,Planck, и PlanckR2 специфичны для данной модели тепловизора.
Как можно заметить, моя программа для Windows сохраняет RAW-файлы. Для их анализа я также написал отдельное приложение. Выглядит оно вот так вот:
Анализатор RAW-файлов для Windows XP.
Собственно, на этом всё. Исходники и сами программы прилагаются по ссылкам ниже (я так и не понял, как их разместить на github).
Автор: da-nie