MCP23016 I/O expander driving LEDs PICAXE 28X1 hi2c sample code

BCJKiwi

Senior Member
Note that the sample program shown relates to sinking the current. The circuit this code is for has a common supply (PWM'd) to all the LEDS with the MCP23016 sinking to 0V to complete the circuit and turn on the LED.

Code:
'#################################################
'# For PICAXE-28X1, MCP23016 driving LEDS        #
'#################################################
#picaxe 28x1
SetFreq m8
'#################################################
Init:
 hi2csetup i2cmaster,%01000000,i2cfast_8,i2cbyte
       '%0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
       '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1'
       'If using multiple devices of different speeds on the bus,
       'then use this line to change speed and remove the [%01000000] in the next line.
 hi2cout [%01000000],6,($00,$00)       'IRDIR0,IRDIR1 set port direction register to output
       'Note:- MCP23016 documentation indicates this register pair (06 & 07) 
       'defaults to all 1's (all Inputs) on Power On Reset.
       'However if this register pair is not configured to all 0's (Outputs) there is no function when driving LEDS.
 hi2cout $0A,($00,$00)   'IOCON0  
IO_1:
 hi2cout 0,(%01010101,%01010101) 'GPO,GP1 Turn on each alternate output
       'A '0' bit to register 0 will turn ON current sink and a '1' will reverse to a current source
       'i.e. the port is not actually turned on or off but rather it's direction is reversed 
 pause 1250
 hi2cout 0,(%10101010,%10101010)
 pause 250
 hi2cout 0,(%01010101,%01010101)
 pause 1250
 hi2cout 0,(%10101010,%10101010)
 pause 250
Goto IO_1 'Loop
 
Last edited:

evgerven

New Member
MCP23016 LED Clock

Funny. I'm building an 'analog' clock using this same IO chip. I seem to have a problem the outputs are not always correct. data is set in the output register in my case. I will try your approach this evening and hope for better results.

Using Picaxe 18x, TCN75A (I2C temp sensor) and 1307 (I2C RTC).
This analog clock will display time in 3 rows of 12 LED's each (hrs, 10 mins, mins) changing every few seconds to temperature in celcius scale ('10101010',10c,1c)


Erik
 
Last edited:
IO_2

here is the code I try now. for some reason the io chip doesn't get the data right, therefore I'm writing the same data multiple times.

<code>
; *******************************
; Filename: MCP23017
; Date: test
; File Version: 0.1
; Written by: EvG
; Last Revision: 07-02-2008
; Target PICAXE: 18-X
; *******************************

IO_2:
i2cslave %01000000, i2cslow, i2cbyte
writei2c $0A,($00,$00) 'IOCON0 cofiguration register
writei2c $00,($00,$00) 'Set portdirection to outputs

for b0 = 0 to 8

lookup b0,(%11111111,%01111111,%10111111,%11011111,%11101111,%11110111,%11111011,%11111101,%11111110),b1

for b3 = 0 to 2
writei2c $13,(b1)
pause 5
next
next
goto IO_2
<\code)
 

BCJKiwi

Senior Member
Are you using an MCP23016 or an MCP23017?
Your text says 16 but the code header says 17.

The configuration of a 23017 is different and more complex so the code you are using won't be adequate for a 17.

Are you driving LEDs or LCD?
If LEDS there are 36 (3 x 12) but don't see code for more than 16 LEDs

Can you give me a bit more info please.
 

evgerven

New Member
It's the 23017. Allright... Got to the point where recognition wins from jurisdiction :)

Looked into specs of the 23016 is less complex indeed...
Main differences are 23017 has extended cofiguration register, 2 address-mappings... and high speed I2C interface.

The extra's I don't need but the 23017 is cheaper.

Actually, there will be 2 23017's in my project. The code I supplied earlier is just to try out the functionality of the chip vs. Picaxe 18X

3 rows of 12 LED's will be used where the middle row - showing 10 of minutes - will have the LED's 2-by-2 connected, showing 00,10,...,50 minutes.

Per row, just 1 (or 2 in series) LED will be lit because the chip is not capable to drive all 16 outputs at once (summarised 320 mA where 200 mA is the chip-max rating)
 

evgerven

New Member
But more important...
My testsetup is still showing I2C commands are not always correct understood... It looks like the 23017 sometimes (repeatedly) misses some of them.
After a powerflip, it works correctly for a while until (after plm. 30 minutes) apparently some I2C commands are not taken by the 23017.
I tried i2cslow and i2cfast settings on the picaxe 18x but this makes no difference.
The AXE033 LCD, 1307 RTC and the temp sensors are connected to the same I2C-bus and working correct...
Standard decoupling is done (100nF cap.). Also tried an 100mF Elco extra to it made no difference.
Maybe I will give the LED's their own 5V supply, see if this helps
 

BCJKiwi

Senior Member
The speed setting actually supplies the wrong constant so slow and fast both produce around 33kHz. This was posted previously and due to be fixed by Rev-Ed on the next programmer update.

For now you can replace the fast/slow with the relevant number from the table below.
Code:
Functional Mode Parameters
    hi2csetup       PICAXE      i2c
    MODE            Clock       Clock
    ----------------------------------
    i2cany          any         32KHz
    137             4MHz        100kHz
    147             8MHz        100kHz
    167             16MHz       100kHz
    1               4MHz        400kHz
    4               8MHz        400kHz
    9               16MHz       400kHz
    For example:- 
        hi2csetup i2cmaster,RTC_0,167,i2cbyte
        where RTC_0 is the device address
    Speeds verified with an oscilloscope
    for a 28X1 at 16MHz [COLOR=black]clock speed.[/COLOR]
However, I doubt this is your problem but it might be worth a try.

Since you have 23017s, you will need to do more setup work to get it running right. There have been some good discussions on this chip on the forum which should help.

The right size current limiting resistors on the leds should enable all 16 ports to be run at the same time.

However I'm not sure I have been of much help and don't really know what to suggest next.

Generally if something works for a while then goes unstable, it's loose connections, heat buildup, or an accumulating error which takes time to reach the critical point.

In your test code above (if that is what you are actually running), the 23017's are re-initialised every full program cycle which is uneccessary.

You need only set up the registers etc once per power up.
You also only need to select the chip address once unless you switch between different chips.

perhaps you could try;
Code:
Initialise:
i2cslave %01000000, i2cslow, i2cbyte
writei2c $0A,($00,$00) 'IOCON0 cofiguration register
writei2c $00,($00,$00) 'Set portdirection to outputs
'plus other 23017 setup commands
 
IO_2:

for b0 = 0 to 8

lookup b0,(%11111111,%01111111,%10111111,%11011111,%11101 111,%11110111,%11111011,%11111101,%11111110),b1

for b3 = 0 to 2 
writei2c $13,(b1) 
pause 5
next
next
goto IO_2
just in case it makes a difference.
 

evgerven

New Member
the analogue clock is running fine now

Well... the problem was I definately needed the pause command after a i2c write.
Also, using debug pretty much messes up I2C also.
I knew the pause is needed but did make it a habit to do some calculating or other stuff instead of taking a pause.
In the setup is also an LCD (AXE 033... serial) active for monitoring until the LED display was fully functional..

The clock seem to run fine now. 2 rows of 12 LEDS (hrs and minutes) and 1 of 6 double LEDS (tens of minutes) shows time.
Every last 10 seconds on every minute the temperature (in degrees Celcius) is shown.
Every last second of a full minute I still reset the 2 IO chips... just to be sure.

I'll publish the results in the projects area when completely finished.

Thanks for your help,

Erik
 

BCJKiwi

Senior Member
Sample Code for both MCP23016 and MCP23017

Sample code for both MCP23016 and 17.

Note that the sample programs shown relate to sinking the current. The circuit this code is for has a common supply (PWM'd) to all the LEDS with the MCP23016/7 sinking to 0V to complete the circuit and turn on the LED.

MCP23017 is preferred device for new projects as;
Higher speeds supported
Cleaner I/O layout
Internal timing thus no R/C network required
Code is little different
Still available in DIP package

Have placed original 016 and new 017 code together here for ease of comparison/use.

Code:
#rem
'#################################################
'# For PICAXE-28X1, MCP23016 driving LEDS        #
'#################################################
#picaxe 28x1
SetFreq m8
'#################################################
Init:
 hi2csetup i2cmaster,%01000000,i2cslow_16,i2cbyte
       '%0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
       '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1'
       'If using multiple devices of different speeds on the bus,
       'then use this line to change speed and remove the [%01000000] in the next line.
 hi2cout [%01000000],6,($00,$00)       'IRDIR0,IRDIR1 set port direction register to output
       'Note:- MCP23016 documentation indicates this register pair (06 & 07) 
       'defaults to all 1's (all Inputs) on Power On Reset.
       'However if this register pair is not configured to all 0's (Outputs) there is no function when driving LEDS.
 hi2cout $0A,($00,$00)   'IOCON0  
IO_1:
 hi2cout 0,(%01010101,%01010101) 'GPO,GP1 Turn on each alternate output
       'A '0' bit to register 0 will turn ON current sink and a '1' will reverse to a current source
       'i.e. the port is not actually turned on or off but rather it's direction is reversed 
 pause 1250
 hi2cout 0,(%10101010,%10101010)
 pause 250
 hi2cout 0,(%01010101,%01010101)
 pause 1250
 hi2cout 0,(%10101010,%10101010)
 pause 250
Goto IO_1 'Loop
#Endrem
'#rem
'#################################################
'# For PICAXE-28X1, MCP23017 driving LEDS        #
'#################################################
#picaxe 28x1
SetFreq m16
'#################################################
Init:
'MCP23017
'Note setup register and data is the same as for MCP23016
'Direction and output registers are different
'
 hi2csetup i2cmaster,%01000000,i2cslow_16,i2cbyte ' or i2cfast_16
  '%0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
  '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1' - just a fixed part of the ID
 hi2cout [%01000000],0,($00,$00)  'IODIRA,IODIRB set port direction register to output
 hi2cout 8,($00,$00)     'IOCON0 Active driver output, Active Low - i.e sinks.
 hi2cout $12,(%11111111,%11111111) 'turn off all the LEDs (output High)
IO_1:
'GPI/O register number is different from MCP23016
 hi2cout $12,(%01010101,%01010101) 'GPO,GP1 Turn on each alternate output
       'A '0' bit to register 0 will turn ON current sink and a '1' will reverse to a current source
       'i.e. the port is not actually turned on or off but rather it's direction is reversed 
 pause 1250
 hi2cout $12,(%10101010,%10101010)
 pause 250
 hi2cout $12,(%01010101,%01010101)
 pause 1250
 hi2cout $12,(%10101010,%10101010)
 pause 250
Goto IO_1 'Loop
'#Endrem
 
Last edited:

Rasmus

New Member
Can't get the code for the mcp23017 to work

Hi,

I've tried the code for the mcp23017 but cant get it to work.

Its on a 28X1.

Anybody got it to work?

R.
 

BCJKiwi

Senior Member
Well I'm using the code supplied without problems.

Please post your code.
the device address you are using,
the way you have the MCP23017 address set on your circuit
What you want the chip to do.

The sample supplied provides for sinking from a high supply through the device to ground (i.e. sinks).

There are many other ways the chips can be used / set.
 

westaust55

Moderator
Having noted that I am frequently using a pair of PCF8574 8-bit chip IO Expanders, started to look towards using some MCP23017 16-bit IO Expanders instead.

Read up on MCP23017 code a bit thru BCJKiwis code snippets above.
Noted a couple of points in BCJKiwi’s example code that I will elaborate/clarify upon.

1. In the MCP23017 example he states:
Code:
hi2csetup i2cmaster,%01000000,i2cslow_16,i2cbyte ' or i2cfast_16
  '%0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
  '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1' - just a fixed part of the ID
The most significant four bits of the slave address are the “device type identifier”
This fixed part (first 4 bits) of the i2c 7-bit device slave address is defined by the I2C bus committee and is assigned based on device type.
I have created a separate post in the active section at:
http://www.picaxeforum.co.uk/showthread.php?p=81771#post81771
to explain a bit more about this with some examples.

2. In the example code the line:
Code:
hi2cout 8,($00,$00)     'IOCON0 Active driver output, Active Low - i.e sinks.
Actually registers 8 and 9 are for the INTCONA and INTCONB registers.

Through the use of other registers, input data can be inverted within the MCP23017 before being read by a master i2c device but output data cannot.
 

BCJKiwi

Senior Member
Yes well I started this thread a year ago when I had just got things working and there were a few others trying to get their head around it - the MCP23017 was a quick update from the original MCP23016 code.
 

westaust55

Moderator
For the MCP23017, the IOCON register(s) $0A and $0B are used for a totally different purpose to the register of the same name within the MCP23016.
For the MCP23017, these two registers may (?) need to be set, particularly if using more than one IO Expander device.

The power on and reset default values for these two registers is $00 (%0000 0000).
 
Last edited:

BCJKiwi

Senior Member
Iv'e not studied the Datasheet in ages and I guess I'll need to have another look but all I can say right now is that I doubt your analysis - why? Well I have 4 MCP23017s working in the same circuit along with 3 other i2c devices and they work just fine, and are correctly addressed.
The entire configuration code block for the 4 MCP23017s consists of;
Code:
'MCP23017
 hi2csetup i2cmaster,IO_0,i2cslow_16,i2cbyte
  '[IO_0] %0100 0  0  0  0 is the address with A0,A1,A2 all tied to 0V
  '%0100 A2 A1 A0 RW - there is no explanation for the 6th bit being '1' - just a fixed part of the ID
 hi2cout [IO_0],0,($00,$00)
 hi2cout 8,($00,$00)
 hi2cout $12,(%11111111,%11111111) 'turn off all the LEDs (output High)
 hi2cout [IO_1],0,($00,$00)
 hi2cout 8,($00,$00) 
 hi2cout $12,(%11111111,%11111111) 'turn off all the LEDs (output High)
 hi2cout [IO_2],0,($00,$00)
 hi2cout 8,($00,$00)  
 hi2cout $12,(%11111111,%11111111) 'turn off all the LEDs (output High)
 hi2cout [IO_3],0,($00,$00)
 hi2cout 8,($00,$00)
 hi2cout $12,(%11111111,%11111111) 'turn off all the LEDs (output High)
where [IO_0] etc contains the MCP23017 address set by 10k to +v or 0v.
 

westaust55

Moderator
Had another look through the datsheet. took a couple of passes.

Yes you are correct. The HAEN bit in the IOCON registers are only used on the SPI versions. It is ignored on the i2c versions.

There is a moral to this:

One cannot even believe all one reads in the datasheets.
In Micrchip datasheet DS21952B (2007) page 3 covering both the MCP23017 (i2c version)and MCP23S17 (SPI version) it does clearly state:
The two devices differ ONLY in the serial interface"

Ah well, live and learn :rolleyes:

Not the first time I have had a datasheet error to contend with. Another case that comes to mind is the E-Labs EDE1188 datasheet which states the output values are in the range 1 to 64 whereas the actual output values are 0 to 63,
 
Last edited:
Top