Thermal imaging project help

Hi Everyone,

I am trying to build a thermal imaging scanner similar to these:
http://spill.tanagram.com/2010/11/24/diy-thermal-imaging-system-for-under-200/

I got some readings but it always seem to stop after some readings. I don't know where it gets stuck, but my guess would be there is some problem with the serial communication or something. Another concern I have is the usb port, the arduino program keeps telling me the board is not available at com port 3, I have to remove and reattach the usb cable to the board to continue. (is this related to my other problem?)

Thanks for your help in advance.

This is the output I get:
Starting
3,
7,
0,
5,
3,
3,
3,
4,

,

,

,
ï
,

,
?
,

,

,
11,
18,
12,
11,
12,
15,
7,
7,
13,

,

,

,
ï
,

//here it does not give any output, even pressing on the reset button on the board does nothing, the only thing that helps is removing and reattaching the usb cable after which I get:

Starting
26,

My code:

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

Servo MyServoX;
Servo MyServoY;
int CurrentPosX = 0; 
int CurrentPosY = 0;

byte TempArray[8] = {'0','0','0','0','0','0','0','0'}; 

void setup()
{
  Wire.begin();
    MyServoX.attach(11);
    MyServoY.attach(10); 
    Serial.begin(9600); //9600

    Serial.println("Started");
}

void SetServosToZero() 
{
    MyServoY.write(0); 
    MyServoX.write(0); 
    delay(10);
}

void SetTempArrayToZero()
{
    for (int i = 0 ; i < 8; i++)
    {
       TempArray[i] = '0'; 
    }
}

void loop()                     
{
  SetServosToZero();

  for(int x = CurrentPosX ; x < 180  ; x += 5)
  {
     for (int y = CurrentPosY ; y < 140 ; y += 5)
     {
         MyServoY.write(y); 
         delay(15);
     }  
     MyServoY.write(0); 
     MyServoX.write(x); 
  }
  
  byte TempArray[8];
  GetTemp();

  byte b ; 
  for (int i = 0 ; i < 8; i++)
  {
      b = TempArray[i];
      Serial.println(b); 
      Serial.println(",");
  }
}

void GetTemp() 
{
    byte b;
    for (int i = 0; i <= 8; i++)
    {
      Wire.beginTransmission(TPA81ADDR);
      Wire.send((i +1));
      Wire.endTransmission();

      Wire.requestFrom(TPA81ADDR, (int) 1);
    
      int Whiles; 
      boolean Breaked = false;  
      //Serial.println("Starting while loop");

      while((Wire.available() < 1) && (Breaked == false))
      { 
         if (Whiles > 10)
         {
             Breaked = true;
             break; 
         }
         Whiles++;
      }

    if (Breaked == false) 
    {
      b = Wire.receive(); 
      TempArray[i] = b;
      Serial.print(b, DEC);
      Serial.println(",");
    }
  }
}
  for(int x = CurrentPosX ; x < 180  ; x += 5)
  {
     for (int y = CurrentPosY ; y < 140 ; y += 5)
     {
         MyServoY.write(y); 
         delay(15);
     }  
     MyServoY.write(0); 
     MyServoX.write(x); 
  }

Waving the servos around, without doing anything. Why bother?

byte TempArray[8] = {'0','0','0','0','0','0','0','0'}; 
  byte TempArray[8];
  GetTemp();

  byte b ; 
  for (int i = 0 ; i < 8; i++)
  {
      b = TempArray[i];

Which TempArray are you printing? Why do you have two identically named variables?

Thanks for your reply,
At first I had my GetTemp code inside the servo loop, but I set it aside for debugging purposes. But eventually it has to go back in.

I removed one declaration of my output array. (nice catch... I completely missed that)

But the program still does not get through the GetTemp methode, if I don't call this methode it runs fine, but when I do call it, it just gets stuck, and the program no longer responds. So there must be something wrong within this methode, but I can't find it.

byte TempArray[8] = {'0','0','0','0','0','0','0','0'}; 
#include <Wire.h>
#define TPA81ADDR (0xd0>>1)

void GetTemp() 
{
    byte b;
    for (int i = 0; i <= 8; i++)
    {
          Wire.beginTransmission(TPA81ADDR);
          Wire.write((i +1));
          Wire.endTransmission();
  
        Wire.requestFrom(TPA81ADDR, (int) 1);
      
        int Whiles; 
        boolean Breaked = false;  
        //Serial.println("Starting while loop");
        while((Wire.available() < 1) && (Breaked == false))
        { 
           if (Whiles > 10)
           {
               Breaked = true;
               break; 
           }
           Whiles++;
        }
  
      if (Breaked == false) 
      {
        b = Wire.read(); 
        TempArray[i] = b;
        Serial.print(b, DEC);
        Serial.print(",");
      }
    }
}
        Wire.requestFrom(TPA81ADDR, (int) 1);

1 is an int by definition. There is no reason to cast it to an int. The requestFrom function returns a value. What is that value?

        int Whiles; 
        boolean Breaked = false;  
        //Serial.println("Starting while loop");
        while((Wire.available() < 1) && (Breaked == false))
        { 
           if (Whiles > 10)
           {
               Breaked = true;
               break; 
           }
           Whiles++;
        }

Local variables, like Whiles, are not initialized. For all you know, Whiles starts off with a value of -32401. I'm guessing that that is not what you want. Also, the while loop will execute very fast. Iterating 10 or 100 or 1000 times will not result in a significant wait.

You've said nothing about what you are reading from, so it isn't obvious why you expect to be able to read 8 different values from it.

Thanks for your help. I really appreciate it.

To be honest I didn't write that particular part of code, I copied it from those two other projects I mentioned.
The idea is that this code reads eight values from a heat measuring device (http://www.solarbotics.com/products/40370/)
I am not sure exactly how it is supposed to work, especially the stuff with addresses and the wire class to get the values from the heat measuring device.

I updated my while loop but it still gets stuck (I suspect there is still something wrong with the code that gets the heat information)
My new while loop:

int Whiles = 0; 
        boolean Breaked = false;  
        //Serial.println("Starting while loop");
        while((Wire.available() < 1) && (Breaked == false))
        { 
           delay(1000); 
           if (Whiles > 10)
           {
               Breaked = true;
               break; 
           }
           Whiles++;
        }

I'd try getting rid of the while loop altogether. There is either a byte of data to read, or there isn't. You can tell which is the case. If there is no data, wait 50 milliseconds, and try again. If there is still no data, there never will be. Move on.

Add Serial.print() statements to the GetTemp() function to see where it hangs, if it continues to hang.

The byte being printed is assumed to be a character. The funky symbols are because the character is a non-printing character. Try printing the value using

Serial.print(b, HEX);

I tried putting print statements all over the code... And the place it always gets stuck is:
Wire.requestFrom(TPA81ADDR, 1);
with #define TPA81ADDR 0xd0>>1 //I figure the first four are some kind of address but I have no idea what the >>1 means by the way.

I tried several other addresses, and with some others it does get passed the requestFrom.
I also adapted the while statement like you said, and told it to print the result of endTransmission, this is zero for the adres 0xd0>>1 and for 0x68 (without anything after it). For the last one (0x68) it (sometimes) finds something (pretty sure its not temperatures), but also gets stuck sometimes.

I really have no idea what's going on, because the output differs when I make no changes, and I am still doubting if I have the right address.

I am still doubting if I have the right address.

According to the data sheet, the address is 0xD0, by default. The >> 1 bit is shifting the address one bit to the right. The Wire library manages the read/write bit, so, I think that 0xD0 >> 1 is correct.

I'm not sure why it sometimes seems to work, and sometimes doesn't. I'm not sure what values you need to write to the chip to get it return specific registers. Nick's the SPI expert. Hopefully, he'll be along.

Assuming the address is correct, and the code is similar to the standard way of using this library, it has to be my setup.
So I had a good look at my designs, and the only thing I can think of is that because the i2c device works with an open drain principle I have to provide additional power. Currently my setup is like this (similar to the example projects):
http://spill.tanagram.com/wp-content/uploads/2010/11/ThermoscannerSchematic1.png
without any additional power on the SDA and SCL lines. I could put 5v on these lines but I am afraid this might damage my board or the thermal imaging device. Could trying this do harm to my board or device?

UndeaDS:
Currently my setup is like this (similar to the example projects):
http://spill.tanagram.com/wp-content/uploads/2010/11/ThermoscannerSchematic1.png
without any additional power on the SDA and SCL lines. I could put 5v on these lines but I am afraid this might damage my board or the thermal imaging device. Could trying this do harm to my board or device?

Probably a bad idea. Read the bit about two-wire serial in the Atmel manual, it will shed some light. It starts on page 216, here,

According to this site,
http://www.robot-electronics.co.uk/htm/tpa81tech.htm

That board that you're using doesn't have any external pull-up resistors pre-wired on it. I'd assume that you'd need some. Try putting a 4.7k resistor in-line with your SDA and SCL line. No pull-ups mean shoddy digital edges and bad communications. Just something I learned from experience.

-Ian

So if I understand correctly I put 5v from my Arduino (I have uno) through one regular 4.7k resistor and hook that up to both my sda and scl line going from my thermal device to my Arduino?
Does it have to be 4.7 or could I also use 10k?

UndeaDS:
So if I understand correctly I put 5v from my Arduino (I have uno) through one regular 4.7k resistor and hook that up to both my sda and scl line going from my thermal device to my Arduino?
Does it have to be 4.7 or could I also use 10k?

No.

Your device is powered. Don't run any other power to the SDA or SCL lines.

You need a 4.7k resistor (or lower, but at least 1k, I've found most I2C devices work best with 4.7k and I can't find a datasheet on the TPA081) between the TPA081 and the Arduino, in line. What this does is help bring the communication line back up to voltage when it's released by either the slave or the master.

It will look something like this.

TPA081 SDA port >--------<4.7k>---------< Arduino analog #4 pin

TPA081 SCL port >--------<4.7k>---------< Arduino analog #5 pin

But no matter what you do, don't put 5v direct to either of the communication pins. I'm pretty sure it won't hurt the Arduino, but if your sensor communicates using 3.3v or lower, you could damage that.

-Ian

Still no luck, I used two resistors (I don't have 4.7 resistors (yet), so I used 2.2k). One between the sda and pin 4, and one between scl and pin 5. This still doesn't work, and I am really starting to run out of ideas...

My wire.endtransmission returns zero, sometimes 2 and rarely a 4.
The Wire.available() hardly ever does anything and is almost always zero.

This is my GetTemp method :

void GetTemp() 
{
    SetTempArrayToZero();
    byte result;
    byte b;
    for (int i = 0; i <= 9; i++)
    {
        Wire.beginTransmission(TPA81ADDR);
        Serial.print("WriteResult: ");
        result = Wire.write((i +1));
        Serial.println(result);
                
        Serial.print("TransmissionEndResult: ");
        result = Wire.endTransmission();
        Serial.println(result);
        Serial.println("StartedWireRequest");
        Wire.requestFrom(TPA81ADDR, 1);
        Serial.println("PassedWireRequest");

        result = Wire.available(); 
       
       if (Wire.available() < 1)
       {
          delay(1000);  
       }
       if (Wire.available() < 1)
       { 
         Serial.print("Wire not available: ");
         Serial.println(Wire.available());
       }
       else 
       { 
           b = Wire.read(); 
           TempArray[i] = b;
           Serial.print("Temp found: "); 
           Serial.print(b, DEC);
           Serial.println(",");
       }
    }

And this is what this results in:

WriteResult: 1
TransmissionEndResult: 0
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 0
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 0
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 2
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 2
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 4
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 0
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 2
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 2
StartedWireRequest
PassedWireRequest
Wire not available: 0
WriteResult: 1
TransmissionEndResult: 0
StartedWireRequest
PassedWireRequest
Wire not available: 0

I figured it out. The trick was only putting a resistor in the scl line and not in the sda. No idea why, but it works, so I am happy.

To everyone who helped: Thank you very very much!!

For someone with the same problem, I used the same setup as in the example projects, but I put a resistor (2.2k) in the scl line and used this code to get the temperatures (it's still a bit troublesome and I intent to have another look at it, but at least it works):

int TempArray[12] = {0,0,0,0,0,0,0,0,0,0,0,0}; 

void SetTempArrayToZero()
{
    for (int i = 0 ; i < 12; i++)
    {
       TempArray[i] = 0; 
    }
}

void GetTemp() 
{
    SetTempArrayToZero();
    byte result;
    byte b;
    for (int i = 0 ; i < 11; i++) 
    {
        Wire.beginTransmission(TPA81ADDR);
        Serial.print("WriteResult: ");
        result = Wire.write((i)); 
        Serial.println(result);
        
        Serial.print("TransmissionEndResult: ");
        result = Wire.endTransmission();
        Serial.println(result);
        Serial.println("StartedWireRequest");
        Wire.requestFrom(TPA81ADDR, 1);
        Serial.println("PassedWireRequest");

        result = Wire.available(); 
       
       if (Wire.available() < 1)
       {
          delay(1000);  
       }
       if (Wire.available() < 1)
       { 
         Serial.print("Wire not available: ");
        // Serial.println(Wire.available());
       }
       else 
       { 
           b = Wire.read(); 
           TempArray[(i)] = (int) b; 
           Serial.print("Temp found: "); 
           Serial.print(b, DEC);
           Serial.println(",");
       }
    }
}