How To Build Arduino Thermal Camera

My recent arduino project was to build thermal camera on the cheap using an ir sensor and some pan/tilt hardware. If you look at the device picture to the left there is also acoustic range finder mounted to the top.

Arduino Thermal Camera
The device works by sweeping a grid of points and assembles the image piecewise. The output consists of two images: 1) an acoustic images which tells the distance to the objects in view and 2) a thermal image that gives the temperature of the objects in view. I use gnuplot to assemble the images. See the scripts below.

I plan on using the range finder to determine the spot size of the IR reader. The spot size scales by dh_o/dL=2sin(5). Where dh_o is the change in spot diameter and dL is the change in distance from the sensor to the object. The five is a constant based on the 5degree viewing angle of the IR sensor.

I got the idea for the project from this site: http://www.cheap-thermocam.tk/

 

Assembly progression:

  1. Assemble Pan/Tilt with servos. Use medium servos because small was a little too under torqued for the tilt action (notice jerkyness in video). The servos require 5V.
  2. Attached the Ultrasonic transducer to a proto board by putting a wire through holes and soldering on both sides. (holes should align on both boards) Position the ultrasonic sensor in the middle of the main board so the ir sensor will align with the center of the ultrasonic sensor.
  3. Attached laser mount to Pan/Tilt hardware such that the two right angle mounting holes are on the top side to connect the board. I used the left over screws from the servo to connect the laser mount. I drilled a hole first that was slightly smaller than the screw thread diameter.

Arduino Thermal Camera circuit

  1. Push laser into laser mount all the way. Stop and mess with the laser and simple servo application.
  2. Now run a 3V power line and GND line leaving some extra wire to play with. The ultrasonic transducer can take 3V or 5V (5V better resolution). The IR sensor can only take 3V. My build just uses 3V for both the ir and sonar.
  3. Now put the ir senor in carefully and just solder the leads don’t trim. Next run your 4.7K ohm resistors from the power to the opposite side of board above the ir sensor.
  4. Now form the interconnects on the board.
  5. Add three wires to go from board to arduino. There is one for the ultrasound sensor and two for the ir sensor.
  6. Mount the sensor to the laser mount. Use the holes provided on the laser mount. I also used the extra screws from the servos and drilled out the matching holes on the sensor board. It is critical that everything is square.
  7. Connection the laser wires to the 3V power (red wire) and GND (white).
  8. Now form the interconnects on the board.
  9. Add three wires to go from board to arduino. There is one for the ultrasound sensor and two for the ir sensor.
  10. Mount the sensor to the laser mount. Use the holes provided on the laser mount. I also used the extra screws from the servos and drilled out the matching holes on the sensor board. It is critical that everything is square.
  11. Connection the laser wires to the 3V power (red wire) and GND (white).
  12. Connect the two power wires and three data lines to a intermediate board (got one from radio shack and cut it in half with a coping saw). This intermediate board will allow you to transition to the arduino pins. I add male headers (3pins) to this intermediate board to accept the servo connectors. Thus, if I blow a servo I don’t have to re-solder.
  13. When using the intermediate board you can create a common ground.
  14. Now, modify the plastic picture box to accept the servo on the top and wires to come through the top. I found the center of the top and traced the dimension of the servo on the top and drilled holes and coped out the hole. Then I drilled some holes to secure it to the plastic using the hardware for mounting provided on the servo. Additionally, I cut a rectangular section out of the side to accept the usb and power. I placed the arduino in the enclosure and traced the general shape and again used a coping saw to make the opening.
  15. I added standoffs to the bottom of my arduino and just hot glued the stand offs to the enclosure and the bottom of the arduino.
  16. Now feed wires from sensors through holes to the intermediate board and solder. Also add wires on the intermediate board to connect to the arduino.
  17. I added hot glue to the arduino wires to make sure they don’t pull out.
  18. Now close everything up and add some hot glue to the edge of the enclosure to keep everything together.
  19. Plug usb and power in and upload the following code.

Arduino code:
The program won’t start until you open a serial connection and hit ‘1’ and Enter. It will then outline the area of interest. To proceed hit ‘1’ and Enter again. The arduino will begin to collect data in a 2d array that it will output to the screen when completed.

//Arduino Thermal Camera
#include <i2cmaster.h>
#include <Servo.h>

Servo mvert;
Servo mhorz;

// Pins: 7=sonar; 4&5=ir sensor; 8=vert servo; 9=horz servo
//
//
//
const int pwPin = 7;
const int dev = 0x5A<<1;

long count = 0;

///Servo Ranges
int home_p = 0;
int j_done = 0;
int even = 0;
int xskip = 1;
int yskip = 1;
int xstart = 60;
int xstop = 75;
int ystart = 80;
int ystop = 70;

const int xnum = abs(xstart-xstop)+1;
const int ynum = abs(ystart-ystop)+1;

double therm[16][11];
double acous[16][11];

void setup(){

//sonar pin
pinMode(pwPin, INPUT);

//Servo pins
mvert.attach(8);
mhorz.attach(9);

//Home position servos
mvert.write(xstart); //1485
mhorz.write(ystart);  //1530

Serial.begin(9600);
Serial.println("Setup...");

i2c_init(); //Initialise the i2c bus
PORTC = (1 << PORTC4) | (1 << PORTC5);//enable pullups

}

void loop(){

int i,j,jt;
int hpos,vpos,hpos2,vpos2;
double tempData1 = 0x0000; // zero out the data
double sonrData1 = 0x0000;

if(Serial.available()){

if(home_p == 0){
i = 0;
Serial.flush();
Serial.println("Sweeping Viewing Space");
Serial.println("Enter 1 to confirm space");
mvert.write(ystart);
mhorz.write(xstart);
delay(30);
do
{
//This will sweep through window of view
for(int hpos=xstart;hpos<=xstop;hpos++){
mvert.write(ystart);
mhorz.write(hpos);
delay(20);
}
for(int vpos=ystart;vpos>=ystop;vpos--){
mvert.write(vpos);
mhorz.write(xstop);
delay(20);
}
for(int hpos=xstop;hpos>=xstart;hpos--){
mvert.write(ystop);
mhorz.write(hpos);
delay(20);
}
for(int vpos=ystop;vpos<=ystart;vpos++){
mvert.write(vpos);
mhorz.write(xstart);
delay(20);
}
i=Serial.read();
}while (i<=0);
Serial.println("Starting Calculation");
home_p=1;
}

if(j_done == 0){
for(int i=ystart;i>=ystop;i-=yskip){
for(int j=xstart;j<=xstop;j+=xskip){
if(even == 0){
jt = j;
mhorz.write(j);
delay(20);
}
else{
jt=xstop-(j-xstart);
mhorz.write(jt);
delay(20);
}

sonrData1 = readSonar(1);
tempData1 = readMLX(1);

//58uS per cm
double cm = sonrData1;
double celcius = tempData1 - 273.15;
//double fahrenheit = (celcius*1.8) + 32;

//Serial.print("temp,dist,i,j: ");
//Serial.print(celcius);
//Serial.print(", ");
//Serial.print(cm);
//Serial.print(", ");
//Serial.print(ystart-i);
//Serial.print(", ");
//Serial.println(xstop-jt);
//Serial.print("Fahrenheit,inches: ");
//Serial.println(fahrenheit,inches);
therm[xstop-jt][ystart-i] = celcius;
acous[xstop-jt][ystart-i] = cm;
delay(400); // wait a second before printing again
}
mvert.write(i);
delay(20);
if(even == 0){
even = 1;
}else{
even = 0;
}
}
//Output data
Serial.println("Outputting Data");
for(int j=0;j<ynum;j++){
for(int i=0;i<xnum;i++){
Serial.print(therm[i][j]);
Serial.print(", ");
Serial.print(acous[i][j]);
Serial.print(", ");
Serial.print(i);
Serial.print(", ");
Serial.println(j);
Serial.flush();
}
Serial.println(" ");
}
j_done = 1;
}
}}

double readMLX(int Tt) {

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.228;

return tempData;
}

double readSonar(int St) {

long pulse;

//Used to read in the pulse that is being sent by the MaxSonar device.
//Pulse Width representation with a scale factor of 147 uS per Inch.
pulse = pulseIn(pwPin, HIGH);

double sonrData = (double) ((pulse)/58.0);

return sonrData;
}

Gnuplot code:
I will fix this but for now copy and paste the data outputted to the screen from the code above to a file called data.txt. It is the temperature in celcius, distance in cm and x-y coordinate. Now create another file call _plot.gnu and paste the code below into that file. Then execute the gnuplot script by typing gnuplot ./_plot.gnu . Make sure the data.txt and _plot.gnu are in the same folder.

Major Components in Project

List of materials:

Source : How To Build Arduino Thermal Camera

 


About The Author

Ibrar Ayyub

I am an experienced technical writer holding a Master's degree in computer science from BZU Multan, Pakistan University. With a background spanning various industries, particularly in home automation and engineering, I have honed my skills in crafting clear and concise content. Proficient in leveraging infographics and diagrams, I strive to simplify complex concepts for readers. My strength lies in thorough research and presenting information in a structured and logical format.

Follow Us:
LinkedinTwitter

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top