Shop OBEX P1 Docs P2 Docs Learn Events
I2C Help — Parallax Forums

I2C Help

lboucherlboucher Posts: 139
edited 2010-03-31 21:52 in General Discussion
Hi All

I was hoping someone could help me out with trying to control the PCA9622 with the SX28.
The PCA9622 is a 16 channel LED controller and you communicate with it via I2C. I attached the datasheet.

I have never used I2C or this LED controller before.

I got everything wired up and spent a few hours trying to get my LED's lite up last night and it just doesn't seem to work.

Hardware Setup:
I am using the tssop version.
I have SDA and SCL pulled high via 10k resistors like in Figure 17, and also connected to RC.0 and RC.1.
I have OE pulled low via a 10K resistor, I do not have it connected to an SX pin like fig 17, its just direct to ground, does that matter? Shouldn't as far as i can tell.
The A0-A6 pins are set exactly like Fig 17. which should result in an I2C address of 0010101x.
I have LED8-15 hooked up, 1 led and 1 resistor Vdd=5
Due to limited space on breadboard i left LED0-7 disconnected.

Firmware Side:
I am following figure 14,
Do
pause 1000
I send a I2Cstart
Then I2Csend 42· which should be correct to write to 0010101x
Then I2Csend 162 which should be the correct control register setting for the sequence in Fig 14.
Then i write out 16 bytes.
Then send I2Cstop
loop

I am at work right now, will attach code when i get home.
Do i have to write to MODE1 and MODE2 registers?
I don't see any requirement to, if all i want to do is PWM controll of all 16 leds.
I completely don't care about grouping or all call or anything like that.


(Note: the one thing that is an unknown. I hand soldered the tssop package to a breakout board. So it is possible I overheated it, but i·have 2 units and both won't·work.·I consider it slightly less likely that i damaged both units.)

Also note i have quadruple checked all connections.
I do see the I2Cstart/end events with a multimeter, i have no scope.

Any help will be greatly appreciated.

Attempt to rewrite main code piece quickly. (Can ya tell i am in a tele-con at work?)

I2Cdatapin···· PIN··· RC.0···· INPUT PULLUP···· (Do i need the pullup if i have external pullup, i just did this because I2CRECV example has it.)
I2Cclockpin····PIN···· RC.1··· INPUT PULLUP

Nak···· VAR·· Bit
idx······ VAR·· Byte

Start:
Nak = 1

Main:
pause 1000
I2CSTART I2Cdatapin
I2CSEND I2Cdatapin,42,Nak··'Send address·· (Do i need this Nak or is that an issue?? Also i believe I remember that it was always returning 0, which i think is right?)
I2CSEND I2Cdatapin,162,Nak·· ' Send Control Register
for idx = 1 to 16
I2CSEND I2Cdatapin,128,Nak· ' Light all LEDs to half brightness
next
I2CSTOP I2Cdatapin
GOTO Main

Update:
Here is the actual code

DEVICE········· SX28, OSCHS2, TURBO, STACKX, OPTIONX, BOR42
FREQ··········· 50_000_000
ID··"LED16"

·I2CData· ·PIN···· RC.0 INPUT pullup
·I2CClock ·PIN···· RC.1 input pullup
·ADC_CLK······ ·PIN···· RC.2 OUTPUT
·ADC_CS······ ·PIN···· RC.3 OUTPUT···
·CH14········· ·PIN···· RC.4 OUTPUT
·CH15········· ·PIN···· RC.5 OUTPUT
·CH16········· ·PIN···· RC.6 OUTPUT
·CH17········ ·PIN···· RC.7 OUTPUT

·b_all··PIN·RB OUTPUT
·led··PIN·RB.1
·a_all··PIN·RA OUTPUT
brightness· var byte
idx ·VAR·Byte
Nak·VAR·BIT
received var·Byte
I2C_TX_BYTE sub·1
I2C_Start_Led sub 0
I2C_Stop_Led sub 0
' =========================================================================
· PROGRAM Start
' =========================================================================
Start:
Nak = 1
brightness = 128
low led
pause 1000
Main:
high led
pause 1000
low led
I2C_Start_Led
I2C_TX_BYTE 42·· '00101010··· Should be address shown in figure 17
I2C_TX_BYTE 162·· '10100010··· Should be set to individually address all 16 led's

· FOR idx = 1 TO 16
I2C_TX_BYTE brightness
· NEXT
I2C_Stop_Led
inc brightness
GOTO Main
sub I2C_TX_BYTE
i2csend I2CData,__PARAM1,Nak
endsub
sub I2C_Start_Led
i2cstart I2CData
endsub
sub I2C_Stop_Led
i2cstop I2CData
endsub

UPDATE 2:
I have tried so many ideas?? Err, i just don't know what to try next.
I was really hoping this would just be simple.
Thanks in advance to anyone that can help.

Post Edited (lboucher) : 3/31/2010 3:23:38 AM GMT

Comments

  • John CoutureJohn Couture Posts: 370
    edited 2010-03-31 18:46
    Mr. Boucher,

    Wow! Thank you for bringing up this chip.· I don't have one but it sure looks like an interesting one.· Reading over the datasheet, you happen to select a pretty sophisticated chip to start learning I2C on.· On the professional development board, there is a DS1307 which is much easier to cut your teeth on.
    However, we work with what we have, so:

    =============================
    HARDWARE SETUP
    =============================
    1) To make your I2C network work, you need to have a SIMPLE SETUP so that you can verify that the setup works.· With that in mind you should have the following connected:

    · a) Connect all of the grounds: 1,9,14,19,24 (see note on pg 6)
    ·
    · b) Connect power to pin 32
    ·
    · c) Connect data lines.· SCL (30) to RB.1 (I2CClock in your program), SDA (31) to RC.0 (I2CData in your program).· Note in SX/B documentation that these have to be two consecutive pins and the SCL has to be the higher number of the two (you did this, see I2CSEND command for more info).
    ·
    · d) Specify the ADDRESS of the device.· Normally on an I2C device you have a very narrow range of addresses to use.· This device allows you up to 126 different combinations as long as you avoid the reserved address. You do this by connecting selected pins A0 through A6 to ground or to a pullup while avoiding the "reserved" address that are specified on pages 7-8 of the datasheet.· We have to avoid the following addresses:
    ·
    ···· %0000 000x - General Call
    ···· %0000 0110 - Software Reset
    ···· %0000 011x - Reserved for future I2C designs
    ···· %0000 1xxx - High speed mode
    ···· %1110 000x - LED All call
    ···· %1111 0xxx - Other devices
    ···· %1111 1xxx - Reserved for future I2C designs
    ·
    · It looks like %0100 0100· (44h) is right in the middle.· Remember the fewer pins you have connected to pullups, the less current it will draw.· Referring to the pin out on page 5 we would set the pins as follows:

    ·· Func· Pin·· Connect To
    ··· A0· (02)·· GND
    ··· A1· (03)·· pullup
    ··· A2· (04)·· GND
    ··· A3· (05)·· GND
    ··· A4· (06)·· GND
    ··· A5· (28)·· pullup
    ··· A6· (29)·· GND

    · e) Now connect ONE led (to simplify our test procedure).· Connect the cathode (NEG side) of an LED to pin 7.· Connect the other side of the LED to a 330 ohm resistor and thence to 5vdc.

    ===================================
    SOFTWARE SETUP
    ===================================·

    2) Once the MCU and I2C device are powered up and the voltage is stabalized, you can start sending commands to the I2C device.· Your program just used the raw i2csend commands and there is much more to the protocol than that (like I said you kinda picked a complicated chip to learn I2C on).··· In SX/B the i2cstart, send, read and stop commands take up a LOT of memory so putting them in their own one-line subroutines actually saves space even if you factor in the call commnds.

    3) Most I2C devices have to be told to "wake up, I want you to get ready for accepting commands".· In other words, the I2C device needs to be sent a command to initialize it (see page 16).· Here I am using a subroutine that I will explain later.

    · I2C_INIT················· ' Reset the device (pg 16, step 2-5)
    ·
    4) Next we want to send it a command to turn on the LED to full brightness.· Here I am using a subroutine that is explained later.

    ·· I2C_Write $44,$02,$FF···· ' send slave ID, register address, brightness ($ff=100% bright)

    5) Typically you would want to wait about a second then turn it off again so you can actually see it change state

    ·· PAUSE 1000

    6) Now turn it off
    ··
    ·· I2C_Write $44,$02,$00···· ' send slave ID, register address, brightness ($00=0% bright)

    '==================================================
    ' SUBROUTINES
    '==================================================
    ' Again the i2csend, read, start and stop commands
    ' take up a lot of memory so they are segrated into
    ' their own subroutines and called.· They are known as:
    ' i2cst = i2cStart
    ' i2csn = i2cSend
    ' i2crc = i2cRecv
    ' i2csp = i2cStop
    '==================================================
    I2C_INIT:
    ' Initialize the PCS9622 device (Datasheet, pg 16)

    ·· input I2CData········· ' prepare line for input
    ·· input I2CClock········ ' prepare line for input
    ·· I2CSt················· ' Start Communications
    ·· I2CSn $06············· ' I2C Reset command
    ·· Pause 10
    ·· I2CSn $A5············· ' wakeup PCA9622
    ·· I2CSn $5A············· ' wakeup PCA9622
    ·· I2CSp················· ' Stop Communications
    ·· ' I2C_WRITE $44,$00,$00· ' Setup mode 1 Register?
    ·· ' I2C_WRITE $44,$00,$00· ' Setup mode 2 Register?
    ·· RETURN

    '==================================================
    I2C_WRITE:
    ' Write a single byte to an I2C Device
    ' USAGE:
    '··· I2C_WRITE DeviceAddress, RegisterAddress, DataToBeWritten
    '
    ·· I2C_Device············ = __param1
    ·· I2C_RegAddr··········· = __param2
    ·· I2C_Dataout··········· = __param3
    ·· I2CSt················· ' start communication
    ·· I2CSn I2C_Device······ ' send the device address
    ·· I2CSn I2C_RegAddr····· ' send the register address
    ·· I2CSn I2C_Dataout····· ' send the data to put in the register
    ·· I2CSp················· ' stop communication
    ·· RETURN

    '==================================================
    I2C_READ:
    ' Get a byte from the I2C device
    ' USAGE:
    '··· myVar = I2C_READ DeviceAddress, RegisterAddress
    '······
    ·· I2C_Device············ = __param1
    ·· I2C_RegAddrn·········· = __param2
    ·· I2CSt················· ' start communication
    ·· I2CSn I2C_Device······ ' send the device address
    ·· I2CSn I2C_RegAddr····· ' send the register address
    ·· I2CSt················· ' restart for read
    ·· I2CSn i2c_device······ ' resend the device address
    ·· Temp = i2crcv
    ·· i2csn $i2c_dataout···· ' send the data to put in the register
    ·· i2csp················· ' stop communication
    ·· RETURN

    '==================================================
    I2CSt:
    ·· I2CStart I2CData
    ·· return
    '==================================================
    I2CSp:
    ·· I2CStop I2CData
    ·· return
    '==================================================
    I2CSn:
    ·· Temp = __PARAM1
    ·· I2CSend I2CData,Temp
    ·· return
    '==================================================
    I2CRcv:
    ·· I2CRecv I2CData,Temp·· ' get one byte from i2c device
    ·· return Temp

    ·One last point.· I don't have this chip so I don't have a way to test this out.· However, there is enough data above to get you started.· If you get stuck, I would recommend looking at the DS1307 chip on the Prof Dev Board and trying to get that to work first.

    ·John.

    ▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔▔
    John J. Couture

    San Diego Miramar College
  • lboucherlboucher Posts: 139
    edited 2010-03-31 21:52
    Hey John

    Thanks for the awesomely detailed responce.

    I got a responce from a guy name Phil in australia who works with this chip.

    He caught 2 things i missed, and one I had tested but wouldn't do anything without the other 2 gotchas.

    The thing i had thought off was that MODE1 register had to be changed to turn on the oscilator, then wait 500 us.

    Gotcha 1 was that I didn't realize what an I2C restart was and how to use it.

    Gotcha 2 I had to enable to LED0-3 banks.

    Now everything works fine.

    Here is his responce.

    Ok, you need to set the LEDOUTx registers, they are off by default and take the 9622 out of sleep mode in Mode 1 register.
    Pay attention to Table 5 and table 10

    Sending Sequence is
    (send i2c start)
    Address
    control register
    Mode 1 Register·· (turn off sleep)
    Pause >500uS so osc starts

    (restart)... this is what is called a repeated start without a stop command
    Address
    control register
    ledout0 (turn on led output)
    ledout1 (turn on led output)
    ledout2 (turn on led output)
    ledout3 (turn on led output)

    (send i2c stop)


    Now you can send the channel data
    (send i2c start)
    address
    control register· (set to autoinc and start at pwm0)
    pwm0
    .
    .
    .
    pwm15

    (send i2c stop)

    You shouldn't need to set anything in the Mode 2 Register. grppwm and grpfreq can be left at default values
Sign In or Register to comment.