MCP230XX library problem

Moderators: adafruit_support_bill, adafruit

Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/
Locked
stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

MCP230XX library problem

Post by stefanet »

Hi guys,

i have a problem with adafruit_mcp230xx python libraries from github.

My code is

Code: Select all

try:
    from Adafruit_MCP230xx import Adafruit_MCP230XX
    import sys, time
    """
    The MCP23017 has 16 pins - A0 thru A7 + B0 thru B7. A0 is called 0 in the library, and A7 is called 7, then B0 continues from there as is called 8 and finally B7 is pin 15

    """

    # Base variable settings
    OUTPUT = 0
    INPUT = 1
    DISABLE = 0
    ENABLE = 1

    sensor = 8 # GPB0
    door = 9 # GPB1
    door_led = 11 # GPB3

    mcp = Adafruit_MCP230XX( busnum = 1, address = 0x20, num_gpios = 16 )

    # GPIO MCP230xx OUTPUT settings
    mcp.config( door_led, OUTPUT)

    # GPIO MCP230xx Input settings with Pull-UP resistor
    mcp.pullup( sensor, 1 )
    mcp.pullup( door, 1 )

    while ( True ):
        # Pir Sensor
        if not mcp.input( sensor ):
            print "Sensor:" + str( mcp.input( sensor ) )

        # Magnetic Door switch
        if not mcp.input( door ):
            print "Door:" + str( mcp.input( door ) )
            mcp.output( door_led, ENABLE )

        time.sleep(0.3)
except KeyboardInterrupt:
    sys.exit(127)
When i run it I have the following error:

Code: Select all

Traceback (most recent call last):
  File "switch.py", line 31, in <module>
    if not mcp.input( sensor ):
  File "/root/Adafruit_MCP230xx.py", line 118, in input
    assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
AssertionError: Pin 8 not set to input
If I comment out the mcp output settings, it works fine.
Why? Where is my error?
It seems to loose the input settings. I'm confused.

Following another code correctly runned

Code: Select all

# -*- coding: iso-8859-15 -*-
try:
    from Adafruit_MCP230xx import Adafruit_MCP230XX
    import re, sys, time
    """
    The MCP23017 has 16 pins - A0 thru A7 + B0 thru B7. A0 is called 0 in the library, and A7 is called 7, then B0 continues from there as is called 8 and finally B7 is pin 15

    mapping
    pin1 = col2 = gpio7 => col[1] = 7
    pin3 = col1 = gpio5 => col[0] = 5
    pin5 = col3 = gpio3 => col[2] = 3
    pin2 = raw1 = gpio6 => raw[0] = 6
    pin4 = raw4 = gpio4 => raw[3] = 4
    pin6 = raw3 = gpio2 => raw[2] = 2
    pin7 = raw2 = gpio1 => raw[1] = 1

    """

    # Base variable settings
    OUTPUT = 0
    INPUT = 1
    code = ""

    # keypad array settings
    raw = [ 6, 1, 2, 4 ]
    col = [ 5, 7, 3 ]
    keypad = [ [ '1', '2', '3' ] , [ '4', '5', '6' ], [ '7', '8', '9' ], [ '*', '0', '#' ] ]

    mcp = Adafruit_MCP230XX( busnum = 1, address = 0x20, num_gpios = 16 )
    # GPIO MCP230xx OUTPUT settings
    for gp_out in col:
        mcp.config( gp_out, OUTPUT)

    # GPIO MCP230xx Input settings with Pull-UP resistor
    for gp_in in raw:
        mcp.pullup( gp_in, 1 )

    while ( True ):
        # Base column settings
        for gp_out in col:
            mcp.output( gp_out, 1) # 
        # Column scans
        for col_sel in col:
            # set column to 0 value
            mcp.output(col_sel, 0)

            # Raw scans
            for raw_sel in raw:
                if mcp.input(raw_sel) == 0: # Key pressed
                    value = keypad [ raw.index(raw_sel)][ col.index(col_sel) ] # get key value
                    code += value # building code
                    #print "|" + code + "| - " + str(raw.index(raw_sel)) + ":" + str(col.index(col_sel))

                    if re.search( '^(\d|#)', code ): # If not start with '*' reset code variable: code must start with '*'
                        code = ""
                    if re.search( '(\*(\d+)#)', code ): # Ok code between '*' and '#'
                        print re.match( '.*(\*(\d+)#)', code ).group(2)
                        code = ""

                    while mcp.input(raw_sel) == 0: # wait until key released
                        time.sleep(0.1)

        time.sleep(0.1)

except KeyboardInterrupt:
    sys.exit(127)
Why?

Regards,
Stefano

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

i would guess that you were previously using pin 8 as an output. if the mcp23017 has not been powered down it will remember that. either get in the habit of explicitly setting your inputs to input or modify your copy of the library so that the mcp230xx constructor clears the data direction registers.

stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

Re: MCP230XX library problem

Post by stefanet »

But I never set pin 8 to OUTPUT as you can see...

It's the same if I change the output pin ^_^

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

actually, i can't see. i have no idea what code you were running day before yesterday. if you haven't turned off the power the mcp23017 will remember its state. have you tried explicitly setting the input to input? this would be good programming practice.

stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

Re: MCP230XX library problem

Post by stefanet »

Yes, i turned off the power and I never set OUTPUT for this pin. So I don't known how it can remember this.

Yes, I set initial state to INPUT by mcp.pullup( pin ).

I don't understand. :cry:

Regard,

Stefano

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

mcp.pullup sets the pullup for the pin, it does not set the pin to input. you need a call to mcp.config to do that, although it's true that the startup state for the pins is supposed to be input.

you could try reading the control registers on the mcp23017 to see what's going on.

stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

Re: MCP230XX library problem

Post by stefanet »

Yes, I'll try it as possible.

I follow an adafruit guide:

http://learn.adafruit.com/mcp230xx-gpio ... he-library

It shows thant pullup function set pin to input mode.

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

ah, but i read the datasheet. setting the pullup has no effect on the data direction register. as near as i can tell the adafruit library does not set the data direction pin when the pullup is enabled.

it is true, however, that the power up state of the data direction register is all pins set to input, but i don't understand why people do not want to bother with something as simple as

Code: Select all

    mcp.config( 8, INPUT)
it's just good practice to not make assumptions about the state of the registers. it also makes your code somewhat self documenting.

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

damn. i've been soooooo wrong. the adafruit library does initialize all of the gpios to inputs.

i didn't notice when i looked at the code. i didn't notice as i was adding a dump function to the mcp230xx class.

but when i ran my new dump function, sure enough, everything started out as inputs even though i had left some pins set as outputs. so i looked at the library, again. boy, do i feel stupid.

i was right, however, that enabling pullups has nothing to do with setting a pin as input. it would be an input even if you didn't enable the pullup.

here's the function i added to the Adafruit_MCP230xx class...

Code: Select all

    def dump (self) :
       if self.num_gpios == 8 :
          return {'IODIRA' : self.i2c.readU8 (0),
                  'IPOLA' : self.i2c.readU8 (1),
                  'GPINTENA' : self.i2c.readU8 (2),
                  'GPPUA' : self.i2c.readU8 (6),
                  'GPIOA' : self.i2c.readU8 (9),
                  'GPOLATA' : self.i2c.readU8 (10)}
       else :
          iocon = self.i2c.readU8 (10)
          return {'IODIRA' : self.i2c.readU8 (0),
                  'IPOLA' : self.i2c.readU8 (2),
                  'INTENA' : self.i2c.readU8 (4),
                  'DEFVALA' : self.i2c.readU8 (6),
                  'INTCONA' : self.i2c.readU8 (8),
                  'IOCON' : {'bank' : iocon >> 7 & 1, 'mirror' : iocon >> 6 & 1,
                             'seqop' : iocon >> 5 & 1, 'disslw' : iocon >> 4 & 1,
                             'haen' : iocon >> 3 & 1, 'odr' : iocon >> 2 & 1,
                             'intpol' : iocon >> 1 & 1},
                  'PUA' : self.i2c.readU8 (12),
                  'INTFA' : self.i2c.readU8 (14),
                  'INTCAPA' : self.i2c.readU8 (16),
                  'GPIOA' : self.i2c.readU8 (18),
                  'OLATA' : self.i2c.readU8 (20),
                  'IODIRB' : self.i2c.readU8 (1),
                  'IPOLB' : self.i2c.readU8 (3),
                  'INTENB' : self.i2c.readU8 (5),
                  'DEFVALB' : self.i2c.readU8 (7),
                  'INTCONB' : self.i2c.readU8 (9),
                  'IOCON2' : self.i2c.readU8 (11),
                  'PUB' : self.i2c.readU8 (13),
                  'INTFB' : self.i2c.readU8 (15),
                  'INTCAPB' : self.i2c.readU8 (17),
                  'GPIOB' : self.i2c.readU8 (19),
                  'OLATB' : self.i2c.readU8 (21)}
here's what i stuck at the end of the file to test my new function...

Code: Select all

    from time import sleep
    mcp = Adafruit_MCP230XX(address = 0x20, num_gpios = 16, busnum = 1)
    print "mcp230017 initialized"
    print mcp.dump ()
    mcp.config(0, mcp.OUTPUT)
    mcp.config(1, mcp.OUTPUT)
    mcp.config(2, mcp.OUTPUT)
    mcp.config(7, mcp.INPUT)
    mcp.pullup(3,1)
    print "PORTA 0,1,2 set as output. PORTA 3 set as input with PUP enabled.
    print mcp.dump ()
    while mcp.input(3) :
      pass
    print "Button on PORTA pin 3 pressed.
    print mcp.dump ()
    for i in range (5) :
      mcp.output (0, 1)
      sleep (1)
      mcp.output (0, 0)
      sleep (1)
here's the output...

Code: Select all

pi@raspberrypi ~/Adafruit-Raspberry-Pi-Python-Code/Adafruit_MCP230xx $ sudo ./Adafruit_MCP230xx.py            
mcp230017 initialized                                                                                         
{'OLATA': 8, 'INTCAPA': 0, 'INTCAPB': 0, 'IODIRA': 255, 'IODIRB': 255, 'INTCONA': 0, 'INTCONB': 0, 'IOCON2': 0, 'IOB': 0, 'INTENA': 0, 'INTENB': 0, 'OLATB': 0, 'INTFB': 0, 'GPIOA': 8, 'IPOLB': 0, 'IPOLA': 0, 'DEFVALA': 0, 'DEFVALB': 0, 'IOCON': {'haen': 0, 'odr': 0, 'intpol': 0, 'seqop': 0, 'mirror': 0, 'disslw': 0, 'bank': 0}, 'INTFA': 0, 'PUA': 0, 'PUB': 0}                                                           
PORTA 0,1,2 set as output. PORTA 3 set as input with PUP enabled.                                                                                  
{'OLATA': 8, 'INTCAPA': 0, 'INTCAPB': 0, 'IODIRA': 248, 'IODIRB': 255, 'INTCONA': 0, 'INTCONB': 0, 'IOCON2': 0, 'IOB': 0, 'INTENA': 0, 'INTENB': 0, 'OLATB': 0, 'INTFB': 0, 'GPIOA': 8, 'IPOLB': 0, 'IPOLA': 0, 'DEFVALA': 0, 'DEFVALB': 0, 'IOCON': {'haen': 0, 'odr': 0, 'intpol': 0, 'seqop': 0, 'mirror': 0, 'disslw': 0, 'bank': 0}, 'INTFA': 0, 'PUA': 8, 'PUB': 0}                                                                                
Button on PORTA pin 3 pressed.                                                                                                                     
{'OLATA': 8, 'INTCAPA': 0, 'INTCAPB': 0, 'IODIRA': 248, 'IODIRB': 255, 'INTCONA': 0, 'INTCONB': 0, 'IOCON2': 0, 'IOB': 0, 'INTENA': 0, 'INTENB': 0, 'OLATB': 0, 'INTFB': 0, 'GPIOA': 0, 'IPOLB': 0, 'IPOLA': 0, 'DEFVALA': 0, 'DEFVALB': 0, 'IOCON': {'haen': 0, 'odr': 0, 'intpol': 0, 'seqop': 0, 'mirror': 0, 'disslw': 0, 'bank': 0}, 'INTFA': 0, 'PUA': 8, 'PUB': 0}
perhaps you'll find it helpful. sorry about my idiotic blathering.

stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

Re: MCP230XX library problem

Post by stefanet »

Well, i done some tests.

The Adafruit_MCP230XX library seems to be wrong in line 118. This line checks the direction.
If pin direction return 1 it's configured to INPUT else to OUTPUT. This check is inverted

I changed

Code: Select all

assert self.direction & (1 << pin) != 0, "Pin %s not set to input" % pin
to

Code: Select all

assert self.direction & (1 << pin) != 1, "Pin %s not set to input" % pin
and now it runs.

My "final" code is

Code: Select all

#!/usr/bin/python
# -*- coding: iso-8859-15 -*-
try:
    from Adafruit_MCP230xx import Adafruit_MCP230XX
    import sys, time, smbus
    """
    The MCP23017 has 16 pins - A0 thru A7 + B0 thru B7. A0 is called 0 in the library, and A7 is called 7, then B0 continues from there as is called 8 and finally B7 is pin 15

    """

    # Base variable settings
    OUTPUT = 0
    INPUT = 1
    DISABLE = 0
    ENABLE = 1

    sensor = 8 # GPB0
    door = 9 # GPB1
    door_led = 11 # GPB3

    mcp = Adafruit_MCP230XX( busnum = 1, address = 0x20, num_gpios = 16 )

    #print mcp.dump ()

    # MCP230xx GPIO Direction settings
    mcp.config ( sensor, INPUT)
    mcp.config ( door, INPUT)
    mcp.config( door_led, OUTPUT)

    # MCP230xx GPIOPull-UP resistor 
    mcp.pullup( sensor, ENABLE )
    mcp.pullup( door, ENABLE )

    #print mcp.dump()

    while ( True ):
        if mcp.input( sensor ):
            print "Sensor:" + str( mcp.input( sensor ) )

        if mcp.input( door ):
            #print "Door:" + str( mcp.input( door ) )
            mcp.output( door_led, ENABLE )
        else:
            mcp.output( door_led, DISABLE )

        time.sleep(0.2)

except KeyboardInterrupt:
    sys.exit(127)
Sensor is PIR sensor and door is magnetic door switch. When I open door a red LED is on and when i close it the LED is off.

tldr
 
Posts: 466
Joined: Thu Aug 30, 2012 1:34 am

Re: MCP230XX library problem

Post by tldr »

only problem is is that that's not an error. what assert does is say this condition has to be fulfilled and if it's not die horribly and print this message.

i can speak with some authority on this topic because i just looked it up in a book that probably outweighs my brain.

stefanet
 
Posts: 6
Joined: Mon Feb 25, 2013 5:37 pm

Re: MCP230XX library problem

Post by stefanet »

Hi,

The MCP230XX library have many bugs.
I found a patch by bbkiwi on github to solve the problem.

https://github.com/adafruit/Adafruit-Ra ... de/pull/27

Thanks
Stefano

Locked
Forum rules
Talk about Adafruit Raspberry Pi® accessories! Please do not ask for Linux support, this is for Adafruit products only! For Raspberry Pi help please visit: http://www.raspberrypi.org/phpBB3/

Return to “Adafruit Raspberry Pi® accessories”