Go Down

Topic: Trouble with MCP9808 temperature sensor on I2c (Read 6331 times) previous topic - next topic

MotoX

Hey guys! My first post on this forum, posting about a problem I have with my first project in the arduino environment.

I recently bought the sensor MCP9808, a temperature sensor I wan't to run on the I2c-bus of the Arduino Uno rev3.
Datasheet

Hardware wise I got some help from a friend who works with soldering to put a 4 lead sensor cable to the pins VCC, SDA, SCL and GND. He also soldered on a bridge pin between VCC and the pins A0, A1 and A2 on the sensor giving the sensor the I2c address 0x1F. Also worth mentioning is that the cable going to the sensor is about 40-50cm long. I would rather not shorten this if I don't have to since I want the sensor resting in a metal tube and then submerged in a water bath.

I hooked the 5V of the arduino up to the VCC lead. Put the SDA and SCL to inputs A4 and A5 on the arduino. GND lead to GND next to 5V and bridged 5V to SDA and SCL respectively with 10kOhm resistors.

Code wise I sat down and played around _alot_ with this for 6 hours last night... I tried alot of different examples on different ways to run sensors on I2c but it still seems like I can't really get through to the sensor. I have done an I2c scan and indeed 0x1F is the only address to show up. I tried switching places on SDA and SCL (my friend could have mixed them up) but that made the sensor go away completely from the scan. I have changed the I2c frequency in the arduino folder (I am not at home right now so can't tell you exactly which file) from 100kHz to 400kHz without any noticable difference. I have tried to put in 2 parallell coupled 10kOhm resistors each on SDA and SCL without any difference either. One thing I havn't tried is deactivate the internal pull ups of A4 and A5.

One thing that I was wondering about in particular, the code below
Code: [Select]

void setup()
{
  Wire.begin();
  Serial.begin(9600);
}

void loop()
{
  Wire.beginTransmission(0x1F);
  Wire.write(0x05); // Sending register pointer 0x05 for temp bytes
  Serial.println(Wire.endTransmission());

  delay(1000);
}


Will very often give me the values 2, sometimes also 3, in rare cases 4 and almost never 0. However I have completed the code with

Code: [Select]

  Wire.requestFrom(0x1F, 2);

  Serial.println(Wire.read(), BIN);

  delay(1000);

  Serial.println(Wire.read(), BIN);

  delay(1000);

Which normaly produces the binary codes
0000 1101
1111 1111
Sometimes though it instead goes
0000 0001
1111 1111

I have calculated these values according to the datasheet but I get something like 500 degrees celsius which, let me tell you, I don't have that in my room...

Another thing worth mentioning is that when I for instance write
Code: [Select]
Wire.requestFrom(0x1F, 6);
all of the extra bytes I fetch will just be 1111 1111.

So... Anybody here who are able to give me any hints as to what I might be doing wrong?

Erdin

That chip is able to use 3.3V and 5V.
So you can use it with 5V, that's good.

The 10k pull-up resistors on SDA and SCL are good.
Normally would 4k7 be better, but at 100kHz it is no problem at all.
You should use the original Wire library at 100kHz.
The internal activated pull-up resistors are not a problem for you, since you have a 5V I2C bus.

If the i2c_scanner is detecting it, the wiring is okay.

So far so good.

You have mixed result.
It might be the cable and it might be the code.
Could you use seperate wires instead of a cable ? If the SDA and SCL lines are close to each other and are capacitive coupled, it might destroy the communicaton.
Let the i2c_scanner run for an hour to be sure it is okay.
Could you write a function to write a single byte and a function to read a single byte.
I didn't look at the datasheet how the registers should be used yet, but it seems the normal register usage. So when reading a byte, you first have to write the registers address ("pointer") and after that you read the register.

MotoX

Yes as you say, first a register pointer and then read. I have attached a picture of it, found on page 26 in the datasheet, here in the post.

The sensor is a bit to small for me to solder, I could have a go at it later but for now I don't really have the time to make a new one. I do have spare sensors at home though so in about 2 weeks I could produce one with seperate shorter wires.

I can write the function when i get home and log the results.

Isn't it weird though that the
Code: [Select]
Serial.println(Wire.endTransmission());
gives me so many response 2, 3 and 4?

Quote from: Arduino Wire reference
Returns
byte, which indicates the status of the transmission:
0:success
1:data too long to fit in transmit buffer
2:received NACK on transmit of address
3:received NACK on transmit of data
4:other error

Erdin

Yes, that is very weird.
It could be a bad cable or a bad connection or a missing 100nF at the 5V and GND near the chip.

That datasheet is hard to understand!
Luckely they have included example source code.

It seems to have 9 registers of 16 bits.
Only register 0x08 (the nineth register) seems to be 8 bits.

Code: [Select]

// untested example code

const int mcp_address = 0x1F;

unsigned int ReadMCP( int reg)
{
  int i, lsb, msb;
  unsigned int x;

  Wire.beginTransmission( mcp_address);
  Wire.write( reg);
  i = Wire.endTransmission();    // perhaps add parameter true or false
  if( i != 0)
  {
    Serial.print( "Error in endTransmission in ReadMCP : ");
    Serial.println( i);
   return 0;
  }

  Wire.requestFrom( mcp_address, 2);    // perhaps add parameter true or false

  // set lsb and msb to zero, in case they could not be read.
  lsb = msb = 0;
  if( Wire.available() > 0)
    msb = Wire.read
  if( Wire.available() > 0)
    lsb = Wire.read

  x = word( msb, lsb);

  return( x);
}


int WriteMCP( int reg, unsigned int data)
{
  int i;

  Wire.beginTransmission( mcp_address);
  Wire.write( reg);

  Wire.write( highbyte( data));
  Wire.write( lowbyte( data));

  i = Wire.endTransmission();   // perhaps add parameter true or false
  if( i != 0)
  {
    Serial.print( "Error in endTransmission in WriteMCP : ");
    Serial.println( i);
  }

  return( i);
}

MotoX

So, could it be likely that it actually is the cable being to long? It would be a shame if 50cm of cable is to long but then again these aren't the most expensive things so..?

You were also talking about a missing 100nF, I havn't put anything like this in the hardware, I don't think I should either but I might as well ask to be certain?

Erdin

A cable of 50cm could be too long, but that depends on the cable.
With good wiring some get 2 meters with I2C.

Since the cable could be a problem, I would certainly recommend a 100nF at the end of it at 5V and GND.

MotoX

Sorry for asking questions most of the people here allready know the answer to, but just so I don't screw anything up. That would be
Arduino 5V -> 100nF -> VCC on sensor
right?
Should it be connected near the Arduino or near the sensor btw?

Erdin

You don't have to be sorry for asking questions. That's okay.

Sine the cable could have some bad influence on the signals, it might also influence the 5V. The 5V could have very short peaks and drops. I mean very short, like nano seconds.
That is why a 100nF should be good at the end of the cable. To smoothen the 5V for the sensor chip.
So the 5V is to the Vcc, just as it was.
The GND to GND, just as it was.
And a capacitor of 100nF is added to the 5V/Vcc and to GND

Go Up