MIT-i Programming Help with Arduino I2C & Sensirion Temp Sensor

Don't have one but I was looking at the data sheet. There are a couple of issues that I can see...try this snippet and if it works, you can clean it up - figure out what mode you want to use, calculate a checksum, mess with the status, add pull up resistors and that kind of thing.

#include <Wire.h>
int address1 = 0x4A; // hex address of sensor 1 with ADDR to GND

void setup() {
Serial.begin(9600);
Wire.begin(); // create a wire object
Wire.beginTransmission(address1); //start the communication with IC with the address xx
Serial.println("begin");
// set up for single shot mode / clock stretching /.5/sec max frequency
Wire.write(byte(0x2C));
Wire.write(byte(0x06));
Wire.endTransmission();
Serial.println("mode set");
//end transmission
}

void loop() {
Serial.println(" wait..");
delay(1000);
// request the 3 bytes of measurement data 16 bit temp value plus checksum
Wire.requestFrom(address1, 3);
byte byte1=Wire.read(); // msb of temp
byte byte2=Wire.read(); // lsb of temp
byte byte3=Wire.read(); // chksum
unsigned short tC= (byte1<<8) + byte2;
float temperatureC= -45 + 175 * (tC/65536-1);
Serial.print("Temperature (C) = ");
Serial.println(temperatureC);
}

edit: 8 not 16 duh?
 
Last edited:

RK37

Joined Jun 26, 2015
677
Hey Ryan,

As djsfantasi said, you want to use the first two bytes from the sensor, not the first two bits. The raw temperature data from the sensor is a 16-bit number. The first received byte is bits 15 to 8, and the second received byte is bits 7 to 0. You can ignore the third byte, which is just for error detection.

The number that you're displaying doesn't make sense. If you plug it into the two conversion formulas, you get unrealistic values (about -44C or -48F). The raw sensor value would have to be much larger to produce a realistic temperature. The fact that all your values are less than 255 indicates that you are displaying only one byte. The value changes when you apply heat because you are actually looking at part of the temperature reading, but the temperature is not correct because you have only one of the two bytes.

Your code has the following:

int c = Wire.read();

Does this function realize that it has to take two bytes and combine them into one 16-bit variable? Or is it just taking one of the bytes and storing that in the variable c?
 

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
Thanks, Robert @RK37. I knew something seemed a little odd about the numbers that it was returning. Supposedly, the function should know to take two bytes because of Wire.requestFrom(); but it doesn't seem that way. Maybe I will have luck if I add another Wire.read() statement. I'm hoping to have Thursday off to finalize everything and write the entire project. I will continue trying to get proper readings until then.
 

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
Thank you, @Raymond Genovese !

I haven't had a chance to run this code yet, but it seems as though the multiple Wire.read statements you have will help me in returning the proper value from the sensor. I will keep everybody updated. Thanks so much!
 

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
Hello, everyone! We are almost there. I have been playing with @Raymond Genovese code for the past two nights but haven't found a final solution but we are close. Right now, using the Fahrenheit equation, I receive a value of about -266*F at room temperature. Of course, this isn't right or I'd be dead. How can I tell if I am actually receiving the two bytes from the sensor? That seems to be the leading issue as @RK37 mentioned. I will be here most of the day tinkering until I get it if anyone has any ideas. I couldn't have gotten this far without you all!

**************************************************
C:
#include <Wire.h>
int address1 = 0x4A; // hex address of sensor 1 with ADDR to GND

void setup() {
  Serial.begin(9600);
  Wire.begin(); // create a wire object
  Wire.beginTransmission(address1); //start the communication with IC with the address xx
  Serial.println("begin");
  // set up for single shot mode / clock stretching /.5/sec max frequency
  Wire.write(byte(0x2C));
  Wire.write(byte(0x06));
  Wire.endTransmission();
  Serial.println("mode set");
  //end transmission
}

void loop() {
  Serial.println(" wait..");
  delay(1000);
  // request the 3 bytes of measurement data 16 bit temp value plus checksum
  Wire.requestFrom(address1, 3);
    byte byte1 = Wire.read(); // msb of temp
    byte byte2 = Wire.read(); // lsb of temp
    byte byte3 = Wire.read(); // chksum
    unsigned short tC = (byte1>>8) + byte2;
    float temperatureF = (-49 + 315)  * (tC / 65536 - 1);
    Serial.print("Temperature (F) = ");
    Serial.println(temperatureF);
    //Wire.endTransmission();
  }
 
hang on let me look at the formula again

hmmm you have
unsigned short tC = (byte1>>8) + byte2;

I had
unsigned short tC= (byte1<<8) + byte2;
also can you try

float temperatureC= -45 + 175 * (tC/65536-1) first

...and remember My Dear Aunt Sally
 
Last edited:

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
@Raymond Genovese Whoops, that wasn't supposed to be left in there! Using your original code I receive a value of -220*C, but what's throwing me off is that the value doesn't change when I apply heat to the sensor, as opposed to my most recent code before, which also wasn't the correct value, but at least detected a temperature change. Thank you for your generous help.

Upon printing the bytes I receive the following:

Byte1 = 102
Byte2 = 223
Byte3 = 164

but now, upon reset, I receive:

Byte1 = 0
Byte2 = 0
Byte3 = 129
 
@Raymond Genovese Whoops, that wasn't supposed to be left in there! Using your original code I receive a value of -220*C, but what's throwing me off is that the value doesn't change when I apply heat to the sensor, as opposed to my most recent code before, which also wasn't the correct value, but at least detected a temperature change. Thank you for your generous help.

Upon printing the bytes I receive the following:

Byte1 = 102
Byte2 = 223
Byte3 = 164

but now, upon reset, I receive:

Byte1 = 0
Byte2 = 0
Byte3 = 129

You may need to set the mode every time before a read for single shot. Try moving these lines out of set up and into the main loop before the read.

Wire.beginTransmission(address1); //start the communication with IC with the address xx
Serial.println("begin");
// set up for single shot mode / clock stretching /.5/sec max frequency
Wire.write(byte(0x2C));
Wire.write(byte(0x06));
Wire.endTransmission();
Serial.println("mode set");

I wish I had one here. Can you post the complete program you use after this change and the bytes?
 

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
@Raymond Genovese Thank you, this is what it looks like now. Now the bytes constantly change values but the temperature calculation remains the same.
********************************
C:
#include <Wire.h>
int address1 = 0x4A; // hex address of sensor 1 with ADDR to GND

void setup() {
  Serial.begin(9600);
  Wire.begin(); // create a wire object
  //end transmission
}

void loop() {

  Wire.beginTransmission(address1); //start the communication with IC with the address xx
  Serial.println("begin");
  // set up for single shot mode / clock stretching /.5/sec max frequency
  Wire.write(byte(0x2C));
  Wire.write(byte(0x06));
  Wire.endTransmission();
  Serial.println("mode set");

/********************************/
  Serial.println(" wait..");
  delay(1000);
  // request the 3 bytes of measurement data 16 bit temp value plus checksum
  Wire.requestFrom(address1, 3);
    byte byte1 = Wire.read(); // msb of temp
    Serial.println(byte1);
    byte byte2 = Wire.read(); // lsb of temp
    Serial.println(byte2);
    byte byte3 = Wire.read(); // chksum
    Serial.println(byte3);
    unsigned short tC = (byte1>>8) + byte2;
    float temperatureC= -45 + 175 * (tC/65536-1);
    Serial.print("Temperature (C ) = ");
    Serial.println(temperatureC);
    //Wire.endTransmission();
  }
*************************
The "0" "0" "129" are the first bytes after I reset the device.

Screen Shot 2017-02-16 at 9.53.18 AM.png
 
@Raymond Genovese Thank you, this is what it looks like now. Now the bytes constantly change values but the temperature calculation remains the same.
********************************
C:
#include <Wire.h>
int address1 = 0x4A; // hex address of sensor 1 with ADDR to GND

void setup() {
  Serial.begin(9600);
  Wire.begin(); // create a wire object
  //end transmission
}

void loop() {

  Wire.beginTransmission(address1); //start the communication with IC with the address xx
  Serial.println("begin");
  // set up for single shot mode / clock stretching /.5/sec max frequency
  Wire.write(byte(0x2C));
  Wire.write(byte(0x06));
  Wire.endTransmission();
  Serial.println("mode set");

/********************************/
  Serial.println(" wait..");
  delay(1000);
  // request the 3 bytes of measurement data 16 bit temp value plus checksum
  Wire.requestFrom(address1, 3);
    byte byte1 = Wire.read(); // msb of temp
    Serial.println(byte1);
    byte byte2 = Wire.read(); // lsb of temp
    Serial.println(byte2);
    byte byte3 = Wire.read(); // chksum
    Serial.println(byte3);
    unsigned short tC = (byte1>>8) + byte2;
    float temperatureC= -45 + 175 * (tC/65536-1);
    Serial.print("Temperature (C ) = ");
    Serial.println(temperatureC);
    //Wire.endTransmission();
  }
*************************
The "0" "0" "129" are the first bytes after I reset the device.

View attachment 120675
unsigned short tC = (byte1>>8) + byte2;

make that

tC=(byte1<<8) +byte2;

what does that do to the values?
 
ok, I think I have it. Can you please cut and paste these lines and run. Tell me the values heating up and cooling off.

#include <Wire.h>
int address1 = 0x4A; // hex address of sensor 1 with ADDR to GND
unsigned short tC;
byte byte1, byte2, byte3;
float temperatureC;

void setup() {
Serial.begin(9600);
Wire.begin();
//end transmission
}
void loop() {
Serial.println(" wait..");
delay(1000);
// set up for single shot mode / clock stretching /.5/sec max frequency
Wire.beginTransmission(address1); //start the communication with IC with the address xx
Wire.write(byte(0x2C));
Wire.write(byte(0x06));
Wire.endTransmission();
// request the 3 bytes of measurement data 16 bit temp value plus checksum
Wire.requestFrom(address1, 3);
byte1=Wire.read(); // msb of temp
byte2=Wire.read(); // lsb of temp
byte3=Wire.read(); // chksum
tC= (byte1<<8) + byte2;
temperatureC= -45 + 175 * ((float)tC )/ 65536 -1 ;
Serial.print("Temperature (C) = ");
Serial.println(temperatureC);
}

edit: forgot to declare byte3
 

RK37

Joined Jun 26, 2015
677
The numbers shown in Ryan's most recent post correspond to realistic temperatures. Nice work, guys. You're getting good data from the sensor, and that's by far the most difficult part.

If you're still having math issues, I would try this for the calculation statement:

temperatureC = -45 + (175 * (float)tC/65535);
 
The numbers shown in Ryan's most recent post correspond to realistic temperatures. Nice work, guys. You're getting good data from the sensor, and that's by far the most difficult part.

If you're still having math issues, I would try this for the calculation statement:

temperatureC = -45 + (175 * (float)tC/65535);

Yeah, I think that's in the code I posted ok unless I have the 65536-1 wrong in which case yours is more accurate. I had forgotten the conversion to float. Would you be willing to code the checksum check? Those make my head hurt RK
 

Thread Starter

Ryan Jones

Joined Aug 27, 2016
35
@Raymond Genovese @RK37

Sorry, took a quick breakfast break. It seems as though that worked!!! Attached are the readings, which seem accurate for the temperature of my house! Would you agree? I used Raymond's code exactly.

Screen Shot 2017-02-16 at 11.02.43 AM.png
 
Last edited:
@Raymond Genovese @RK37

Sorry, took a quick breakfast break. It seems as though that worked!!! Attached are the readings, which seem accurate for the temperature of my house! Would you agree?

View attachment 120679
Good deal. Use the formula RK posted. Mine gives almost one degree too cold - but then I am not an engineer so I should not be expected to do addition and subtraction accurately :) You should be able to do the F conversion in an analogous manner. You should probably do a check on the checksum (that's the third value).

Ray
 

djsfantasi

Joined Apr 11, 2010
9,163
@Raymond Genovese Thank you for all of your help! You are a life saver. How do I check a checksum?
It depends. You need to know the slgorithm used to generate it. There are several possibilities. If you can find the algorithm, you use the values that were read and re-calculate it. If the calculated number is the same as the transmitted number, life is good.
 
Top