How to send a NACK with wire

I am trying to get a sensor working with I2C in Arduino. I have already used this sensor successfully with another micro. The I2C sequence is basically the same as most others EXCEPT that the datasheet seems to require a NACK prior to ending the transmission. The 4D IDE has a NACK command, and I confirmed that removing the NACK broke the communications. With the NACK command i get data.

The datasheet for the si7021 is
On pg 19 is the sequence with the NACK after receiving 2nd Byte
If I am correct in my assumption, how do I send a NACK from Arduino?

My testing code is below. I never receive any data and also never get the “2nd wire end” reply.

Am I doing something wrong?

#include <Wire.h>

void setup()
  Wire.begin();                // join i2c bus (address optional for master)
  Serial.begin(9600);          // start serial communication at 9600bps

int reading = 0;

void loop()
  // step 1: instruct sensor to read echoes
  Wire.beginTransmission(0x80); // transmit to device 
  Serial.println("wire begin 0x80");                          
  Wire.write(byte(0xE5));      // sets register pointer to the command register (0xE5)  

  if (Wire.endTransmission () == 0)
    Serial.println("1st wire end");
  // step 2: wait for readings to happen

  // step 3: instruct sensor to return a particular echo reading
  Wire.beginTransmission(0x81); // transmit to device in read mode

  // step 4: request reading from sensor
  Wire.requestFrom(0x81, 2);    // request 2 bytes from slave device 

  if(2 <= Wire.available())    // if two bytes were received
    reading =;  // receive high byte (overwrites previous reading)
    reading = reading << 8;    // shift high byte to be high 8 bits
    reading |=; // receive low byte as lower 8 bits
    Serial.println(reading);   // print the reading

  if (Wire.endTransmission () == 0){
    Serial.println("2nd wire end");
  delay(250);                  // wait a bit since people have to read the output :)

You're using the wrong address in beginTransmission. From the Wire library documentiation in the reference section:


There are both 7- and 8-bit versions of I2C addresses. 7 bits identify the device, and the eighth bit determines if it's being written to or read from. The Wire library uses 7 bit addresses throughout. If you have a datasheet or sample code that uses 8 bit address, you'll want to drop the low bit (i.e. shift the value one bit to the right), yielding an address between 0 and 127.

change all your beginTransmissions to

Wire.beginTransmission( 0x40 );

and it should work. Whether you're reading or writing, the address will not change. The Wire library takes care of the R/W bit.

Thank you very much.
That solved it. I didnt know the wire library took care of the read address.
Thanks again