четверг, 7 января 2016 г.

"Тепловизор" на основе Arduino и сенсора MLX90620

Некоторое время назад я приобрёл интересный прибор -- сенсор MLX90620. Это массив термостолбиков (thermopile) 16x4. По сути это такой "почти что" тепловизор, разве что с очень низким разрешением: 4 строки по 16 элементов. Другими словами он позволяет одновременно измерять поле темперутур в 64 точках на расстоянии. Мне конечно было очень интересно попробовать его в действии.

Датчик MLX90620 подключается к шине I2C, а значит его должно быть легко подключить к различным микроконтроллерам. Первым делом я попробовал соединить его с платой Raspberry Pi, но оказалось, что процессор Raspberry Pi (BCM2835) содержит аппаратный баг в реализации шины I2C, и штатными средствами подключить датчик к этой плате не получится.

Поэтому я переключился на подключение датчика к плате Arduino Uno. Для этого я собрал на макетной плате такую схему:







Датчик нужно питать напряжением 2.6 вольта. Самый простой способ подать такое напряжение -- запитать его от порта 3.3 вольта на Arduino через кремниевый диод. На диоде будет падать примерно 0.6 вольт, следовательно на ножке питания сенсора будет примерно 2.7 вольта.

С точки зрения шины I2C сенсор определяется как два устройства с адресами 0x50 и 0x60. По адресу 0x50 находится небольшое ПЗУ, в котором хранятся калибровочные константы для каждого из 64-х чувствительнх элементов-пикселей сенсора а так же для встроенного датчика внешней температуры. Из устройства по адресу 0x60 производится непосредственное чтение температур. Для перевода прочитанных значений в градусы нужно использовать формулы из спецификации к сенсору.

Само собой, я был не первым, кто пытался подружить Arduino и MLX90620. Я нашёл статью Олега Евсигнеева в которой есть ссылка на готовый работающий скетч для Arduino. К сожалению приведённая в этой статье ссылка на библиотеку i2cmaster, которая необходима для работы этого скетча, оказалась устаревшей. В итоге я использовал версию библиотеки отсюда.

Вообще-то там не один скетч, а два, которые надо залить в Arduino по очереди. Первый скетч MLX90620_alphaCalculator.ino читает из ПЗУ сенсора калибровочне константы alpha_ij и отправляет их в Serial port адруино. Эти константы следует увидеть в терминале (например, PuTTY), скопировать в буфер обмена и вставить во второй скетч: MLX90620_Example.ino. После этого надо скомпилировать второй скетч и залить его в Arduino на место первого.

Этот скетч будет выдавать в терминальное окно таблицу 4x16 с температурами в градусах Фаренгейта. Если вы, как и я, не любите градусы Фаренгейта, просто найдите такую строчку в скетче:

    Serial.print(convertToFahrenheit(temperatures[i]));

И замените её на

    Serial.print(temperatures[i]);
.

Работает! В терминале такой вывод:
25.82, 25.59, 24.78, 23.87, 26.47, 25.72, 24.15, 25.00, 26.51, 25.80, 23.65, 25.87, 27.85, 26.60, 25.93, 26.61,
27.78, 31.22, 31.05, 30.55, 28.85, 42.29, 58.05, 54.52, 28.77, 43.14, 59.59, 56.39, 29.16, 44.10, 59.48, 56.69,
29.06, 42.96, 59.27, 56.48, 28.35, 38.74, 49.77, 45.42, 26.55, 27.55, 29.37, 31.01, 26.92, 27.23, 27.23, 27.25,
25.02, 26.58, 27.24, 26.56, 26.09, 25.83, 25.13, 25.39, 26.54, 25.35, 25.76, 27.34, 26.52, 26.10, 26.11, 26.02,


Чтобы протестировать датчик я поставил горячий чайник примерно по центру поля зрения MLX90620, и получил такой вывод. Действительно, температура фона - 23-25 градусов, тогда как по центру - 50-60. Не совсем понятно откуда взялись высокие значения температуры в правом конце второй строки. Блик?

Имейте в виду, что заявленной точности сенсора 0.5К при частоте обновления "картинки" 1Гц недостаточно для "медицинских" применений. Кроме того (об этом даже упомянуто отдельно в спецификации) температура на поверхности открытого участка тела может сильно отличаться от ожидаемых 36-37 градусов цельсия.