tutorial_ arduino and the i2c bus - part two

Upload: sigid-ariewibowo

Post on 14-Jan-2016

64 views

Category:

Documents


3 download

DESCRIPTION

Tutorial_ Arduino and the I2C Bus - Part Two

TRANSCRIPT

  • tronixstuff fun and learning with electronics

    HomeTronixlabsArduino Tutorials Kit ReviewsProjectsReviewsAboutContact Us

    Categorized | 24LC256, arduino, I2C, learning electronics, lesson, microcontrollers, PCF8574, tutorial

    Tutorial: Arduino and the I2C bus Part TwoPosted on 29 October 2010. Tags: 24lc256, 24lc512, arduino, bus, digital, eeprom, example, expander, guide, guides, i/o, i2c, instruments,lesson, lessons, microchip, PCF8547, PCF8547N, texas, TI, tronixstuff, tutorial, tutorials

    Part two of our Arduino and I2C bus tutorial.

    [Updated 28/11/2014]

    Today we are going to continue learning about the I2C bus and how it can work for us. If you have not already, please read andunderstand the first I2C article before continuing.

    First of all, there are some limitations of I2C to take into account when designing your projects. One of these is the physical length of theSDA and SCL lines. If all your devices are on the same PCB, then there is nothing to worry about, however if your I2C bus is longer thanaround one metre, it is recommended that you use an I2C bus extender IC. These ICs reduce electrical noise over the extended-lengthbus runs and buffer the I2C signals to reduce signal degradation and chance of errors in the data. An example of such an IC is the NXPP82B715 (data sheet). Using a pair of these ICs, you can have cable runs of 20 to 30 metres, using shielded twisted-pair cable. Below is agood example of this, from the aforementioned NXP data sheet:

    Several applications come to mind with an extended I2C bus, for example remote temperature monitoring using the the STMicroelectronics CN75 temperature sensor from part one; or controlling several I/O ports using an I2C expander without the expense orworry of using a wireless system. Speaking of which, lets do that now

    A very useful and inexpensive part is the PCF8574 I/O expander (data sheet.pdf). This gives us another eight outputs, in a very similarmethod to the 74HC595; or can be used as eight extra inputs. In fact, if you were to use more than one 74HC595 this IC might bepreferable, as you can individually address each chip instead of having to readdress every IC in line as you would with shift registers. Sohow do we do this? First, lets consult the pinout:

    1 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • There should not be any surprises for you there. A2~A0 are used to select the last three bits of the device address, P0~P7 are the I/Opins, and INT is an interrupt output which we will not use. To address the PCF8574 we need two things, the device address, and a byte ofdata which represents the required output pin state. Huh? Consider:

    So if we set pins A0 to A2 to GND, our device address in binary will be 0100000, or 0x20 in hexadecimal. And the same again to set theoutput pins, for example to turn them all on we send binary 0 in hexadecimal which is 0; or to have the first four on and the second fouroff, use 00001111 which is Ox0F. Hopefully you noticed that those last two values seemed backwards why would we send a zero toturn all the pins on?

    The reason is that the PCF8574 is a current sink. This means that current runs from +5v, through into the I/O pins. For example, an LEDwould have the anode on the +5V, and the cathode connected to an I/O pin. Normally (for example with a 74HC595) current would runfrom the IC, through the resistor, LED and then to earth. That is a current source. Consider the following quick diagram:

    In the example above, please note that the PCF8574N can take care of current limitation with LEDs, whereas the 74HC595 needs acurrent-limiting resistor to protect the LED.

    Luckily this IC can handle higher volumes of current, so a resistor will not be required. It sounds a bit odd, but like anything is easy onceyou spend a few moments looking into it. So now lets use three PCF8574s to control 24 LEDs. To recreate this masterpiece of blinkinessyou will need:

    Arduino Uno or compatible boardA large solderless breadboardThree PCF8574 I/O extendersEight each of red, green and yellow (or your choice) LEDs, each with a current draw of no more than 20mATwo 4.7 kilo ohm resistorsHook-up wiresThree 0.1 uF ceramic capacitors

    Here is the schematic:

    2 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • and the example board layout:

    3 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • and the example sketch. Note that the device addresses in the sketch match the schematic above. If for some reason you are wiring yourPCF8574s differently, you will need to recalculate your device addresses:

    123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657

    // Example 21/.1

    #include "Wire.h"#define redchip 0x20 // device addresses for PCF8547Ns on each LED colour bank #define yellowchip 0x22 // addresses in this example match the published schematic in the tutorial#define greenchip 0x21 // you will need to change addresses if you vary from the schematicint dd=20; // used for delay timing

    void setup(){Wire.begin();allOff(); // the PCF8574N defaults to high, so this functions turns all outputs off}

    // remember that the IC "sinks" current, that is current runs fro +5v through the LED and then to I/O pin// this means that 'high' = off, 'low' = on.

    void testfunc(){Wire.beginTransmission(redchip);Wire.write(0);Wire.endTransmission();delay(dd+50);Wire.beginTransmission(redchip);Wire.write(255);Wire.endTransmission();delay(dd+50);Wire.beginTransmission(yellowchip);Wire.write(0);Wire.endTransmission();delay(dd+50);Wire.beginTransmission(yellowchip);Wire.write(255);Wire.endTransmission();delay(dd+50);Wire.beginTransmission(greenchip);Wire.write(0);Wire.endTransmission();delay(dd+50);Wire.beginTransmission(greenchip);Wire.write(255);Wire.endTransmission();delay(dd+50);

    }

    void testfunc2(){for (int y=1; y

  • And finally our demonstration video:

    585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127

    }

    for (int y=1; y

  • That was a good example of controlling many outputs with our humble I2C bus. You could literally control hundreds of outputs ifnecessary a quite inexpensive way of doing so. Dont forget to take into account the total current draw of any extended circuits if youare powering from your Arduino boards.

    The next devices to examine on our I2C bus ride are EEPROMs Electrically Erasable Programmable Read-Only Memory. These arememory chips that can store data without requiring power to retain memory. Why would we want to use these? Sometimes you mightneed to store a lot of reference data for use in calculations during a sketch, such as a mathematical table; or perhaps numericalrepresentations of maps or location data; or create your own interpreter within a sketch that takes instruction from data stored in an array.

    In other words, an EEPROM can be used to store data of a more permanent use, ideal for when your main microcontroller doesnt havenenough memory for you to store the data in the program code. However, EEPROMs are not really designed for random-access orconstant read/write operations they have a finite lifespan. But their use is quite simple, so we can take advantage of them.

    EEPROMS, like anything else come in many shapes and sizes. The model we will examine today is the Microchip 24LC256 (datasheet.pdf). It can hold 256 kilobits of data (thats 32 kilobytes) and is quite inexpensive. This model also has selectable device addressesusing three pins, so we can use up to eight at once on the same bus. An example:

    The pinouts are very simple:

    6 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Pin 7 is write protect set this low for read/write or high for read only. You could also control this in software if necessary. Once againwe need to create a slave I2C device address using pins 1, 2 and 3 these correlate to A2, A1 and A0 in the following table:

    So if you were just using one 24LC256, the easiest solution would be to set A0~A2 to GND which makes your slave address 1010000or 0x50 in hexadecimal. There are several things to understand when it comes to reading and writing our bytes of data. As this IC has 32kilobytes of storage, we need to be able to reference each byte in order to read or write to it. There is a slight catch in that you need morethan one byte to reference 32767 (as in binary 32767 is 11111111 0100100 [16 bits]).

    So when it comes time to send read and write requests, we need to send two bytes down the bus one representing the higher end of theaddress (the first 8 bits from left to right), and the next one representing the lower end of the address (the final 8 bits from left to right) see figure 6.1 on page 9 of the data sheet.

    An example we need to reference byte number 25000. In binary, 25000 is 0110000110101000. So we split that upinto 01100001 and 10101000, then covert the binary values to numerical bytes with which to send using the Wire.send(). Thankfullythere are two operators to help us with this. This first is >>, known as bitshift right. This will take the higher end of the byte and drop offthe lower end, leaving us with the first 8 bits. To isolate the lower end of the address, we use another operator &, known as bitwise and.This unassuming character, when used with 0XFF can separate the lower bits for us. This may seem odd, but will work in the examplesbelow.

    Writing data to the 24LC256

    Writing data is quite easy. But first remember that a byte of data is 11111111 in binary, or 255 in decimal. First we wake up the I2C buswith:

    then send down some data. The first data are the two bytes representing the address (25000) of the byte (12) we want to write to thememory.

    And finally, we send the byte of data to store at address 25000, then finish the connection:

    There we have it. Now for getting it back

    Reading data from the 24LC256Reading is quite similar. First we need to start things up and move the pointer to the data we want to read:

    Then, ask for the byte(s) of data starting at the current address:

    In this example, incomingbyte is a byte variable used to store the data we retrieved from the IC. Now we have the theory, lets put it intopractice with the test circuit below, which contains two 24LC256 EEPROMs. To recreate this you will need:

    Arduino Uno or compatible boardA large solderless breadboard

    1 Wire.beginTransmission(0x50); // if pins A0~A2 are set to GND

    12

    Wire.write(25000 >> 8); // send the left-hand side of the address downWire.write(25000 & 0xFF); // send the right-hand side of the address down

    12

    Wire.write(12);Wire.endTransmission();

    1234

    Wire.beginTransmission(0x50); // if pins A0~A2 are set to GNDWire.write(25000 >> 8); // send the left-hand side of the address downWire.write(25000 & 0xFF); // send the right-hand side of the address downWire.endTransmission();

    123

    Wire.beginTransmission(0x50); // if pins A0~A2 are set to GNDWire.requestFrom(0x50,1);Wire.read(incomingbyte);

    7 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Two Microchip 24LC256 EEPROMs (you can use 24LC512s as well)Two 4.7 kilo ohm resistorsHook-up wiresTwo 0.1 uF ceramic capacitors

    Here is the schematic:

    the board layout:

    and the example sketch. Note that the device addresses in the sketch match the schematic above. If for some reason you are wiring your24LC256s differently, you will need to recalculate your device addresses. To save time with future coding, we have our own functions forreading and writing bytes to the EEPROM readData() and writeData(). Consider the sketch for our example:1234567891011121314151617181920212223242526272829303132

    // Example 21.2

    #include "Wire.h" // for I2C#define chip1 0x50 // device address for left-hand chip on our breadboard#define chip2 0x51 // and the right

    // always have your values in variablesunsigned int pointer = 69; // we need this to be unsigned, as you may have an address > 32767byte d=0; // example variable to handle data going in and out of EERPROMS

    void setup(){

    Serial.begin(9600); // for screen outputWire.begin(); // wake up, I2C!

    }

    void writeData(int device, unsigned int add, byte data)// writes a byte of data 'data' to the chip at I2C address 'device', in memory location 'add'{

    Wire.beginTransmission(device);Wire.write((int)(add >> 8)); // left-part of pointer addressWire.write((int)(add & 0xFF)); // and the rightWire.write(data);Wire.endTransmission();delay(10);

    }

    byte readData(int device, unsigned int add)// reads a byte of data from memory location 'add' in chip at I2C address 'device' {

    byte result; // returned valueWire.beginTransmission(device); // these three lines set the pointer position in the EEPROM

    8 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Bio

    And the output from the example sketch:

    Although the sketch in itself was simple, you now have the functions to read and write byte data to EEPROMS. Now it is up to yourimagination to take use of the extra memory.

    If you enjoyed this article, or want to introduce someone else to the interesting world of Arduino check out my book (now in afourth printing!) Arduino Workshop.

    Have fun and keep checking into tronixstuff.com. Why not follow things on twitter, Google+, subscribe for email updates or RSS usingthe links on the right-hand column, or join our forum dedicated to the projects and related items on this website.

    John BoxallFounder, owner and managing editor of tronixstuff.com.

    33343536373839404142434445464748495051525354555657585960616263646566

    Wire.write((int)(add >> 8)); // left-part of pointer addressWire.write((int)(add & 0xFF)); // and the rightWire.endTransmission();Wire.requestFrom(device,1); // now get the byte of data...result = Wire.read();return result; // and return it as a result of the function readData

    }

    void loop(){

    Serial.println("Writing data...");for (int a=0; a

  • Please share with others:

    Breaking up an automatic room deodoriser round twoKit review nootropics design EZ-Expander Shield

    17 Responses to Tutorial: Arduino and the I2C bus Part Two

    Marcel says:October 29, 2010 at 12:42 am

    Very useful. Thanks.

    Im confused on the Sink / Source issue and dont see why a resistor is not necessary if its Sinking. :\

    [m]

    Reply

    John Boxall says:October 29, 2010 at 12:49 am

    Hi MarcelThats a good question. It is peculiar to the TI PCF8574, it takes care of the current for us, whereas the 74HC595 currentsource needs a resistor.Thanks for pointing out that to me, Ill go back and change it a little.CheersjohnReply

    1.

    Lander Vanrobaeys says:December 7, 2010 at 1:03 am

    Hi,

    I am new at IC.I am using 2 Compmonents working with IC,MMA7660 & HMC5843. Accelerometer & Compass.But they use same registers to read out.How can i make this work on a arduino uno?cause that device only has 1 SDA and 1 SCL.

    Grtz

    Reply

    John Boxall says:December 7, 2010 at 10:20 pm

    With I2C the concept is to run many I2C devices on the same data bus. Perhaps you will find my articles about Arduino andI2C interesting please see http://wp.me/pQmjR-11V and then http://wp.me/pQmjR-16p.Have funjohnReply

    2.

    Sonny says:3.

    21

    Like this:

    Be the first to like this.

    10 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • December 19, 2010 at 1:50 am

    In part one you mentioned you would look at the thermostat function of the CN75 in part two. However part 2 addressed someother types of devices. Could you make a part 3 I2C and go over more of the CN75 functions? Also using the PCF8574 would it bepossible to control an H-Bridge with this chip using I2C?

    Reply

    John Boxall says:December 19, 2010 at 9:24 pm

    Hi SonnyYes, I2C part III is on my to-do list, however Im not sure exactly when at this stage.CheersjohnReply

    rusty says:January 12, 2011 at 7:00 am

    Ive been reading & re-reading the datasheet for the PCF8574. What is the wording (or diagram) that tells the user the output is acurrent sink. I am trying to use a PCA9555 and if not for the diagram (fig.19) that shows the hook-up of a LED I wouldnt haveknown it was a current sink also. Help!Rusty

    Reply

    John Boxall says:January 12, 2011 at 10:36 am

    On page one: At power on, the I/Os are high. In this mode, only a current source to VCC is active. Which means that thereis 5V at the pin, so current will not flow from 5V through the LED to the 8574s pin. In other words, a current sink.Sometimes I think data sheet authors dont really write their documentation in an easily accessible form. When we set thepin to low, it becomes 0V, and current will flow from 5V through the LED to the pin. It seems a bit arse-about (backwards),and to let current flow through all pins (turn all 8 LEDs on) we set all the pins low. Took me an hour or so to work it out aswell.cheersjohnReply

    4.

    Eugene Sherbin says:February 5, 2011 at 6:42 pm

    According to your writeup the PCF8574 is an I/O chip which means it can read or write and according to the data sheet it can readif you set the R/W bit to high.

    So I have 2 questions based on that statement.

    First, how do I set the R/W bit in my code? It seems by default its low so in your code you didnt even have to mention it.

    And second, how do I then read the data? Do I just do Wire.requestFrom(address, quantity)?Thank you

    Reply

    5.

    ram says:May 5, 2013 at 3:32 pm

    in PCF8574s coding .i am confused how it is writing each led one by one plzz guide me ..i am novice !!

    Reply

    6.

    11 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • John Boxall says:May 6, 2013 at 9:36 am

    Look at the sketch Example 21.1, especially the following:for (int y=1; y

  • August 14, 2013 at 9:30 am

    Thanks for the guidance. Ill discontinue using the MCP23017 for this. Ive got a common cathode display and waswondering what you think about using the MAX7221? This portion of the project is a necessary step for the largerproject. Thanks again.

    John Boxall says:August 14, 2013 at 11:26 am

    Yes, MAX7219/7221 is much easier. See http://playground.arduino.cc/Main/LedControl

    Trackbacks/Pingbacks

    Leave a Reply

    Name (required)

    Mail (will not be published) (required)

    Website

    Notify me of follow-up comments by email.

    Notify me of new posts by email.

    Visit tronixlabs.com

    Helping you make it with Australia's best value for supported hobbyist electronics from adafruit, DFRobot, Freetronics, Seeed Studio andmore!

    Subscribe via email

    Receive notifications of new posts by email.

    13 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Search the site

    tronixstuff forum

    Why not join our moderated discussion forum?

    Arduino Tutorials

    Click for Detailed Chapter Index

    Chapters 0 1 2 3 4Chapters 5 6 6a 7 8Chapters 9 10 11 12 13Ch. 14 - XBeeCh. 15 - RFID - RDM-630Ch. 15a - RFID - ID-20Ch. 16 - EthernetCh. 17 - GPS - EM406ACh. 18 - RGB matrix - awaiting updateCh. 19 - GPS - MediaTek 3329Ch. 20 - I2C bus part ICh. 21 - I2C bus part IICh. 22 - AREF pinCh. 23 - Touch screenCh. 24 - Monochrome LCDCh. 25 - Analog buttonsCh. 26 - GSM - SM5100 UnoCh. 27 - GSM - SM5100 MegaCh. 28 - Colour LCDCh. 29 - TFT LCD - coming soon...Ch. 30 - Arduino + twitterCh. 31 - Inbuilt EEPROMCh. 32 - Infra-red controlCh. 33 - Control AC via SMSCh. 34 - SPI bus part ICh. 35 - Video-outCh. 36 - SPI bus part IICh. 37 - Timing with millis()Ch. 38 - Thermal PrinterCh. 39 - NXP SAA1064Ch. 40 - Push wheel switchesCh. 40a - Wheel switches IICh. 41 - More digital I/OCh. 42 - Numeric keypadsCh. 43 - Port Manipulation - UnoCh. 44 - ATtiny+ArduinoCh. 45 - Ultrasonic SensorCh. 46 - Analog + buttons IICh. 47 - Internet-controlled relaysCh. 48 - MSGEQ7 Spectrum AnalyzerFirst look - Arduino DueCh. 49 - KTM-S1201 LCD modulesCh. 50 - ILI9325 colour TFT LCD modules

    BluetoothStarter Kit

    Jump start your bluetoothdata app with a flexible

    PIC32 starter kit

    14 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Ch. 51 - MC14489 LED display driver ICCh. 52 - NXP PCF8591 ADC/DAC ICCh. 53 - TI ADS1110 16-bit ADC ICCh. 54 - NXP PCF8563 RTCCh. 55 - GSM - SIM900Ch. 56 - MAX7219 LED driver ICCh. 57 - TI TLC5940 LED driver ICCh. 58 - Serial PCF8574 LCD BackpacksCh. 59 - L298 Motor ControlCh. 60 - DS1307 and DS3231 RTC part IArduino Yn tutorialspcDuino tutorials

    The Arduino Book

    Fr unsere deutschen Freunde

    Dla naszych polskich przyjaci ...

    15 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...

  • Australian Electronics!

    Buy and support Silicon Chip - Australia's only Electronics Magazine.

    Interesting Sites

    Amazing Arduino Shield DirectoryDavid L. Jones' eev blogSilicon Chip magazine Always a great read!Talking ElectronicsDangerous PrototypesThe Amp Hour podcastSuperhouse.tv High-tech home renovation

    Use of our content

    tronixstuff.com by John Boxall is licensed under a Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International License.

    16 http://tronixstuff.com/2010/10/29/tutorial-arduino-and-the-i2c-bus-part...