Introduction: I2C Talking to a Temperature Sensor - EMC1182

About: We sell DIY kits for electronics. Please check out our website: http://www.jouletime.com/

In our last Instructable, we showed you how to use a simple Arduino sketch to check if your device was connected properly.

How to Get Started With I2C

This time we will walk you through connecting a temperature sensor. And then some sample code to get a temperature measurement.

You will need:

1 Arduino Uno or similar controller

2. An EMC1182 on a breakout board

3. Breadboard

4. A few wires

5. A 1uf and 0.1uF capacitor are optional.

Step 1: Making the Connections

The EMC1182 - Dual Temperature Sensor

The EMC1182 is a curious chip. It runs on 3.3V max. but it has data pins that are 5V tolerant. So you have to use 3.3V to power the chip, but you can use regular I2C 5V for communication.

Technically it uses the SMBus protocol which is almost exactly identical to I2C. You can mostly ignore the difference.

DFN-8 Breakout Board

This is a DFN-8 part that is a bother to find a breakout board. We hand etched our first one. To make this easier for us and others, we are running a Kickstarter for a bunch of breakout boards at a great price. That campaign has ended, but if you are still interested then send us an email. You can contact us through Instructables, Kickstarter, or our website www.jouletime.com. Check out the Kickstarter here.

https://www.kickstarter.com/projects/1257390142/ba...

Basic and Advance Breakout Boards - Plus More

Simple Four Wire Connection, 2 Power & 2 Data

When connecting this part you first run 3.3V from the Arduino over to the breadboard. Then you run ground. The evaluation board from Microchip used both a 1uF and 0.1 uF capacitor between power and ground. We show the same setup in our photo.

  1. 3.3 V - Arduino to pin 1 - EMC1182.
  2. Ground - Arduino to pin 5 - EMC11882.
  3. A5 - Arduino to pin 8 - EMC1182.
  4. A4 - Arduino to pin 7 - EMC1182.

I told you that wiring up these parts was easy.

Step 2: Options

Beyond the Basics

There is an option for an external sensor. The trick here is that is uses a bipolar transistor/diode to act as the sensor.

In a bipolar transistor, the pn junction acts like a diode. As a diode heats up, the electrical characteristics change. The EMC1181 is able to measure this change and translate it into an accurate temperature reading, very cool trick.

So once you get everything working, you can later add a transistor for a remote temperture sensor.

The chip has a pin for sending an alarm if a maximum temperature is reached. Using this will depend on what type of circuit you are building.

There is also a register for adjusting the temperature to calibrate the output.

If you are not sure how to do this, we recommend reading the datasheet on the evaluation board. It has a lot of good tips on how to use some of the many features.

Step 3: Test First With I2C Scanner to See If It Is Working

You can run the I2C scanner software that we shared in our last instructable. The temperature sensor will show up at 0x4C. We have already prepared the scanner to look for this device.

We are using the EMC1182-1 version of the chip. Its address is hard coded at 1001100b. The EMC1182-2 version is hard coded at 1001101b. You could have one of each version in your circuit and you could talk to them both seperately by selecting which address to send to.

The EMC1182-A has a programable address for more flexibility.

The crazy thing is the device address is only 7 bits long. That is one bit short of a byte. You have to add a beginning zero to the address to make it 8 bits long. That makes the address change from 1001100b to 01001100b (binary number) or 0x4C (hexadecimal). The Arduino software will then toggle that leading bit high or low depending on if you are reading or writing to the sensor. That is how it works for the Arduino. It may be different if you use other software.

Step 4: I2C and Registers

The information on your sensors will normally be stored in a register. Each register will have its own address.

For communication you start off by sending the device address, a.k.a. slave address. For our part it was 0x4C. Then you send the address of the register you want to read. Then you end transmission.

The chip is now set to send information from the register that you picked. When you do your next transmission it will use this address.

The requestfrom command is how you read the data. You give it the slave address and then tell it how many bytes of data to read back. The sketch uses a while loop to read off each byte of data. For this chip, the temperature is a single byte.

If you don’t understand registers, try our instructable for registers.

https://www.instructables.com/id/How-to-Use-Comput...

Beyond the Wire Library

The offical Wire library from Arduino did not used to work with all I2C devices. Wayne from DSS Circuits wrote his own version Wayne’s I2C library

So we started using that version instead. Our Github repository has a version of the same sketch written using the I2C library. You will have to install the I2C library to try out this other sketch.

Step 5: Here Is the Code

You can find our code here:

EMC1182 Sketch

Here is a copy and paste of the code. Since it is code, the instructable editor confuses it with HTML and it doesn’t copy well. You should use the Github link.

//This sketch was written by Frank Fox for JouleTime.

//Find us at http://www.jouletime.com

//Shop our listings on Ebay at http://www.jouletime.com//Shop


/* This sketch will demonstrate how to use the Dual Channel Temperature Sensor, EMC1182, from Microchip The sensor is accurate to +/-1 degree Celsius with Beta compensation to correct readings. Include both an internal and external temperature sensor. The external temperature sensor uses a diode/transitor with an optional capacitor filter. This device includes numerous options, high/low limits, Beta configuration, Diode Ideality Factor, etc. The device is compatible with 1.8V SMBus and I2C communications. We will use a fixed slave address version, EMC1182-1. For this device, the slave address is 1001100b, (0x4C). Otherwise the device address is selected by the value of resistor connected. This device has multiple operation registers, 0x00 to 0xFF. Write Mode: Write mode must include three bytes of information: Write Slave Address, Control/Operating Register, Data for Control/Operating Register Some of the important control/operating register addresses are: 0x00 Internal Diode Data High Byte. 0x01 External Diode Data High Byte. 0x03 Configuration, controls general operation. mirrored 0x09. 0x04 Conversion Rate, how often the reading is updated, mirrored 0x0A. 0x10 External Diode Data Low Byte, only 3 MSB. 0x25 External Diode Beta Configuration. (default 0x08) 0x27 External Diode Ideality Factor. (default 0x12) 0x29 Internal Diode Data Low Byte, only 3 MSB. Read Mode: Send Slave, Send Control Register, Read Slave Address, and how many data bytes. There is no auto increment after reading a register. You must send the register address everytime you want to look at a new register. Otherwise it will repeat reading the same over and over. Before read, you can select an operating register by writing the register address first. If the address is already set then read can happen immediately. */

#include //Include the I2C/TWI (two wire interface)library with your sketch.

#define TempSensor 0x4C byte i=0;

void setup()/* Perform these actions: 1. Prepare and start Serial Monitor. 2. Write register address and print out to serial monitor the values in the registers. */ { Serial.begin(9600); // 1. set up Serial Monitor to send data to screen. Wire.begin(); while (!Serial) { // Wait for Serial Monitor to start. Delay to allow Leonardo type boards to connect to serial port. ; } // 2. Write registers address, then read register data. delay(3000); // wait 3 seconds i=0; Serial.print("This is Internal Diode Data High Byte, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // line return i++; Serial.print("This is External Diode Data High Byte, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // line return i++; Serial.print("This is Status, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // line return i++; Serial.print("This is Configuration, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // this creates a line return i++; Serial.print("This is Conversion Rate, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x06."); Serial.println(); // this creates a line return i++; Serial.print("This is Internal Diode High Limit, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x55."); Serial.println(); // this creates a line return i++; Serial.print("This is Internal Diode Low Limit, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // this creates a line return i++; Serial.print("This is External Diode High Limit, High Byte, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x55."); Serial.println(); // this creates a line return i++; Serial.print("This is External Diode Low Limit, High Byte, "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // this creates a line return Serial.print("This is External Diode Beta Configuration, "); Serial.print(GetTempRegister(0x25), HEX); // Serial.print(", default 0x08."); Serial.println(); // this creates a line return Serial.print("This is External Diode Ideality Factor, "); Serial.print(GetTempRegister(0x27), HEX); // Serial.print(", default 0x12."); Serial.println(); // this creates a line return Serial.print("This is Internal Diode Data Low Byte, only 3 MSB, "); Serial.print(GetTempRegister(0x29), HEX); // Serial.print(", default 0x00."); Serial.println(); // this creates a line return /* i++; Serial.print("This is Internal Diode Low Limit (Mirror) "); Serial.print(GetTempRegister(i), HEX); // the value is displayed Serial.print(", default 0x00."); Serial.println(); // this creates a line return */ delay(2000); // 2 second delay until repeat} void loop(){ // Read the internal and external temperature, and Send the data to serial monitor. i=0; int temp=0; Serial.println(); // this creates a line return Serial.println(); // this creates a line return Serial.print("This is Internal Diode, High Byte "); Serial.print(GetTempRegister(i), DEC); // the decimal value is displayed Serial.print("C, or "); temp=GetTempRegister(i)*9/5+32; //Convert to Fahrenheit Serial.print(temp, DEC); Serial.print("F. "); Serial.println(); // this creates a line return i++; Serial.print("This is External Diode, High Byte "); Serial.print(GetTempRegister(i), DEC); // the decimal value is displayed Serial.print("C, or "); temp=GetTempRegister(i)*9/5+32; //Convert to Fahrenheit Serial.print(temp, DEC); Serial.print("F. "); Serial.println(); // this creates a line return delay(4000);// 4 second delay}

// this function moves the register pointer then reads the databyte GetTempRegister(byte Register){ Wire.beginTransmission(TempSensor); // send slave device address // NOTE: All write() statements send data to a buffer, actual writing is initiated by endTransmission Wire.write(Register); // send the register address. Wire.endTransmission(); // end the setup. byte data = 0 ; // variable to return the data Wire.requestFrom(TempSensor, 1); // send the slave address, and specify how may bytes of data to read while (Wire.available()) { data=Wire.read(); //keep reading data while available, we asked for 13 bytes(0-12). } return data;}

Step 6: Open Serial Monitor

When you run this sketch it sends the information to the serial monitor. You have to open the screen after you upload the sketch to your Arduino.

The sketch will read back information in the various registers. The obvious one is the internal temperature. This is the actual temperature of the chip itself. You can put your finger on it and warm it up to see the reading change. (Make sure you are grounded and not electrically charged when you touch this part.)

This is just a basic sketch. You can add alarms and other things if needed in your design.

Have fun changing the code to tap into other features. Drop us a note if you do and share your awesome improvements.