I2C Sensor reading problem, only receiving "255" as a sensor output

Hello all,

With my arduino mega with atmega2560 processor, I'm trying to read data from digital thermopile infrared sensor. It is a 2 channel HID E224 sensor produced by Heimann. Here is the link to the datasheet: http://www.heimannsensor.com/Datasheets/Datasheet%20HID%20E22x%20F1%20F2%20Gx.pdf
I have build the circuitry according to the datasheet and connected the SDA and SCL outputs to my arduino. Datasheet says that it gives SM Bus output, but as I read in the internet, I can use I2C protocol to read it.
Address of the sensor is 0x5A, and when I run a scanner it detecs that a device is connected with that addres. I am supposed to read data from 0x04 address, but I only receive 255 all the time. I couldn't solve the problem.

Here is my code:

#include <Wire.h>

#define HID_address 0x5A
int ch1=0;

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  Wire.begin();
  Serial.print("initiated... \n");
  delay(200);
}

void read_val(){
  Serial.println("-read val-");
  
  Wire.beginTransmission(HID_address);
  Serial.println("-read val-begintransmission-");
  
  Wire.write(0x04);
  Serial.println("-read val-wirewrite-");
  
  Wire.requestFrom(HID_address,4);
  Serial.println("-read val-requestfrom-");
  
  if (Wire.available()) {
    ch1 = Wire.read();
    Serial.println("-read val-ch1read-");
    Serial.println("Ch1 :");
    Serial.println(ch1);
  }
  Wire.endTransmission();
  Serial.println("-read val-endtransmission-");
}

void loop() {
  // put your main code here, to run repeatedly:
  Serial.println("-loop-");
  read_val();
  Serial.println("Ch1: ");
  Serial.println(ch1);
  delay(500);
}

Thanks for the help in advance,

Ersin

You didn't understand, how the Wire library works.

Wire.beginTransaction() starts a new write action, emptying the write buffer. Wire.write then writes to that buffer (it does nothing else!). Wire.endTransaction() writes the content of the buffer to the I2C bus (check the return value of this method to see if the chip received the data).
Wire.requestFrom() reads some bytes from an I2C slave devices. It does not return before the requested amount of data is received or the slave stopped the transfer.

As you can see, your order of these commands does not make sense to the chip because you read before you told it where you want to read.

I look at I2C interactions as a command byte and optional parameters. The ATmega328p needs a buffer filled with I2C data which is then the command byte and its optional parameters. Once the buffer is ready then a write or read may be used. A write will send the I2C start condition, the I2C address, the buffer data, and an I2C stop condition. On the other hand, a read will send the I2C start condition, the I2C address, the buffer data, a repeated start condition, the I2C address (again), the necessary clocks for slave readback, and finally the I2C stop condition.

If you have a Linux computer I have a debug program that works with the ATmega328p. It was built with the twi library that lives under the Wire library. It should install on an Uno and provide something like a command-line interface that can be used to try I2C commands. The serial may take some getting use to since it is aimed at use on an RS-422 multi-drop.

Dear friends thanks for your replies,

I have made the following changes in my code. It works perfectly with my Bosch BME280 sensor, where I am reading the Chip Id register to confirm that my code works, when I read the 0xD0 register of the BME280, it returns 0x60 (I get 0x6000 since Im reading 2 bytes) as I except. So it works, But I still get FFFF with my sensor. I put some debug lines to see if the wire functions are returning correctly. Wire.write writes 1 bytes as expected, and Wire.endTransmission returns 0 as expected. But still reading FFFF.

Here is my new code,

#include <Wire.h>
//#define BME280_ADDRESS    (0x76)
#define HID_ADDRESS       (0x5A)
//uint8_t BME280_REGISTER_CHIPID    = 0xD0;
uint8_t _i2caddr=HID_ADDRESS;
uint8_t HID_REGISTER_C1    = 0x04;
uint8_t  HID_REGISTER_C2   = 0x05;
uint8_t  HID_REGISTER_TEMP = 0x06;
byte transmission_status=255 ; //just giving 1111 1111 to initiate
int written_bytes=0;

void setup() {
  // put your setup code here, to run once:
  Wire.begin();
  Serial.begin(9600);
  
  Serial.println("\n initiated...");
}
//////////////////////////////////////////////////
////////// LOOP //////////////////////////////////

void loop() {
  // put your main code here, to run repeatedly:
  read32(HID_REGISTER_TEMP);
}
//////////////////////////////////////////////////
////////// LOOP //////////////////////////////////



uint32_t read32(byte reg)
{
    uint32_t value=0;

    Wire.beginTransmission((uint8_t)_i2caddr);
    written_bytes=Wire.write((uint8_t)reg);
    Serial.print("number of bytes written: "); Serial.print(written_bytes);
    transmission_status=Wire.endTransmission();
   
    Serial.print("    transmission status: "); Serial.print(transmission_status);
        
    Wire.requestFrom((uint8_t)_i2caddr, (byte)2);

    value = Wire.read();
    value <<= 8;
    value |= Wire.read();

    Serial.print("  Value: ");Serial.println(value, HEX);
    delay(500);
    return value;
}

I'm stucked :confused:

Check the return value from Wire.requestFrom(). It should return the number of bytes read. If it doesn't return 2 in the above case, the sensor chip aborted the I2C communication.
Change your code to save the return values in variables and print them out all together after the complete transaction happened. Putting out the long strings with 9600 baud need a short eternity measured in processor time. The sensor might have "forgotten" the register address in the meantime.

According the the technical note from Heimann the sensor must not have a stop condition on the bus between sending the register address and reading the value. This means you have to change the line

transmission_status=Wire.endTransmission();

to

transmission_status=Wire.endTransmission(false);

Thank you, Wire.endTransmission(false) has solved this issue :))