User avatar
morphy_richards
Posts: 1603
Joined: Mon Mar 05, 2012 3:26 pm
Location: Epping Forest

python-smbus newbie

Fri Oct 12, 2012 3:31 pm

Hi,
I've been trying to use smbus to turn on some gpio pins on the mcp23008 GPIO port expander.

I'm not even certain I've got the addressing correct for this. I think I need to write this data though

1st byte. The address (0x20)
2nd Byte . Register address for GPIO (0x09)
3rd Byte. Gpio direction - all out (0x00)
4th byte. Bits to corresponding gpio pins (eg. 0b01010101)

Anyway; using the write_byte function in smbus how can I send this?
Would it be something like

Code: Select all

bus = smbus.SMBus(0)
bus.write_byte(0x20, 0x09)
bus.write_byte(0x20, 0x00)
bus.write_byte(0x20, 0b01010101)
?
I can try to run this and it works with no I/O error but I cant see anything happening to the gpio.

techpaul
Posts: 1512
Joined: Sat Jul 14, 2012 6:40 pm
Location: Reading, UK

Re: python-smbus newbie

Fri Oct 12, 2012 5:07 pm

I would start with the python-smbus function

write_i2c_block_data(addr,cmd,vals)

That is

Code: Select all

write_i2c_block_data(0x20,i,,0x09, 0, 0x55)
From command prompt try "man python-smbus" My 'i' for cmd is from memory so check that
Just another techie on the net - For GPIO boards see http:///www.facebook.com/pcservicesreading
or http://www.pcserviceselectronics.co.uk/pi/

User avatar
morphy_richards
Posts: 1603
Joined: Mon Mar 05, 2012 3:26 pm
Location: Epping Forest

Re: python-smbus newbie

Mon Oct 15, 2012 3:24 pm

Thanks techpaul...

Strangely
bus.write_i2c_block_data(0x20,0,[0x09, 0x00, 0b10101010])

Just sends 0b1001 (0x09) to the GPIO as output. The first number in the list is always sent as an output to the GPIO and it seems to always ignore the other bytes. So I cant physically select the GPIO register or set the register value. That suggests I'm going to struggle when it comes to setting these as inputs.

What's stranger is that I can only turn on half the GPIOs and it's only the even numbered ones.

So,
bus.write_i2c_block_data(0x20,0,[0b10101010])
turns on the corresponding ones (actually a 0 turns the gpio output "on") however
#bus.write_i2c_block_data(0x20,0,[0b01010101])
and nothing comes on at all.

I can only access 0,2,4,6
1,3,5,7 do nothing it seems.

Perplexing :?

techpaul
Posts: 1512
Joined: Sat Jul 14, 2012 6:40 pm
Location: Reading, UK

Re: python-smbus newbie

Mon Oct 15, 2012 3:35 pm

morphy_richards wrote:Thanks techpaul...

Strangely
bus.write_i2c_block_data(0x20,0,[0x09, 0x00, 0b10101010])
Why you using a cmd paramater of 0x00 ?

Check man page and even in python
help( "modules, smbus")

To see what it says about cmd parameter, not got access at moment to module.

without seeing a small test programme from the import to the first write block command I cannot comment further.
Just another techie on the net - For GPIO boards see http:///www.facebook.com/pcservicesreading
or http://www.pcserviceselectronics.co.uk/pi/

User avatar
morphy_richards
Posts: 1603
Joined: Mon Mar 05, 2012 3:26 pm
Location: Epping Forest

Re: python-smbus newbie

Tue Oct 16, 2012 1:00 pm

techpaul wrote:
Why you using a cmd paramater of 0x00 ?

Check man page and even in python
help( "modules, smbus")
I've been struggling to find relevant man/help pages. Closest I can find is man entries for i2cget and i2cset.

I was looking at this http://wiki.erazor-zone.de/wiki:linux:python:smbus:doc which is quite useful but short on specifics.

So, using smbus I've been trying a suck it and see approach.

Code: Select all

import smbus
import time
from itertools import cycle

bus = smbus.SMBus(0)

bus.write_i2c_block_data(0x20,0,[0x0])
cycling_bits = [1 << n for n in range(0,8)] 
for i in cycle(cycling_bits):
 print i
 bus.write_i2c_block_data(0x20,0,[i])
 time.sleep(0.01)
 
Is what I have been experimenting with currently.

I can make this work using the alternative "quick2wire" API like this:

Code: Select all

#!/usr/bin/env python3
import quick2wire.i2c as i2c
import time
from itertools import cycle

address = 0x20
iodir_register=0x00
gpio_register=0x09

with i2c.I2CMaster() as master:
	
 master.transaction(
  i2c.writing_bytes(address, gpio_register, 0b00000000))
  
 cycling_bits = [1 << n for n in range(0,8)] 
 for i in cycle(cycling_bits):     
  print (i)
  master.transaction(
   i2c.writing_bytes(address, gpio_register, i))
  time.sleep(0.5)        
        
...but I would like to know if this can be accomplished using smbus. Quick2wire worries me a little as it's still being developed and so anything I code is potentially subject to bitrot. Plus, I'd just like to understand how to do it :)

User avatar
DougieLawson
Posts: 42232
Joined: Sun Jun 16, 2013 11:19 pm
Location: A small cave in deepest darkest Basingstoke, UK

Re: python-smbus newbie

Sun Dec 29, 2013 11:25 pm

Lets look at the data sheet and we see this is exactly half a MCP23017

There's two registers we're interested in and each of those registers accepts 8bits of data on a write operation.

First is bus:1 dev: 0x20 reg: 0x00
Second is bus:1 dev: 0x20 reg: 0x09

Depending on how you set the bits in reg 0x00 sets whether reg: 0x09 is input or output. If a bit is set to 0b1 then it's input, if the bit is set 0b0 then it's output. The default at power on is 0b11111111 (0xFF) or all input. You can't make any assumptions of the voltage level if a pin is set to input unless you set reg: 0x06 to configure an input pull-up of 100kΩ.

So this code

Code: Select all

import smbus
bus = smbus.SMBus(1) # on a RPi REV2 board
bus.write_byte_data(0x20,0x00,0x00)   # set every GPIO to output
bus.write_byte_data(0x20,0x09,0xFF)  # set them all on
bus.write_byte_data(0x20,0x09,0x00)  # set them all off
bus_write_byte_data(0x20,0x00,0xFF) # set all to input
iodata = bus_read_byte_dat(0x20,0x09)          # and read the values.
should get you going.
Languages using left-hand whitespace for syntax are ridiculous

DMs sent on https://twitter.com/DougieLawson or LinkedIn will be answered next month.
Fake doctors - are all on my foes list.

The use of crystal balls and mind reading is prohibited.

Return to “Interfacing (DSI, CSI, I2C, etc.)”