Hi, here is some details about my thermal cam project:
I used this IR temperature gun:
http://www.ebay.com/itm/150969162727?ssPageName=STRK:MEWNX:IT&_trksid=p3984.m1497.l2649It has a TPS334 thermopile, Op-amp and a ADS1110 AD converter with I2C bus. I use a Arduino Nano to interface the AD converter and pan/tilt servos.
On the PC side a Processing program displays the result.
See pictures for connections.
Arduino code:
#include <Wire.h>
#include <Servo.h>
Servo pan;
Servo tilt;
int angle;
char charInput;
String command, temp;
void setup()
{
pan.attach(2);
tilt.attach(3);
Wire.begin();
Serial.begin(9600);
pinMode(13, OUTPUT);
Wire.beginTransmission(0x49); // thermosensor init
Wire.write(0b10001110);
if (Wire.endTransmission()) Serial.println("Error 1");
}
void loop() {
command="";
while (1) {
charInput = Serial.read();
if (charInput == '\r') break;
if (charInput != -1 && charInput != '\n') command += charInput;
}
if (command.length() == 8) {
temp = command.substring(0,4);
angle = temp.toInt();
angle = constrain(angle, 1000, 2000);
pan.writeMicroseconds(angle);
temp = command.substring(4,8);
angle = temp.toInt();
angle = constrain(angle, 1000, 2000);
tilt.writeMicroseconds(angle);
digitalWrite(13,1);
delay(50);
digitalWrite(13,0);
Serial.println(getTemperature());
}
else Serial.println(command);
}
void debug() {
digitalWrite(13,1);
delay(100);
digitalWrite(13,0);
delay(100);
}
int getTemperature() {
byte byteLow, byteHigh;
Wire.requestFrom(0x49, 2);
if (Wire.available() != 2) Serial.println("Error 2");
byteHigh = Wire.read();
byteLow = Wire.read();
return byteHigh<<8 | byteLow;
}
Processing code:
final int xSize = 150;
final int ySize = 150;
import processing.serial.*;
Serial myPort; // Create object from Serial class
int xPos, yPos, angle, state, temperature, minimum, maximum;
String serialInput;
char charInput;
int[][] temperatureMap = new int[xSize][ySize];
void setup()
{
size(xSize*4, ySize*4);
for (yPos = 0 ; yPos < ySize ; yPos++) {
for (xPos = 0 ; xPos < xSize ; xPos++) {
temperatureMap[xPos][yPos] = 0;
}
}
xPos=0;
yPos=0;
state=1;
minimum = 0x7fff;
maximum = 0x0000;
myPort = new Serial(this, Serial.list()[1], 9600);
delay(2000);
background(0);
}
void draw() {
if (state==1) {
print(xPos);
print(", ");
println(yPos);
angle = 1500 - (-xSize / 2 + xPos ) * 5; //horizontal FOV
myPort.write(str(angle));
angle = 1500 - (-ySize / 2 + yPos ) * 5; //vertical FOV
myPort.write(str(angle));
myPort.write('\r');
if (xPos==0) delay(400);
drawMap();
serialInput = "";
while (true) {
charInput = myPort.readChar();
if (charInput == '\r') break;
if (charInput != 65535 && charInput != '\n') serialInput += charInput;
}
temperature = parseInt(serialInput);
println(temperature);
temperatureMap[xPos][yPos] = temperature;
if (temperature > maximum) maximum = temperature;
if (temperature < minimum) minimum = temperature;
println(minimum);
println(maximum);
xPos++;
if (xPos==xSize) {
xPos=0;
yPos++;
if (yPos==ySize) state=0;
}
}
}
void drawMap() {
int x, y, temp;
float gain, colour;
color c;
gain = 256.0 / (float)(maximum - minimum + 1);
println(gain);
for (y = 0 ; y < ySize ; y++) {
for (x = 0 ; x < xSize ; x++) {
temp = temperatureMap[x][y];
if (temp != 0) {
colour = (float)(temp - minimum) * gain;
stroke(colour);
fill(colour);
rect(x*4,y*4,3,3);
}
}
}
}
Cool.
You could probably speed it up if you used one of those new sensor arrays. Like the 4x16 MLX90620.
They're a bit expensive ($30-100) but still affordable.
That way you'd get more pixels per sample and require less servo movement.
You'd probably need an extra lens, the FOV of those sensors is a bit wide to build a detailed image.
Can you post some more details? I want to make one.
Cool.
You could probably speed it up if you used one of those new sensor arrays. Like the 4x16 MLX90620.
They're a bit expensive ($30-100) but still affordable.
That way you'd get more pixels per sample and require less servo movement.
You'd probably need an extra lens, the FOV of those sensors is a bit wide to build a detailed image.
I have already speed up the servo movements, so I am quite happy with it.
It is still very slow, but I have good time and it gives a good image, the best I have seen by similar projects on the net.
Can you post some more details? I want to make one.
Ok, what details do you need?
Cool job.. I thought about something like this years ago, but I didn't start anything yet. Maybe you would like to give my idea a try.. basically I thought about using a scanning mirror like a laser printer... a hexagon mirror on a rotating motor, and you can servo it vertically. If you use it with a line array it might work pretty well.
Really cool, something I've been wanting to build myself for a long time. I also thought about making a mirror system to make it quieter (probably no use to try to make it faster? What's the update speed of the thermopile you're using?)
A little optimization idea: why make a rough turn to the beginning of the next scan line if you can scan in a meander pattern?
Really cool, something I've been wanting to build myself for a long time. I also thought about making a mirror system to make it quieter (probably no use to try to make it faster? What's the update speed of the thermopile you're using?)
I have not measured it, but is seems reasonably fast. The limiting factor seems to be the slow AD converter.
A little optimization idea: why make a rough turn to the beginning of the next scan line if you can scan in a meander pattern?
Good idea, I will try that.
Really cool, something I've been wanting to build myself for a long time. I also thought about making a mirror system to make it quieter (probably no use to try to make it faster? What's the update speed of the thermopile you're using?)
I have not measured it, but is seems reasonably fast. The limiting factor seems to be the slow AD converter.
A little optimization idea: why make a rough turn to the beginning of the next scan line if you can scan in a meander pattern?
Good idea, I will try that.
Further optimisation - dynamically adjust scan speed according to rate of change, so flat areas are scanned faster.
Further optimisation - dynamically adjust scan speed according to rate of change, so flat areas are scanned faster.
I do not know how well that will work here. Already the scanning rate is close to the speed of the AD-converter ( 15 conversions/second )
A little optimization idea: why make a rough turn to the beginning of the next scan line if you can scan in a meander pattern?
I tested this and it did not work well. The alternating lines where shifted about 3-4 pixels.
I have a new version of the PC-side software that reduces the load on the PC and the scan time. 150x150 pixels take about 30 minutes.
final int xSize = 150;
final int ySize = 150;
import processing.serial.*;
Serial myPort; // Create object from Serial class
int xPos, yPos, angle, state, temperature, minimum, maximum;
String serialInput;
char charInput;
float gain, previousGain;
int[][] temperatureMap = new int[xSize][ySize];
void setup()
{
size(xSize*4, ySize*4);
for (yPos = 0 ; yPos < ySize ; yPos++) {
for (xPos = 0 ; xPos < xSize ; xPos++) {
temperatureMap[xPos][yPos] = 0;
}
}
xPos=0;
yPos=0;
state=1;
minimum = 0x7fff;
maximum = 0x0000;
previousGain = 0;
myPort = new Serial(this, Serial.list()[1], 9600);
delay(2000);
background(0);
}
void draw() {
if (state==1) {
print(xPos);
print(", ");
println(yPos);
angle = 1500 - (-xSize / 2 + xPos ) * 5; //horizontal FOV
myPort.write(str(angle));
angle = 1500 - (-ySize / 2 + yPos ) * 5; //vertical FOV
myPort.write(str(angle));
myPort.write('\r');
if (xPos==0) delay(400);
serialInput = "";
while (true) {
charInput = myPort.readChar();
if (charInput == '\r') break;
if (charInput != 65535 && charInput != '\n') serialInput += charInput;
}
temperature = parseInt(serialInput);
println(temperature);
temperatureMap[xPos][yPos] = temperature;
if (temperature > maximum) maximum = temperature;
if (temperature < minimum) minimum = temperature;
println(minimum);
println(maximum);
gain = 256.0 / (float)(maximum - minimum + 1);
println(gain);
if (gain != previousGain) {
previousGain = gain;
drawMap();
}
else {
drawPixel(xPos, yPos, temperature);
}
xPos++;
if (xPos==xSize) {
xPos=0;
yPos++;
if (yPos==ySize) {
state=0;
myPort.write("15001500\r");
}
}
}
else {
drawMap();
}
}
void drawMap() {
int x, y, temp;
for (y = 0 ; y < ySize ; y++) {
for (x = 0 ; x < xSize ; x++) {
temp = temperatureMap[x][y];
if (temp != 0) {
drawPixel(x, y, temp);
}
}
}
}
void drawPixel(int x, int y, int temp) {
float colour;
colour = (float)(temp - minimum) * gain;
stroke(colour);
fill(colour);
rect(x*4,y*4,3,3);
}
A little optimization idea: why make a rough turn to the beginning of the next scan line if you can scan in a meander pattern?
I tested this and it did not work well. The alternating lines where shifted about 3-4 pixels.
Yeah, RC servos usually have a lot of play, ~2 degrees is nothing special even in the expensive ones. You can try preloading it by pulling it to one side with a spring or a rubber band.
I think backlash is only a part of the problem. There is not that much hysteresis in the servo. The sensors time constant and other processing delay also play a role. I either have to slow down the scan (it is now much faster than in the video, about 10 pixels/second) or apply some more processing.
Hi Kaptein QK,
nice project, thanks for posting the details.
The link to eBay 50:1 is not working, would you please be so kind to post a new one to your featured device.
Thanks a lot in advance.
Just stumbled across this thread. Your image clarity is amazing!
I have also built a thermal imager a while ago. I used a TMP006 on a breakout board (22$ on ebay). The results were rather poor because of the huge field of view. Trying to limit that with a plastic straw didn't help a lot. I had to superimpose an optical image to even see what's in the picture.
Has anyone tried the Melexis MLX90614ESF-DCI ? From the datasheet it sounds ideal.
EDIT: Fixed typo.
Unfortunately not available outside US. Presumably as the framerate is 1Hz over the 9Hz limit for requiring an export license.
This guy in France sells a Grid-Eye board :
http://ir-robotics.com/shop/category.php?id_category=6
Does it goe by the max rate of the sensor or the entire product? They could limit the rate in the MCU firmware.
Unfortunately not available outside US. Presumably as the framerate is 1Hz over the 9Hz limit for requiring an export license.
This guy in France sells a Grid-Eye board :
http://ir-robotics.com/shop/category.php?id_category=6
Does it goe by the max rate of the sensor or the entire product? They could limit the rate in the MCU firmware.
From my reading of it, it's a bit of a grey area - ITAR can cover components within equipment, but what constitutes a component could be arguable in many cases.