NXT I2C Tutorial

Discussion specific to the intelligent brick, sensors, motors, and more.
Post Reply
sebi-mylegopage
Posts: 16
Joined: 29 Sep 2010, 13:47
Location: Germany
Contact:

NXT I2C Tutorial

Post by sebi-mylegopage »

This is a I2C Tutorial for NXT.
PCF8574P with 8 LEDs

A PCF8574 has 8 I/O(Input or Output. All I/Os kann be read/write 1 or 0.)
PinConfiguration:
Pin 1-3==A0-2
Pin 4-7== P0-3
Pin 8== GND/-
Pin 9-12==P4-7
Pin 13== INT
Pin 14== SCL
Pin 15== SDA
Pin 16==Vdd/+5V
A0-2 is for I2C Adress Configuration. The standart Addres of PC8574 is 0x40. If you put any of the Ports to 0/1 (+/-) the Addres changes.
The schematic of the Adres:
0 1 0 0 A2 A1 A0 0.
If A0-2 aro Low(0,-) The address is only 0x40.(01000000 to hexadecimal is 0x40).
As Example:
A0=1
A1=0
A2=1
You must ad the binary value of Ports to 0x40:
101=0x05
0x05+0x40=0x45

P0-7 are the I/O Ports. You can put as an example LEDs or switches on they.

SCL and SDA are the Pins for the I2C Communication. They need an pullup(Resistor to +) of 82k.

INT is the interrupt output. If any Input is changing. It go to High(+). This pin you cann connect to Pin1(ADA). And read as an Touchsensor. So you don't must read any time des PCF8574 per I2C for checking Inputs.
But if Pin1 is set to 9V(e.g. if intalised as Ultrasonic Senor), the IC will be destroid. A

If you want to connect a or more LED(s) to the IC you should connect them with kathode to an Output, und with anode to +. Naturraly the LED needs an resistor ;)

Curcuit:
Image
R1 and R2 have 82k. For R3-10 I had used 470Ohm. I think 220Ohm should work too. But you should use the value you want ;).
But the maximal current is 180mA.

Building plan für Breadboard

For this tests I had used the Driver from Adam Mokanszki. But you must change the addres to 0x40. (In the Header of the Programm)
Programm for a 8 Channel Knight Rider, using Adam Mokansukis Driver:

Code: Select all

#include "pcf8574llb.nxc"

task main()
{
    int port=1;
    bool richtung=true;
    SetSensorLowspeed(S1);
    WritePorts(0xFF); //Alle Ports auf 1(+) setzen.
    Wait(100);
    while(true)
    {
        DeletePort(port); //Wechselt Wert 1(+)->0(-)
        Wait(500);
        WritePort(port); //Schreibt 1(+)
        if(richtung==true)
        {
           port++;
        }
        else
        {
           port-=1;
        }
        if(port==8)
        {
           richtung=false;
        }
        if(port==1)
        {
           richtung=true;
        }
    }
}

pcf8574llb.nxc

Code: Select all


/*************************************************************/
/*                                                           */
/*                     PCF8574Driver for NXC                 */
/*                                                           */
/*                 Programmed by: Adam Mokanszki             */
/*                                                           */
/*                 University of Debrecen Hungary            */
/*                                                           */
/*                            ENJOY! :)                      */
/*                                                           */
/*************************************************************/
#ifndef _PCF8574_
#define _PCF8574_

#define  PCF8574ID  0x40    //The address of your PCF8574---*******Here you must change the address to 0x40, I have done this yet.
#define  PCF8574Port  S1   //This is the port on the NXT where the device is connected
void WritePort(char input);  //Writing a single port the input is the port number 1-8
void DeletePort(char input); //Deleting a single port the input is the port number 1-8
void WritePorts(byte input); //Writing all ports with one byte
int ReadPort(char input);    //Reading a single port the input is the port number 1-8 returning with a logical value in integer: 0,1
int ReadPorts();             //Reading all ports returning with one byte
                             //That's all what you need to know about this file

void WritePort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;
    
    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    byte Command = result | (1<<(input-1));

    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {
        loop = I2CStatus(PCF8574Port, nByteReady);
    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }
}

void DeletePort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    byte Command = result ^ (1<<(input-1));

    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

}

void WritePorts(byte input){

    byte I2CMsg[];
    byte Address = PCF8574ID;
    byte Command = input;
    byte nByteReady = 0;
    int loop;
    
    ArrayBuild(I2CMsg, Address, Command);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }

    I2CWrite(S1, 1, I2CMsg);

    while (loop == STAT_COMM_PENDING) {

        loop = I2CStatus(PCF8574Port, nByteReady);

    }
}

int ReadPort(char input){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);
    Wait(8);
    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }

    if( result == (result | (1<<input-1)) ){

       result = 1;

    }
    else{

       result = 0;

    }
    
    if(result==-1){

     TextOut(0, LCD_LINE7, "Error: Check the");
     TextOut(0, LCD_LINE8, "   connection!");
     Wait(500);
     ClearScreen();
    }
    return result;
}

int ReadPorts(){

    byte cnt = 0x02;
    byte I2CMsg[];
    byte inbuf[];
    byte Address = PCF8574ID;
    byte nByteReady = 0;
    int  result = -1;
    int loop;

    ArrayBuild(I2CMsg, Address);

    Wait(8);

    while (loop == STAT_COMM_PENDING) {

          loop = I2CStatus(PCF8574Port, nByteReady);

    }

    if (I2CBytes(PCF8574Port, I2CMsg, cnt, inbuf)) {

        result = inbuf[1];

    }
    if(result==-1){

     TextOut(0, LCD_LINE7, "Error: Check the");
     TextOut(0, LCD_LINE8, "   connection!");
     Wait(500);
     ClearScreen();
    }
    return result;
}
#endif
-to be continued
Last edited by sebi-mylegopage on 29 Sep 2010, 15:23, edited 2 times in total.
afanofosc
Site Admin
Posts: 1256
Joined: 26 Sep 2010, 19:36
Location: Nashville, TN
Contact:

Re: NXT I2C Tutorial

Post by afanofosc »

Very nice! Thanks for sharing this code. I wish I had more time to get into making custom I2C devices like I've seen other people make. It brings back fond memories of when I helped my dad build a Heathkit H8 computer and color TV and when as a dance DJ in the 80s I made a phase shifter and helped build a sound-controlled light box.

John Hansen
Multi-platform LEGO MINDSTORMS programming
http://bricxcc.sourceforge.net/
philoo
Posts: 76
Joined: 29 Sep 2010, 09:04
Location: Paris, France
Contact:

Re: NXT I2C Tutorial

Post by philoo »

A nifty little chip, eh!?
sebi-mylegopage wrote:This is a I2C Tutorial for NXT.

INT is the interrupt output. If any Input is changing. It go to High(+). This pin you cann connect to Pin1(ADA). And read as an Touchsensor. So you don't must read any time des PCF8574 per I2C for checking Inputs.

Take care doing so! Pin 1 can be configured in the NXT to provide 9V (eg. for the ultrasonic sensor), this might fry your 8574!
R1 and R2 have 82k. For R3-10 I had used 470Ohm. I think 220Ohm should work too. But you should use the value you want ;).
But the maximal current is 100mA. (I'm not sure)

Total current available for all ports is about 180mA, so 470ohm is safer (but dimmer!)
Philo
sebi-mylegopage
Posts: 16
Joined: 29 Sep 2010, 13:47
Location: Germany
Contact:

Re: NXT I2C Tutorial

Post by sebi-mylegopage »

Thanks, I have edited it.
I will uplaod a INT protect curcuit.
mattallen37
Posts: 1818
Joined: 02 Oct 2010, 02:19
Location: Michigan USA
Contact:

Re: NXT I2C Tutorial

Post by mattallen37 »

sebi-mylegopage wrote:If you want to connect a or more LED(s) to the IC you should connect them with kathode to an Output, und with anode to +. Naturraly the LED needs an resistor ;)
There is a very specific reason why any LEDs that are to be controlled need to be connected in this way. To add to the entirety or this, you should elaborate on this fact, and the fact that you must have a pin written high to sense it being pulled low (as a switch can do). It is all because it cannot source current, only sink it (technically, it can source a tiny bit) on it's eight IO pins.
Matt
http://mattallen37.wordpress.com/

I'm all for gun control... that's why I use both hands when shooting ;)
Post Reply

Who is online

Users browsing this forum: No registered users and 15 guests