I2c fails to read or write

Hi!

I am a noob so please bear some of the dumb questions. I have been trying to connect the Omron Thermal sensor(D6T-44L)r. I converted the code provided by them in C to squirrel. I have used two pull up resistors of 10K for SCL and SDA lines. But I keep getting a write error of -1 and and a Read error of null. I am pasting the codes provided by the manufacturer and the ones written by me below. Any help in understanding what the problem is will be really helpful.

Code provided by manufacturer in C:

#include // I2C communication functions extern void I2C_start(); extern void I2C_repeatstart(); extern void I2C_stop(); extern void I2C_send1( char addr8 , char cmd ); extern void I2C_getx( char addr8 , char buff[] , int length ); extern int D6T_checkPEC( char buff[] , int tPEC );

// Global var.
extern char readbuff[35]; extern int tPTAT;
extern int tP[16];
extern int tPEC;
extern int status;
int LOOPLIMIT = 5000;

int D6T_getvalue() {
I2C_start();
I2C_send1( 0x14 , 0x4C ); // 14h = { 0Ah(Addr7) : Write(0b) }
I2C_repeatstart();
I2C_getx( 0x15 , readbuff , 35 ); // 15h
I2C_stop();

if(!D6T_checkPEC(readbuff,34)){
return -1; // error
}
tPTAT = 256readbuff[1] + readbuff[0];
tP[0] = 256
readbuff[3] + readbuff[2];
tP[1] = 256readbuff[5] + readbuff[4];
tP[2] = 256
readbuff[7] + readbuff[6];
tP[3] = 256readbuff[9] + readbuff[8];
tP[4] = 256
readbuff[11] + readbuff[10];
tP[5] = 256readbuff[13] + readbuff[12];
tP[6] = 256
readbuff[15] + readbuff[14];
tP[7] = 256readbuff[17] + readbuff[16];
tP[8] = 256
readbuff[19] + readbuff[18];
tP[9] = 256readbuff[21] + readbuff[20];
tP[10] = 256
readbuff[23] + readbuff[22];
tP[11] = 256readbuff[25] + readbuff[24];
tP[12] = 256
readbuff[27] + readbuff[26];
tP[13] = 256readbuff[29] + readbuff[28];
tP[14] = 256
readbuff[31] + readbuff[30];
tP[15] = 256*readbuff[33] + readbuff[32];
tPEC = readbuff[34];
return 1;
}

My Code:
//------------------------------------------------------------------------------ class TempSensor {
_i2c  = null;

constructor(i2c) {
_i2c = i2c;
}
//readbuff= [];
//tPTAT = null;
//tP=[];
//tPEC = null;

function D6T_getvalue() {
local write=_i2c.write(0x14 , “0x4C”);
server.log(“Error” + write);
//writebuff=_i2c.read(0x14,"",1);
//server.log(“Write Value”+writebuff);
local readbuff=_i2c.read(0x15,"\x4C", 35); //try 0x16 and 0x15 as well, there might be a error in the datasheet
server.log(“Awesome”+readbuff);
tPTAT = 256readbuff[1] + readbuff[0];
tP[0] = 256
readbuff[3] + readbuff[2];
tP[1] = 256readbuff[5] + readbuff[4];
tP[2] = 256
readbuff[7] + readbuff[6];
tP[3] = 256readbuff[9] + readbuff[8];
tP[4] = 256
readbuff[11] + readbuff[10];
tP[5] = 256readbuff[13] + readbuff[12];
tP[6] = 256
readbuff[15] + readbuff[14];
tP[7] = 256readbuff[17] + readbuff[16];
tP[8] = 256
readbuff[19] + readbuff[18];
tP[9] = 256readbuff[21] + readbuff[20];
tP[10] = 256
readbuff[23] + readbuff[22];
tP[11] = 256readbuff[25] + readbuff[24];
tP[12] = 256
readbuff[27] + readbuff[26];
tP[13] = 256readbuff[29] + readbuff[28];
tP[14] = 256
readbuff[31] + readbuff[30];
tP[15] = 256*readbuff[33] + readbuff[32];
tPEC = readbuff[34];
return 1;
}
}
// configure i2c bus
hardware.i2c12.configure(CLOCK_SPEED_50_KHZ);
// create TempSensor object
tempSensor <- TempSensor(hardware.i2c12);
function main(){
server.log(tempSensor.D6T_getvalue());
server.log(“tP0”+tP[0]+“tP1”+tP[1]+“tP2”+tP[2]+“tP3”+tP[3]+“tP4”+tP[4]+“tP5”+tP[5]+“tP6”+tP[6]+“tP7”+tP[7]+“tP8”+tP[8]+“tP9”+tP[9]+“tP10”
+tP[10] +“tP11”+tP[11]+“tP12”+tP[12]+“tP13”+tP[13]+“tP14”+tP[14]+“tP15”+tP[15]+“tPTAT”+tPTAT+“tPEC”+tPEC);
imp.wakeup(30,main);
}
main();

The datasheet you linked to is just an app note. I looked up the datasheet on omron and sadly it is not much better.

http://www.omron.com/ecb/products/pdf/en-d6t.pdf

Have you determined if there is anything you need to write to the device? I couldn’t see any registers that need to be adjusted so perhaps you only need the i2c.read command and never any .write commands.

you could try

server.log(typeof(readbuff));//to find the type of data returned

Hey! The app note mentioned that to read first I had to write to the address 0x14 that’s why I tried that. But I tried removing it like you suggested but that doesn’t help either. I Tried the typeof(readbuff) bit and it’s giving Null as the output. :frowning:

@mjkuwp94 One more question. Sometimes while writing to the sensor, I get a write error of -1 and at other times an error -2. What is difference between the two? The documentation of the imp only says that non zero return means there’s an error!

What are you doing about voltage translation of the I2C lines? The Omron device is 5V and the Imp is 3v3. See Figure 6.2 in the Omron app note.

This is what the Imp design guide has to say about 5V tolerance on the Imp side:
2. The imp is not 5V tolerant. Your design should not expose the imp to any voltage greater than VDD on the imp. Consult the imp spec sheet for more information on electrical characteristics and absolute maximum ratings.

First you have to shift the i2c adress. The imp quotes these as 8 bit and the datasheet shows them as 7 bit. And you also have to use this Case to connect the D6T to the imp:

Let me try to use this and see whether the problem persists or not.

BTW @chrischi and @deonsmt thanks a lot. I forgot that imp is not 5V tolerant

I think the imp has a higher level library that takes care of some of what you see in the C code. The imp i2c.read command has a place in which to declare the addressof the device and the sub address (the register you want data from). so it seems that i2c.read on the imp will take care of it.

The nominal address of the device seems to be 0x0A = B1010
left shift by 1 and add 0 in the 8th bit is
B10100 = 0x14

left shift by 1 and add 1 in the 8th bit is
B10101 = 0x15

so this makes sense they would tell you to write 14h and 15h

I don’t know the reason but I guess you did have it correct. The device wants to have command 0x4C written to it before making a read request.

here is my guess. I changed the string that you write, and changed read command to “”

`
local write=_i2c.write(0x14 , “\x4C”);
server.log("result (0 means ok) : " + write);

local readbuff=_i2c.read(0x15,"", 35); //no command for reading

server.log("buffer is " + typeof(readbuff));
server.log("length is " + readbuff.len());`

Hey @mjkuwp94! Thanks a lot for checking out my code. But as others pointed out, I think I’m not able to send sufficient enough voltage for the sensor to differentiate between the high and low bits. So I’m going to try and use a level shifter IC in the middle and see what happens. Thanks again :slight_smile:

Two things:

  • if you want to write the byte 0x4c, the string is “\x4c”. You’re sending “0” “x” “4” “C” which I don’t believe is what you wanted.
  • You don’t need to alter the address for read, the imp does it so stick with 0x14.

Hey @hugo! You were absolutely right about sending “\x4C” but somehow for reading I still had to use 0x15, 0x14 didn’t work. Also there’s one more thing I observed. Whenever I’m trying to process(multiply by an integer) the output received from the sensor. I’m getting an error. Do we have a standard function to convert a string into an integer in Squirrel?

If you are trying to convert a string like “1324” to an integer, you can use

local test = “1234”;

local intVal = test.tointeger();

Can I replace the test variable by an array member. for instance can I directly write something like this:
intVal = 26*test[1].tointeger();

@deonsmt that worked! Thanks, that was a neat solution.

Hey Guys! I finally got all the components I needed to rework on this. I even decided to get an Arduino and test the sensor out on it. It’s working perfectly fine on the Arduino. But I’m still getting a Write error of -2 with the imp. I am using the PCA9517D level shifter and pull up resistors of 4.4K on the sensors side(which worked for the arduino) and 3.3K on the imp side.
Below are both my imp codes and arduino codes:
`
//Arduino Code:
#include <Wire.h>
int rbuf [ 35 ] ;//the buffer storing all of the data we read from the sensor (2 bytes per cell of the column of 8, plus two bytes for the reference temperature and one for the packet error check code)
int TDATA [ 16 ] ;//contains temperature data for each cell of the sensor’s matrix (each being two bytes)
int T_PTAT;//stores the reference temperature recorded from the thermal sensor ( see http://www.mouser.com/pdfdocs/D6T01_ThermalIRSensorWhitepaper.pdf page 8)

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

void loop(){
readTemperatures();
}

void readTemperatures(){

String buf = "";
int  i = 0 ;
Wire.beginTransmission(0x0A);
Wire.write(0x4C);

int writeStatus = Wire.endTransmission();
if(writeStatus != 0){
	Serial.println("Writing failed");
	return;
}

Serial.println(“writing succeeded”);
delay(100);
Wire.requestFrom(0x0A, 35);
for (i = 0 ; i < 35 ; i++) {
rbuf [i] = Wire.read();
}
T_PTAT = (rbuf[0]+(rbuf[1] << 8));
for (i = 0 ; i < 16 ; i++) {
TDATA [i] = (rbuf [(i * 2 + 2)] + ( rbuf [(i * 2 + 3)] << 8 ));//offset by 2 because T_PTAT occupies the first 2 bytes
buf = buf + (TDATA[i]);
//I would have expected not to end the string with a comma,
//but if I don’t add a trailing comma, the split function in the Processing sketch
//won’t get the last value as an array element. C++ remains a mystery to me.
buf = buf + (",");
}
Serial.println(buf);
Serial.println(T_PTAT);

}

//Imp Code:
//------------------------------------------------------------------------------
class TempSensor {

_i2c  = null;

constructor(i2c) {
_i2c = i2c;
}

function D6T_getvalue() {
local write=_i2c.write(0x14 , “0x4C”);
imp.sleep(0.5);
server.log(“Result: (0 means ok)” + write);
local readbuff=_i2c.read(0x15,"", 35);
//server.log("length is " + readbuff.len());
server.log(typeof(readbuff));
tPTAT = 256readbuff[1] + readbuff[0];
tP[0] = 256
readbuff[3] + readbuff[2];
tP[1] = 256readbuff[5] + readbuff[4];
tP[2] = 256
readbuff[7] + readbuff[6];
tP[3] = 256readbuff[9] + readbuff[8];
tP[4] = 256
readbuff[11] + readbuff[10];
tP[5] = 256readbuff[13] + readbuff[12];
tP[6] = 256
readbuff[15] + readbuff[14];
tP[7] = 256readbuff[17] + readbuff[16];
tP[8] = 256
readbuff[19] + readbuff[18];
tP[9] = 256readbuff[21] + readbuff[20];
tP[10] = 256
readbuff[23] + readbuff[22];
tP[11] = 256readbuff[25] + readbuff[24];
tP[12] = 256
readbuff[27] + readbuff[26];
tP[13] = 256readbuff[29] + readbuff[28];
tP[14] = 256
readbuff[31] + readbuff[30];
tP[15] = 256*readbuff[33] + readbuff[32];
tPEC = readbuff[34];
return 1;
}
}
// configure i2c bus
hardware.i2c89.configure(CLOCK_SPEED_100_KHZ);
// create TempSensor object
tempSensor <- TempSensor(hardware.i2c89);
function main(){
server.log(tempSensor.D6T_getvalue());
server.log(“tP0”+tP[0]+“tP1”+tP[1]+“tP2”+tP[2]+“tP3”+tP[3]+“tP4”+tP[4]+“tP5”+tP[5]+“tP6”+tP[6]+“tP7”+tP[7]+“tP8”+tP[8]+“tP9”+tP[9]+“tP10”
+tP[10] +“tP11”+tP[11]+“tP12”+tP[12]+“tP13”+tP[13]+“tP14”+tP[14]+“tP15”+tP[15]+“tPTAT”+tPTAT+“tPEC”+tPEC);
imp.wakeup(1,main);
}
main();
`

Please take a look and see if you can help me in any form.

Hi everyone,
Good day, Im new to this forum and new to C++ language too.

Im trying to compile Code provided by Omron for D6T MEM Sensor. I didnot connected any Sensor yet but during compilation I m receiving following error.

Compiler: Default compiler
main.cpp: In function int D6T_getvalue()': main.cpp:20: error: invalid conversion fromchar*’ to char' main.cpp:20: error: initializing argument 1 ofint D6T_checkPEC(char, int)’

main.cpp:20: error: If' undeclared (first use this function) main.cpp:20: error: (Each undeclared identifier is reported only once for each function it appears in.) main.cpp:21: error: expected;’ before ‘{’ token
main.cpp: At global scope:
main.cpp:46: error: ISO C++ forbids declaration of measure' with no type main.cpp: In functionint measure()’:
main.cpp:47: error: n' undeclared (first use this function) main.cpp:49: error:status’ undeclared (first use this function)
main.cpp:51: error: LOOPLIMIT' undeclared (first use this function) main.cpp:52: error:If’ undeclared (first use this function)

main.cpp:52: error: expected ;' before '{' token main.cpp:56: error:print’ undeclared (first use this function)
main.cpp:56: error: expected ;' before "f" main.cpp:56: error: stray '\\147' in program main.cpp:58: error: stray '\\148' in program main.cpp:60: error: expected}’ at end of input

Any Help would be highly appreciated.

Many thanks

Please help!

Sorry, this isn’t the right forum to be asking about C code.