Thermoscanner

Thermography was never so easy/cheap {#emotions_dlg.smile}

 

Take the hardware of the 3d Scanner, and just replacing the distance sensor with a thermopile. Thats it, and there it goes, the Thermoscanner!

 

Whats needed:

Hardware:

This time im using tape, as i was running out of zip ties {#emotions_dlg.innocent}

Just combine the 2 RC Servos and stick the TPA81 onto it.

Theorie:

The TPA81 provides 1x8 Pixels with 5.12° by 6°. The Sensor is mounted verticaly.

To Increase the resolution its stepping 1° horizontal and about 2° verticaly.

 

This makes is possible to get a real nice resolution, as can be seen in the top picture showing the candle.

The Thermal resolution from the TPA81 is 1°, but its jumping +-1° so measuring a human in a room is tricky...

 

(Pictrue from me on the couch)

 

Software:

The Software is splitted, on part Arduino Code, and the other is Processing.

The Arduino is only listening to the Processing Application, and this is then drawing a nice picture from it.

 

Processing makes the picture above, below is it processed in false color:

This is me on a couch wearing a tshirt and shorts, my face/arms/legs are hotter as they are not covered by clothing.

Taking this picture took about 30seconds with the code provided below.

 

Arduino Code:

//test by d2k2 24.09.2009

#include <AFSoftSerial.h>

#include <Wire.h>
#define TPA81ADDR (0xd0>>1)


#include  
 
Servo myServoPan;  // create servo object to control a servo
Servo myServoTilt;  // create servo object to control a servo


AFSoftSerial mySerial = AFSoftSerial(3, 2);

char CurrentServo;
int value;

int valueA; //Storage
int valueB;

int fresh = 0;

int Read = 0;
int runVal = 0;

void setup()
{
  Wire.begin(); // join i2c bus (address optional for master)
  myServoPan.attach(9); // attaches the servo on pin 9 to the servo object
  myServoTilt.attach(10); // attaches the servo on pin 10 to the servo object

  pinMode(13, OUTPUT);
  Serial.begin(57600);
  
  Serial.println("Scanturm V0.1");
}

void loop() // run over and over again
{
    
  get_keyboard_commands();
  
}

void get_keyboard_commands() {


  myServoPan.write(valueA);
  myServoTilt.write(valueB);
  
  
  if ( Serial.available()) {
    
    // read in a string
    Read = Serial.read();
   
   
    if (Read == 200){
      runVal = 0;
     // Serial.println("Reset");
    };
      
      
      
   switch (runVal) {
    case 0:
      runVal = 1;
      break;  
    case 1:
      valueA = Read;
      runVal = 2;
      break;
    case 2:
      valueB = Read;
      runVal = 3;
    case 3:

      SendTPA();

      /*
      Serial.print(": ");
      Serial.print(val);  
      Serial.println("$");
      */
      //runVal = 1;
      break;
   }
 
 }
  
}

void SendTPA(){
  
  //Send the TPA81 Data back to the PC:
  
   byte b;
  int i;
 
  for (i=1; i<=9; i++)
  {
    Wire.beginTransmission(TPA81ADDR);
    Wire.send(i);
    Wire.endTransmission();
    
    Wire.requestFrom(TPA81ADDR, (int) 1);
 
   while(Wire.available() < 1)
   { ; }

    b = Wire.receive(); // receive a byte as character

    Serial.print(b, DEC);
    Serial.print(";");
  }
  Serial.println("");
}

Processing Code:

 

//d2k2 24.09.2009  shows values from the TPA81 
//prestage for putting the sensor on the scan turrent

import processing.serial.*;

Serial myPort; // Create object from Serial class
int lf = 10; // Linefeed in ASCII
String myString;
int[] val = {1,1,1,1,1,1,1,1,1};
int MaxT=100;
int MinT=20;
int pan = 40;
int tilt = 80;
String[] list = null;

int MaxT2 = 0;
int MinT2 = 255;

boolean result = false;
boolean run = false;

long time;
long lastrun = 0;
long runT;
    

void setup()
{
  size(400, 400);

  String portName = Serial.list()[1];
  myPort = new Serial(this, portName, 57600);
  myPort.buffer(1);

}

void draw()
{
  
  time = millis();
  runT =  lastrun - time;


  String myTest = "";
 
  if ( myPort.available() > 0) { // If data is available,
   
    myString = myPort.readStringUntil(lf);
    if (myString != null)
    {
      list = split(myString, ';');
      myTest = list[0];  
      if(int(myTest)>0)
      {

        result = true;
        
        val[1] = int(list[8]);
        val[2] = int(list[7]);
        val[3] = int(list[6]);
        val[4] = int(list[5]);
        val[5] = int(list[4]);
        val[6] = int(list[3]);
        val[7] = int(list[2]);
        val[8] = int(list[1]);
        val[0] = int(list[0]);
        
        //check for new max/min events
        
        if(MaxT2<max(val))
        {
          MaxT2 = max(val);
        }
        
        if(MinT2>min(val))
        {
          MinT2 = min(val);
        }
                 
        //Draw another Line, right at the Pan Position

         //Pan is about everywhere from 10 to 170
         //so i need to update every Pan Pixel and just try it like that now
         
         float Col = 0;

         for(int i = 1;i<9; i = i+1){
           Col = map(val[i],MinT,MaxT,0,255);
           color drp = color(Col,Col,Col);
           for(int i2 = 1; i2 < 5; i2 = i2+1){
           set(pan+pan,    (i*4)+75+i2+tilt+tilt+4*i-100,drp);
           }
           for(int i2 = 1; i2 < 5; i2 = i2+1){
             set(pan+1+pan,(i*4)+75+i2+tilt+tilt+4*i-100,drp);
           }

         }
                          
    }
  }

  //background(255); // Set background to white

//Draw them 9 Pixels in a line:
/*
int Size = 45;
         float Col = 0;
        for (int i = 1; i < 9; i = i+1) {
           rect((Size*i)-Size+5, 5, Size, Size);
           Col = map(val[i],MinT,MaxT,0,255);
           fill(0,0,Col);
        }
*/
  
}


if(millis()>lastrun)
{
if(run == true)
{
  //Now i need to check if i got a result:
  if(result == true)
  {
    //Now i need to check if im at the end of my motion:
    if(pan < 150)
    {
      //Now i can move :)
      pan = pan + 1;
      SetServo();
      lastrun = millis()+100;
    } 
    else
    {
      run = false;
    }
  }
}
}  
  
}

void keyPressed() {
  if( key == '6'){
   pan = pan+1;  
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
  
  if( key == '4'){
   pan = pan-1;
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
 
  if( key == '8'){
   tilt = tilt-2;
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
  
  if( key == '2'){
   tilt = tilt+2;
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
  
  if( key == '5'){
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
  
  if( key == '1'){
   pan = 40;
   SetServo();
   println("Pan: " + pan);
   println("Tilt: " + tilt);
  }
  
  if( key == '3'){
   run = true;
  }

}

void SetServo(){
    result = false;
    myPort.write(200); //init
    myPort.write(tilt); //tilt
    myPort.write(pan); //pan
    delay(100);
    myPort.write(80); //trigger read
}

Links related to this:

Arduino Forum: http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1253898939/0#0
Hack a Day: http://hackaday.com/2009/09/25/arduino-thermoscanner/
Make: http://blog.makezine.com/archive/2009/09/thermal_imaging_on_the_cheap.html