
Code: Select all
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $


My PCF8591 worked without adding any external pull-ups. I suppose the internal ones could be enabled by default.mahjongg wrote:i2c-0 doesn't have the 1K8 pullups included that the normal I2C port has, so you need to add them externally, like a HAT board does.
Here is what I use to enable communications on the i2c-0 bus. Is there something else that needs to be done?joan wrote:I've just bunged a PCF8591 on pins 27/28 etc., did the business in cmdline.txt, changed some gpio modes, and it's working fine.
Code: Select all
#!/usr/bin/python
#!/usr/bin/env python
#
# W. Greathouse 13-Feb-2013
#
# Enable I2C on P1 and P5 (Rev 2 boards only)
#
# #######
# For I2C configuration test
import os
import mmap
BCM2708_PERI_BASE=0x20000000
GPIO_BASE=(BCM2708_PERI_BASE + 0x00200000)
BLOCK_SIZE=4096
def _strto32bit_(str):
return ((ord(str[3])<<24) + (ord(str[2])<<16) + (ord(str[1])<<8) + ord(str[0]))
def _32bittostr_(val):
return chr(val&0xff) + chr((val>>8)&0xff) + chr((val>>16)&0xff) + chr((val>>24)&0xff)
def get_revision():
with open('/proc/cpuinfo') as lines:
for line in lines:
if line.startswith('Revision'):
return int(line.strip()[-4:],16)
raise RuntimeError('No revision found.')
def i2cConfig():
if get_revision() <= 3:
print "Rev 2 or greater Raspberry Pi required."
return
# Use /dev/mem to gain access to peripheral registers
mf=os.open("/dev/mem", os.O_RDWR|os.O_SYNC)
m = mmap.mmap(mf,BLOCK_SIZE, mmap.MAP_SHARED,
mmap.PROT_READ|mmap.PROT_WRITE,offset=GPIO_BASE)
# can close the file after we have mmap
os.close(mf)
# Read function select registers
# GPFSEL0 -- GPIO 0,1 I2C0 GPIO 2,3 I2C1
m.seek(0)
reg0=_strto32bit_(m.read(4))
# GPFSEL2 -- GPIO 28,29 I2C0
m.seek(8)
reg2=_strto32bit_(m.read(4))
# print bin(reg0)[2:].zfill(32)[2:]
# print bin(reg2)[2:].zfill(32)[2:]
# GPFSEL0 bits --> x[26] SCL0[3] SDA0[3]
# GPIO GPIO
m0 = 0b00000000000000000000111111111111
s0 = 0b00000000000000000000100100000000
b0 = reg0 & m0
if b0 <> s0:
#print "reg0 I2C configuration not correct. Updating."
reg0 = (reg0 & ~m0) | s0
m.seek(0)
m.write(_32bittostr_(reg0))
# GPFSEL2 bits --> x[2] SCL0[3] SDA0[3] x[24]
m2 = 0b00111111000000000000000000000000
s2 = 0b00100100000000000000000000000000
b2 = reg2 & m2
if b2 <> s2:
#print "reg2 I2C configuration not correct. Updating."
reg2 = (reg2 & ~m2) | s2
m.seek(8)
m.write(_32bittostr_(reg2))
# No longer need the mmap
m.close()
if __name__ == '__main__':
i2cConfig()
I thought I had seen some bash script to set the mode but it may have been false memory as I can't find it now.Richard-TX wrote:Joan,
Can you suggest a way to set the proper modes for GPIO-0 and 1?
Maybe something from the command line using the shell.?
Code: Select all
/*
2014-10-30
set_mode.c
Public Domain
gcc -o set_mode set_mode.c
sudo ./set-mode
*/
#include <stdio.h>
#include <unistd.h>
#include <stdint.h>
#include <fcntl.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#define GPIO_BASE 0x20200000
#define GPIO_LEN 0xB4
#define GPLEV0 13
#define GPLEV1 14
/* mode: 0-7 */
#define PI_INPUT 0
#define PI_OUTPUT 1
#define PI_ALT0 4
#define PI_ALT1 5
#define PI_ALT2 6
#define PI_ALT3 7
#define PI_ALT4 3
#define PI_ALT5 2
static volatile uint32_t * gpioReg = MAP_FAILED;
int gpioSetMode(unsigned gpio, unsigned mode)
{
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
gpioReg[reg] = (gpioReg[reg] & ~(7<<shift)) | (mode<<shift);
return 0;
}
int gpioGetMode(unsigned gpio)
{
int reg, shift;
reg = gpio/10;
shift = (gpio%10) * 3;
return (*(gpioReg + reg) >> shift) & 7;
}
main()
{
int fd;
fd = open("/dev/mem", O_RDWR | O_SYNC) ;
gpioReg = mmap(0,
GPIO_LEN,
PROT_READ|PROT_WRITE|PROT_EXEC,
MAP_SHARED|MAP_LOCKED,
fd,
GPIO_BASE);
close(fd);
if (gpioReg != MAP_FAILED)
{
gpioSetMode(17, PI_ALT3);
}
}
Code: Select all
s0 = 0b00000000000000000000100100100100
s2 = 0b00001001000000000000000000000000
Code: Select all
s2 = 0b00000000000000000000000000000000

the normal I2C doesn't have external 1K8 pullups for nothing you know! Internal pullups are extremely weak, in the 50K region, to0 weak to reliably work as I2C pullups.joan wrote:My PCF8591 worked without adding any external pull-ups. I suppose the internal ones could be enabled by default.mahjongg wrote:i2c-0 doesn't have the 1K8 pullups included that the normal I2C port has, so you need to add them externally, like a HAT board does.
On my (unmodified) B+ gpios 0 and 1 appear to have hard wired pull ups to 3V3.mahjongg wrote: ...
the normal I2C doesn't have external 1K8 pullups for nothing you know! Internal pullups are extremely weak, in the 50K region, to0 weak to reliably work as I2C pullups.
Been there ... got burned by it!
When I2C doesn't work, add them, even when you think you don't need them!
Code: Select all
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $ pigs mg 28 mg 29 # check 28/29 mode
4
4
harry ~ $ pigs m 28 r m 29 r # set 28/29 as inputs (r)
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $ pigs mg 0 mg 1
4
4
harry ~ $ pigs m 0 r m 1 r # set 0/1 as inputs
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $ pigs r 0 r 1 # read 0/1
1
1
harry ~ $ pigs pud 0 o pud 1 o # 0/1 pull-ups off
harry ~ $ pigs r 0 r 1
1
1
harry ~ $ pigs pud 0 d pud 1 d # 0/1 pull-down
harry ~ $ pigs r 0 r 1
1
1
harry ~ $ pigs w 0 0 w 1 0 # 0/1 output low
harry ~ $ pigs r 0 r 1
0
0
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $ pigs m 0 0 m 1 0 # change mode 0/1 to ALT0 (0)
harry ~ $ pigs r 0 r 1
1
1
harry ~ $ i2cdetect -y 0
0 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- 48 -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
harry ~ $
Code: Select all
#!/usr/bin/python
#!/usr/bin/env python
#
# W. Greathouse 13-Feb-2013
# Richard A. - Nov, 17 2014 - Now works for B, B+ and CM
# Enable I2C on P1 and P5 (Rev 2+ boards only)
#
# #######
# For I2C configuration test
import os
import mmap
bplus=0
BCM2708_PERI_BASE=0x20000000
GPIO_BASE=(BCM2708_PERI_BASE + 0x00200000)
BLOCK_SIZE=4096
def _strto32bit_(str):
return ((ord(str[3])<<24) + (ord(str[2])<<16) + (ord(str[1])<<8) + ord(str[0]))
def _32bittostr_(val):
return chr(val&0xff) + chr((val>>8)&0xff) + chr((val>>16)&0xff) + chr((val>>24)&0xff)
def get_revision():
with open('/proc/cpuinfo') as lines:
for line in lines:
if line.startswith('Revision'):
return int(line.strip()[-4:],16)
raise RuntimeError('No revision found.')
def i2cConfig():
if get_revision() >= 10:
print "B+ or CM detected."
s0 = 0b00000000000000000000100100100100
s2 = 0b00000000000000000000000000000000
if get_revision() <=9:
s0 = 0b00000000000000000000100100000000
s2 = 0b00100100000000000000000000000000
if get_revision() <= 3:
print "Rev 2 or greater Raspberry Pi required."
return
# Use /dev/mem to gain access to peripheral registers
mf=os.open("/dev/mem", os.O_RDWR|os.O_SYNC)
m = mmap.mmap(mf,BLOCK_SIZE, mmap.MAP_SHARED,
mmap.PROT_READ|mmap.PROT_WRITE,offset=GPIO_BASE)
# can close the file after we have mmap
os.close(mf)
# Read function select registers
# GPFSEL0 -- GPIO 0,1 I2C0 GPIO 2,3 I2C1
m.seek(0)
reg0=_strto32bit_(m.read(4))
# GPFSEL2 -- GPIO 28,29 I2C0
m.seek(8)
reg2=_strto32bit_(m.read(4))
# print bin(reg0)[2:].zfill(32)[2:]
# print bin(reg2)[2:].zfill(32)[2:]
# GPFSEL0 bits --> x[26] SCL0[3] SDA0[3]
# GPIO GPIO
m0 = 0b00000000000000000000111111111111
#s0 = 0b00000000000000000000100100100100
b0 = reg0 & m0
if b0 <> s0:
#print "reg0 I2C configuration not correct. Updating."
reg0 = (reg0 & ~m0) | s0
m.seek(0)
m.write(_32bittostr_(reg0))
# GPFSEL2 bits --> x[2] SCL0[3] SDA0[3] x[24]
m2 = 0b00111111000000000000000000000000
b2 = reg2 & m2
if b2 <> s2:
#print "reg2 I2C configuration not correct. Updating."
reg2 = (reg2 & ~m2) | s2
m.seek(8)
m.write(_32bittostr_(reg2))
# No longer need the mmap
m.close()
if __name__ == '__main__':
i2cConfig()

appear is the significant word here, There are four 1K8 pullups (real external resistors) on the B+, R21, R22, R23 and R24.joan wrote: On my (unmodified) B+ gpios 0 and 1 appear to have hard wired pull ups to 3V3.
I just tested gpios 0/1 when not attached to the PCF8591.mahjongg wrote:appear is the significant word here, There are four 1K8 pullups (real external resistors) on the B+, R21, R22, R23 and R24.joan wrote: On my (unmodified) B+ gpios 0 and 1 appear to have hard wired pull ups to 3V3.
Two are on GPIO 2 and 3 (SDA1 and SCL1 pins 3 and 5 of the GPIO header) the other two are on GPIO's 28 and 29 (SDA0 and SCL0 for the camera connector. There are NO pullups on GPIO's 0 and 1 (ID_SD and I_SC pins 27 and 28 for the HAT EEPROM, those 1K8 pullups are on the HAT boards). I2C can be finicky about it's pullups, for some functions slow pullups are okay, for other functions, not so much.
It could be that the presence of pullups on GPIO's 0 and 1 is actually used as a simple and fast way to detect the presence of a HAT.
Code: Select all
harry ~ $ pigs mg 0 mg 1 # get 0/1 mode
4
4
harry ~ $ pigs r 0 r 1 # read 0/1
1
1
harry ~ $ pigs pud 0 o pud 1 o # 0/1 PUD disabled
harry ~ $ pigs r 0 r 1 # read 0/1
0
0
harry ~ $ pigs pud 0 u pud 1 u # 0/1 PUD up
harry ~ $ pigs r 0 r 1 # read 0/1
1
1
harry ~ $ pigs pud 0 o pud 1 o # 0/1 PUD disabled
harry ~ $ pigs r 0 r 1 # read 0/1
0
0
harry ~ $ pigs r 0 r 1 # connect PCF8591 and read 0/1
1
1
harry ~ $ pigs r 0 r 1 # disconnect PCF8591 and read 0/1
0
0
harry ~ $
How do you read resistor values? Isn't 50k > 1,8k? Why is it "too weak" in this context?mahjongg wrote:the normal I2C doesn't have external 1K8 pullups for nothing you know! Internal pullups are extremely weak, in the 50K region, to0 weak to reliably work as I2C pullups.
Been there ... got burned by it!
When I2C doesn't work, add them, even when you think you don't need them!
The higher the resistance the smaller the current that can flow, so the "pull" is weaker.sukisan wrote:How do you read resistor values? Isn't 50k > 1,8k? Why is it "too weak" in this context?
"Burned" in this context mean wasted time.sukisan wrote:Hi
Can you elaborate what you mean by burned? Just "not working" or did anything (or anybody) got harmed?
And you'd only add them if I2C isn't working? How does a malfunctioning look like? Is it not working at all (easy to spot) or are there random transmission errors? Are these errors reported?
Thanks,
Suki
Code: Select all
+-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| | | 3.3v | | | 1 || 2 | | | 5v | | |
| 2 | 8 | SDA.1 | ALT0 | 1 | 3 || 4 | | | 5V | | |
| 3 | 9 | SCL.1 | ALT0 | 1 | 5 || 6 | | | 0v | | |
| 4 | 7 | GPIO. 7 | IN | 0 | 7 || 8 | 1 | ALT0 | TxD | 15 | 14 |
| | | 0v | | | 9 || 10 | 1 | ALT0 | RxD | 16 | 15 |
| 17 | 0 | GPIO. 0 | IN | 0 | 11 || 12 | 0 | IN | GPIO. 1 | 1 | 18 |
| 27 | 2 | GPIO. 2 | IN | 0 | 13 || 14 | | | 0v | | |
| 22 | 3 | GPIO. 3 | IN | 1 | 15 || 16 | 0 | IN | GPIO. 4 | 4 | 23 |
| | | 3.3v | | | 17 || 18 | 0 | IN | GPIO. 5 | 5 | 24 |
| 10 | 12 | MOSI | IN | 0 | 19 || 20 | | | 0v | | |
| 9 | 13 | MISO | IN | 0 | 21 || 22 | 0 | IN | GPIO. 6 | 6 | 25 |
| 11 | 14 | SCLK | IN | 0 | 23 || 24 | 1 | IN | CE0 | 10 | 8 |
| | | 0v | | | 25 || 26 | 1 | IN | CE1 | 11 | 7 |
| 0 | 30 | SDA.0 | IN | 1 | 27 || 28 | 1 | IN | SCL.0 | 31 | 1 |
| 5 | 21 | GPIO.21 | IN | 1 | 29 || 30 | | | 0v | | |
| 6 | 22 | GPIO.22 | IN | 1 | 31 || 32 | 0 | IN | GPIO.26 | 26 | 12 |
| 13 | 23 | GPIO.23 | IN | 0 | 33 || 34 | | | 0v | | |
| 19 | 24 | GPIO.24 | IN | 0 | 35 || 36 | 0 | IN | GPIO.27 | 27 | 16 |
| 26 | 25 | GPIO.25 | IN | 0 | 37 || 38 | 0 | IN | GPIO.28 | 28 | 20 |
| | | 0v | | | 39 || 40 | 0 | IN | GPIO.29 | 29 | 21 |
+-----+-----+---------+------+---+----++----+---+------+---------+-----+-----+
| BCM | wPi | Name | Mode | V | Physical | V | Mode | Name | wPi | BCM |
+-----+-----+---------+------+---+--B Plus--+---+------+---------+-----+-----+