Если вам не по карману языческий чудо-тепловизор, стоимостью от пары-тройки до десятков тысяч хрустящих вечнозеленых президентов, и уже стали захлебываться собственной слюной при его виде, то вы всегда можете нашаманить себе бубен истинно православный гаджет-облучатель из ИК-термометра, RGB-светодиодов и... буратины. Принцип действия настолько прост, что нуждается в отдельном пояснении : вы направляете ИК-датчик термометра на определенный сектор в исследуемой области, микроконтроллер считывает 10-битные данные по последоватеьной SMBus-шине с датчика (данные идут непрерывно для диапазона -20...+120 ˚С с разрешением 0.14 ˚C), пропорциональные измеряемой температуре, и подсвечивает сектор согласно цветовой температуре через RGB-лампу на светодиодах, участки с разной температурой будут иметь разные цветовые оттенки в уже видимом нам цветовом диапазоне восприятия. Параллельно вы проводите съемку фотоаппаратом с открытой диафрагмой. В итоге имеем подсвеченное раскрашенное изображение, эквивалентное температурным показателям.
Схема подключения датчика
Комлектующие
фотоаппарат с включенной выдержкой на время экспозиции объектов
MLX90614 (ИК-термометр)
0.1uF Ceramic Capacitor
2 4.7k Resistors
3 1k Resistors
8-RGB светодиодов
Arduino или... другие буратины
9V Battery Clip and Battery
кожух
Даташит на ИК-термометр.
Примерный код выглядит следующим образом.
#include <i2cmaster.h>
#include "Wire.h"
//#include "BlinkM_funcs.h"
const float lowReading = 60;
const float highReading = 75;
const unsigned char separatorCharacter = 255;
void setup(){
pinMode(9,OUTPUT);
pinMode(10,OUTPUT);
pinMode(11,OUTPUT);
Serial.begin(9600);
Serial.println("starting setup...");
i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups
Serial.println("completed setup");
}
float normf(float x, float low, float high) {
float y = (x - low) * 255.f / (high - low);
if(y > 255) {
y = 255;
}
if(y < 0) {
y = 0;
}
return y;
}
void loop(){
int dev = 0x5A<<1;
int data_low = 0;
int data_high = 0;
int pec = 0;
i2c_start_wait(dev+I2C_WRITE);
i2c_write(0x07);
// read
i2c_rep_start(dev+I2C_READ);
data_low = i2c_readAck(); //Read 1 byte and then send ack
data_high = i2c_readAck(); //Read 1 byte and then send ack
pec = i2c_readNak();
i2c_stop();
//This converts high and low bytes together and processes temperature, MSB is a error bit and is ignored for temps
double tempFactor = 0.02; // 0.02 degrees per LSB (measurement resolution of the MLX90614)
double tempData = 0x0000; // zero out the data
int frac; // data past the decimal point
// This masks off the error bit of the high byte, then moves it left 8 bits and adds the low byte.
tempData = (double)(((data_high & 0x007F) << 8) + data_low);
tempData = (tempData * tempFactor)-0.01;
float celcius = tempData - 273.15;
float fahrenheit = (celcius*1.8) + 32;
//Serial.println(fahrenheit);
float state = normf(fahrenheit, lowReading, highReading);
//Serial.write((unsigned int) state);
//Serial.write(separatorCharacter);
// BlinkM MaxM super-bright LED:
// 165 is blue, 0 is red
//BlinkM_fadeToHSB(blinkm_addr, map(state, 0, 255, 165, 0), 255, 255);
// Regular ol' RGB LED:
int hue = map(state,0,255,359,(359*0.5)); // not the whole color wheel
setLedColorHSV(hue,1,1); //We are using Saturation and Value constant at 1
Serial.print(fahrenheit);
Serial.print(" degrees F, hue: ");
Serial.println(+hue);
}
//Convert a given HSV (Hue Saturation Value) to RGB(Red Green Blue) and set the led to the color
// h is hue value, integer between 0 and 360
// s is saturation value, double between 0 and 1
// v is value, double between 0 and 1
//http://splinter.com.au/blog/?p=29
void setLedColorHSV(int h, double s, double v) {
//this is the algorithm to convert from RGB to HSV
double r=0;
double g=0;
double b=0;
double hf=h/60.0;
int i=(int)floor(h/60.0);
double f = h/60.0 - i;
double pv = v * (1 - s);
double qv = v * (1 - s*f);
double tv = v * (1 - s * (1 - f));
switch (i)
{
case 0: //rojo dominante
r = v;
g = tv;
b = pv;
break;
case 1: //verde
r = qv;
g = v;
b = pv;
break;
case 2:
r = pv;
g = v;
b = tv;
break;
case 3: //azul
r = pv;
g = qv;
b = v;
break;
case 4:
r = tv;
g = pv;
b = v;
break;
case 5: //rojo
r = v;
g = pv;
b = qv;
break;
}
//set each component to a integer value between 0 and 255
int red=constrain((int)255*r,0,255);
int green=constrain((int)255*g,0,255);
int blue=constrain((int)255*b,0,255);
setLedColor(red,green,blue);
}
//Sets the current color for the RGB LED
void setLedColor(int red, int green, int blue) {
//Note that we are reducing 1/4 the intensity for the green and blue components because
// the red one is too dim on my LED. You may want to adjust that.
analogWrite(9,red); //Red pin attached to 9
analogWrite(10,green); //Red pin attached to 9
analogWrite(11,blue); //Red pin attached to 9
}
|