Updated PCF8574 code for 0.8.5

This is where you talk about the NXJ hardware related topics such as the brick, sensors, LEGO pieces, etc

Moderators: roger, 99jonathan, imaqine

Updated PCF8574 code for 0.8.5

Postby oparekh » Fri Oct 30, 2009 6:39 pm

Here's an updated version of a class to talk to a PCF8574(A) I2C I/O extender. The original code is available in this thread; the version below works with 0.8.5.

Code: Select all
import lejos.nxt.*;

/**
 * This class is used to communicate with a PCF8574 two-wire I2C-bus
 * to 8-bit parallel bus I/O expander.
 *
 */
public class PCF8574 {
   
    /**
     * Returns the sensor port. 
     */
    private I2CPort I2Cport;
   
    /**
     * Returns the sensor address. 
     * Values range from 0x20 - 0x27 (or 0x38 - 0x3F when using a PCF8574A).
     */
    private byte address;
   
    /**
     * Returns the current data value. 
     */
    private byte[] data = {0x00};
   
    /**
     * Initializes the PCF8574 sensor.
     * @param sensorPort NXT sensor port.
     * @param address sensor address.  Values range from 0x20 - 0x27
     * (or 0x38 - 0x3F when using a PCF8574A).
     */
    public PCF8574(I2CPort sensorPort, byte sensorAddress) {
      I2Cport = sensorPort;
      address = sensorAddress;
      
      I2Cport.i2cEnable(I2CPort.STANDARD_MODE);
    }
   
    /**
     * Method for sending data to sensor.
     * @param value Data to send.
     * @return
     */
    public void sendData(byte value) {
      data[0] = value;
      I2Cport.i2cStart(address, 0x00, 0, data, 1, 1);
      while (I2Cport.i2cBusy() != 0) {
         Thread.yield();
      }
    }
   
    /**
     * Method for retrieving the data from the sensor.
     * @return value of 8-bit parallel bus port.
     */
    public int getData() {   
      int ret = I2Cport.i2cStart(address, 0x00, 0, data, 1, 0);
      
      if (ret != 0) return -1;
      
      while (I2Cport.i2cBusy() != 0) {
         Thread.yield();
      }
      return (0xFF & data[0]);
    }
   
    /**
     * Method for retrieving the status of one sensor port.
     * @param port the sensor port. Values range from 1-8.  This is the PCF8574, not the NXT port.
     * @return value of sensor port.  1 means port is high, 0 means port is low (pulled to ground).
     */
   
    public int getSensorPortStatus(int sensorPort) {
      int result = -1;
      int mask = -1;
      int data = getData(); //get status of all ports from sensor
      
      //create a mask to logically AND the data with...
      mask = 1 << (sensorPort - 1);
      
      result = (byte)mask & (byte)data;
      if ( result > 0 ) {
         return 1;
      }else {
         return 0;
      }
    }
}
oparekh
New User
 
Posts: 1
Joined: Fri Oct 30, 2009 5:00 pm

Postby gloomyandy » Fri Oct 30, 2009 7:36 pm

Hi,
Does this mean that you now have this working with 0.85?

Also I don't think that your getData method will work correctly, you need to call i2cComplete method to obtain the results of any read operations. See the code here:
http://lejos.svn.sourceforge.net/viewvc/lejos/trunk/classes/lejos/nxt/I2CSensor.java?revision=3423&view=markup

The reason for this is that avoids the firmware from having to hold a pointer to user data during and i2c transaction. Instead an internal buffer is used and the i2cComplete method reads the data out of that...

Andy

PS With 0.85 you may need avoid using port 4 I introduced a bug that means that i2c sensors do not work on this point when adding support for the new Lego color sensor. This is fixed in the developers snapshot, or you can fix it with an updated file for your classes.jar see this thread for details....
http://lejos.sourceforge.net/forum/viewtopic.php?t=1733
User avatar
gloomyandy
leJOS Team Member
 
Posts: 3004
Joined: Fri Sep 28, 2007 2:06 pm
Location: UK

Postby JAVA_kiwi » Mon Dec 28, 2009 2:44 am

Hi,
I have tested this class with leJOS version 0.85 and found that the sendData method worked whilst as Andy said, the getData method didn't. I had a look at the I2CSensor class and rectified this with the i2ccomplete method. getData seems to work fine with 0.85 now.
Here is the class with the modification:
Code: Select all

import lejos.nxt.*;
/**
 * This class is used to communicate with a PCF8574
two-wire I2C-bus
 * to 8-bit parallel bus I/O expander.
 *
 */
public class PCF8574 {
   /**
    * Returns the sensor port.
    */
   private I2CPort I2Cport;
   /**
    * Returns the sensor address.
    * Values range from 0x20 - 0x27 (or 0x38 - 0x3F when
using a PCF8574A).
    */
   private byte address;
   /**
    * Returns the current data value.
    */
   private byte[] data = {0x00};
   /**
    * Initializes the PCF8574 sensor.
    * @param sensorPort NXT sensor port.
    * @param address sensor address. Values range from
0x20 - 0x27
    * (or 0x38 - 0x3F when using a PCF8574A).
    */
   public PCF8574(I2CPort sensorPort, byte sensorAddress)
   {
      I2Cport = sensorPort;
      address = sensorAddress;
      I2Cport.i2cEnable(I2CPort.STANDARD_MODE);
   }
   /**
    * Method for sending data to sensor.
    * @param value Data to send.
    * @return
    */
   public void sendData(byte value) {
      data[0] = value;
      I2Cport.i2cStart(address, 0x00, 0, data, 1, 1);
      while (I2Cport.i2cBusy() != 0) {
         Thread.yield();
      }
      
   }
   /**
    * Method for retrieving the data from the sensor.
    * @return value of 8-bit parallel bus port.
    */
   public int getData() {
      int ret = I2Cport.i2cStart(address, 0x00, 0, null,
            1, 0);
      if (ret != 0) return -1;
      while (I2Cport.i2cBusy() != 0) {
         Thread.yield();
      }
      
      ret = I2Cport.i2cComplete(data, 1);
        return (0xFF & data[0]);
   }
   
   
   /**
    * Method for retrieving the status of one sensor
port.
    * @param port the sensor port. Values range from
1-8. This is the PCF8574, not the NXT port.
    * @return value of sensor port. 1 means port is
high, 0 means port is low (pulled to ground).
    */
   public int getSensorPortStatus(int sensorPort) {
      int result = -1;
      int mask = -1;
      int data = getData(); //get status of all ports from sensor
      //create a mask to logically AND the data with...
      mask = 1 << (sensorPort - 1);
      result = (byte)mask & (byte)data;
      if ( result > 0 ) {
         return 1;
      }else {
         return 0;
      }
   }
}


I also tried both methods with Sensor Port 4 and it also worked fine. I couldn't duplicate any of the bugs Andy mentioned.
Allan
JAVA_kiwi
New User
 
Posts: 4
Joined: Mon Jul 28, 2008 7:08 am

Postby nick_193 » Wed Jan 06, 2010 10:48 am

Can u guys maybe send me the electrical circuit that you built? I cant get the code to work on my chip.

It does read the changing of byte from 0xFD to 0xFF but it my LED's do not light up..

I dont understand if there is datatransfer between my brick and the PCF8574P or not and if so why isnt my LED lighting up.

This is what ive built on my breadbord;

Image
nick_193
New User
 
Posts: 6
Joined: Wed Oct 14, 2009 10:31 am

Postby s.frings » Fri Mar 04, 2011 7:49 pm

I tried the cirquit and code with the current development version of Lejos without success.

The port number is wrong. If all three address configuration pins of the PCF8574 are low, the I2C address is 0x40 (not 0x20). To switch all LED's on, write a 0x00 to the chip this way:

I2CPort port=SensorPort.S1;
port.i2cEnable(I2CPort.STANDARD_MODE);
byte[] data={0x00};
int status=port.i2cTransaction(0x40,data,0,1,null,0,0);
System.out.println("Status: "+status);
Button.waitForPress();

For R1 and R2 use 82k Ohm, as stated in Lego's hardware developer kit. Also remember that the power supply provides only 20mA, so you have only a few mA per LED available.
s.frings
Active User
 
Posts: 131
Joined: Tue Jul 20, 2010 2:01 pm

Postby mattallen37 » Fri Mar 04, 2011 11:29 pm

s.frings wrote:...Also remember that the power supply provides only 20mA, so you have only a few mA per LED available.
Actually, it is 180ma total. This 180ma needs to be shared with all the ports though. It is okay to pull 180ma from one port, as long as you aren't powering any other hardware (including motor encoders).
Matt
mattallen37
Novice
 
Posts: 28
Joined: Thu Mar 03, 2011 7:45 am

Postby s.frings » Sat Mar 05, 2011 4:10 pm

This class works fine for me:
Code: Select all

import lejos.nxt.I2CPort;


/**
 * Access to a PCF8574 chip, which is a parallel port extension via I2C.
 */
public class PCF8574 {
   
    /** Port where the chip is attached to */
    private final I2CPort port;
   
    /** Device address of the chip */
    private final int address;

    /** Buffer for i/o */
    private byte buffer[]={0x00};
   
    /**
     * Constructor
     * @param i2cPort Port wheere the chip is attached to (e.g. SensorPort.S1)
     * @param deviceAddress Device address of the chip (e.g. 0x40)
     */
    public PCF8574(I2CPort i2cPort, int deviceAddress) {
        port=i2cPort;
        address=deviceAddress;
        port.i2cEnable(I2CPort.STANDARD_MODE);
    }

    /**
     * Write to the i/o pins
     * @param value Data to be written
     */
    public void write(byte value) {
        buffer[0]=value;
        port.i2cTransaction(address,buffer,0,1,null,0,0);
    }

    /**
     * Read from the i/o pins
     * @return Data that have been read
     */
    public byte read() {
        port.i2cTransaction(address,null,0,0,buffer,0,1);
        return buffer[0];
    }

}
s.frings
Active User
 
Posts: 131
Joined: Tue Jul 20, 2010 2:01 pm

Re: Updated PCF8574 code for 0.8.5

Postby andrea147 » Mon Sep 26, 2011 8:58 am

Hi,
thank you, exactly levitra what I'm looking for!
andrea147
New User
 
Posts: 1
Joined: Mon Sep 26, 2011 8:57 am


Return to NXJ Hardware

Who is online

Users browsing this forum: No registered users and 0 guests

cron
more stuff