Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Change I2C speed

Fri Feb 22, 2013 3:41 pm

Hi people

I've found this forum extremely useful and helpful earlier, so I'm hoping someone can point in hte right direction again.

I've gotten both i2c busses working (is trying to communicate with two devices with the same fixed address) and have it sort of working. But I think 100KHz is too fast. The only sample I've seen of the thing working was at 28KHz...

So my question is, is there a way for me to change the speed of i2c.

I've tried writing to the DIV register, but changes here seems to be overwritten when I try using the i2c.

I've had some success changing the DEL register to 0x06300630 and the CLKT to 0x0000FFFF. These changes decreased my error rate by a factor of 10, but I still see errors.
I've also noted that my device seems to report 'unknown error' in it's status register. As a note, there's no error indicating the the i2c is running too fast or similar, so I'm hoping lowering the i22c speed will do the trick. If possible...

I have added pull-ups to i2c0 on P5, and I see the same error rate on both i2c buses.

I/m using 2013-02-09-wheezy-raspbian.

I've seem posts which seems to suggest that the control I desire is possible but I can't figure out how. It's likely a trivial GNU/linux issue, but I'm very much a GNU/linux noob.

Thanks in advance

User avatar
Gert van Loo
Posts: 2486
Joined: Tue Aug 02, 2011 7:27 am
Contact: Website

Re: Change I2C speed

Fri Feb 22, 2013 3:54 pm

Raguel,
how do you access the I2C?
Are you using direct register read/write are you using Python drivers or what?
I always map the registers and then directly access them.
That prevents the uncertainty that something changes them 'behind my back' and in that case
the clock divider register works fine.

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Change I2C speed

Sat Feb 23, 2013 9:40 am

Hi Gert

I'm sorry, I should have realized that code would be useful.

While writing this reply and retesting to make sure I hadn't made some stupid blunder I realized that I previously only ran this as part of my overall i2c communication and thus hadn't separated these register writes from my use of python-smbus for actual communication

I've looked a bit further into this and it looks like my problems come from python-smbus.

if I run this code only all values seems to be retained, but after sending a command using python-smbus the DIV value is changed

Code: Select all

#!/usr/bin/env python
#
#  23-Feb-2013
#
#   attempt to slow dowm I2C1 or change other timing parameters to communicate (Rev 2 boards only)
#   DIV register cannot be changed this way. it reverts back before any I2C communication, probably set by driver
#
# #######
import os
import mmap

BCM2708_PERI_BASE=0x20000000
I2C0_BASE=(BCM2708_PERI_BASE + 0x00205000)
I2C1_BASE=(BCM2708_PERI_BASE + 0x00804000)
BLOCK_SIZE=4096
DIV_OFFSET=0x14
DELAY_OFFSET=0x18
CLKT_OFFSET=0x1C

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 i2c_chgClk(i2c):
    if get_revision() <= 3:
        print "Rev 2 or greater Raspberry Pi required."
        return
    
    #determine which i2c is being set up
    if i2c == 0:
        I2C_BASE=I2C0_BASE
    elif i2c == 1:
        I2C_BASE=I2C1_BASE
    else:
        print "Only 0 or 1 is accepted as i2c bus"
        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=I2C_BASE)
    # can close the file after we have mmap
    os.close(mf)

    # Read I2C registers
    # DIVider
    m.seek(DIV_OFFSET)
    div=_strto32bit_(m.read(4))
    # DEL data delay
    m.seek(DELAY_OFFSET)
    delay=_strto32bit_(m.read(4))
    # CLKT clock stretch timeout
    m.seek(CLKT_OFFSET)
    clkt=_strto32bit_(m.read(4))

    print bin(div)[2:].zfill(32)[2:]
    # print bin(delay)[2:].zfill(32)[2:]
    # print bin(clkt)[2:].zfill(32)[2:]

    # DIV bits -->
    #
    m0 = 0b00000000000000001111111111111111
    s0 = 0b00000000000000001100000000000000
    b0 = div & m0
    if b0 <> s0:
        print "div I2C", i2c, " configuration not correct. Updating."
        div = (div & ~m0) | s0
        m.seek(DIV_OFFSET)
        m.write(_32bittostr_(div))

    print 'new', bin(div)[2:].zfill(32)[2:] #value just written
    m.seek(DIV_OFFSET)
    div=_strto32bit_(m.read(4))
    print 'rb ', bin(div)[2:].zfill(32)[2:] #read back from mmap



    # DELay bits
    m1 = 0b11111111111111111111111111111111
    s1 = 0b00000110001100000000011000110000
    b1 = delay & m1
    if b1 <> s1:
        print "delay I2C", i2c, " configuration not correct. Updating."
        delay = (delay & ~m1) | s1
        m.seek(DELAY_OFFSET)
        m.write(_32bittostr_(delay))

    # CLKT bits
    m2 = 0b00000000000000001111111111111111
    s2 = 0b00000000000000001111111111111110
    b2 = clkt & m2
    if b2 <> s2:
        print "clkt I2C", i2c, " configuration not correct. Updating."
        clkt = (clkt & ~m2) | s2
        m.seek(CLKT_OFFSET)
        m.write(_32bittostr_(clkt))

    # No longer need the mmap
    m.close()


if __name__ == '__main__':
    i2c_chgClk(0)
    i2c_chgClk(1)
    i2c_chgClk(2)
So I'm guessing that I either need to write my own driver or ask around how to get python-smbus to accept my new DIV value

I'm a Python noob too, so any comments on the code would be appreciated. I'm from a deeply embedded asm and a little C background on tiny devices, so this high level stuff is a new experience I've been pushed into.
I've based the code heavily on code written by bgreat for getting i2c0 on P5 in a different topic

I'll create a new topic tomorrow regarding python-smbus if no one beats me to it and answers my question here.
I'm on Pacific time and my 2year old tend to get up around 6am, so that gives me 4 hours

Thanks
Raguel

wallasey
Posts: 26
Joined: Fri Nov 16, 2012 5:10 pm

Re: Change I2C speed

Sat Feb 23, 2013 2:44 pm

Hi,

If using SMBus you can control the bus speed directly with the device driver:

sudo modprobe - r i2c_bcm2708
sudo modprobe i2c_bcm2708 baudrate=32000

seems to be the setting that has everything working for me. You can check the existing/default "baudrate" with

sudo cat /sys/module/i2c_bcm2708/parameters/baudrate

I think the way to make this permanent on startup is with an entry somewhere in /etc/modprobe.d/

options i2c_bcm2708 baudrate=32000

Hope it helps.

Mark

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Change I2C speed

Sat Feb 23, 2013 7:57 pm

Thx for the pointer.

I'll try it out.
Will need to find a way of making it permanent

Raguel

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Change I2C speed

Sat Feb 23, 2013 10:08 pm

No luck

I get this:

Code: Select all

[email protected] ~ $ sudo modprobe - r i2c_bcm2708
FATAL: Module - not found.
[email protected] ~ $ sudo cat /sys/module/i2c_bcm2708/parameters/baudrate
100000
and issuing sudo modprobe i2c_bcm2708 baudrate=32000 changes nothing
As i said I'm a total noob with Linux, so this leaves me baffled

I've made sure i2c is not blacklisted, and issuing lsmod I get this

Code: Select all

[email protected] ~ $ lsmod
Module                  Size  Used by
i2c_dev                 5620  0
snd_bcm2835            15846  0
snd_pcm                77560  1 snd_bcm2835
snd_seq                53329  0
snd_timer              19998  2 snd_pcm,snd_seq
snd_seq_device          6438  1 snd_seq
snd                    58447  5 snd_bcm2835,snd_timer,snd_pcm,snd_seq,snd_seq_device
snd_page_alloc          5145  1 snd_pcm
spidev                  5224  0
joydev                  9316  0
8192cu                489381  0
evdev                   9426  2
leds_gpio               2235  0
led_class               3562  1 leds_gpio
spi_bcm2708             4510  0
i2c_bcm2708             3759  0
[email protected] ~ $ modinfo i2c_bcm2708
filename:       /lib/modules/3.6.11+/kernel/drivers/i2c/busses/i2c-bcm2708.ko
alias:          platform:bcm2708_i2c
license:        GPL v2
author:         Chris Boot <[email protected]>
description:    BSC controller driver for Broadcom BCM2708
srcversion:     FF4BB0918EC1184000E2E24
depends:
intree:         Y
vermagic:       3.6.11+ preempt mod_unload modversions ARMv6
parm:           baudrate:The I2C baudrate (uint)
[email protected] ~ $ sudo modprobe - r i2c_bcm2708
FATAL: Module - not found.
Can anyone explain? Or should I just create a new topic elsewhere in the forum?

Raguel

wallasey
Posts: 26
Joined: Fri Nov 16, 2012 5:10 pm

Re: Change I2C speed

Sun Feb 24, 2013 2:33 am

Hi,

Spaces where there should be none in my original post. No space between dash and r for unloading. Code is:

Code: Select all

sudo modprobe -r i2c_bcm2708
sudo modprobe i2c_bcm2708 baudrate=32000
To make permanent, you can put a conf file in /etc/modprobe.d/ containing the line:

Code: Select all

options i2c_bcm2708 baudrate=32000

It does not matter what the file is called so long as it ends in '.conf'
I call mine /etc/modprobe.d/custom.conf You can set up this file the first time with the command:

Code: Select all

sudo sh -c 'echo "options i2c_bcm2708 baudrate=32000\n" > /etc/modprobe.d/custom.conf
Later edits can be done with
sudo nano /etc/modprobe.d/custom.conf

Hope it helps

Mark

Ragu3l
Posts: 17
Joined: Thu Feb 07, 2013 9:29 pm

Re: Change I2C speed

Sun Feb 24, 2013 3:11 am

Thx Mark

I'll give this a try when I get a chance.
I need to take some time and read up on linux

Raguel

mward
Posts: 1
Joined: Thu Mar 05, 2015 10:17 am

Re: Change I2C speed

Thu Mar 05, 2015 10:52 am

I am trying to lower the I2C speed to allow a longer cable.

Code: Select all

sudo modprobe i2c_bcm2708 baudrate=32000
does not give an error, but the speed returned by:

Code: Select all

sudo cat /sys/module/i2c_bcm2708/parameters/baudrate
is still 100000. I also tried creating a file /etc/modprobe.d/i2c.conf with the contents:

Code: Select all

options i2c_bcm2708 baudrate=50000
and rebooting, but this also had no effect.

Edit: it seems that with the new device tree, we cannot set the baud rate via modprobe. Instead we need to edit /boot/config.txt and add this line:

Code: Select all

dtparam=i2c1_baudrate=50000
and then reboot. The rate can be set as low as 5 kHz (5000).

LinuxCircle
Posts: 26
Joined: Sat May 04, 2013 2:03 am
Contact: Website

Re: Change I2C speed

Mon Aug 10, 2015 12:31 am

Hi I have been trying to program I2C Fm receiver namely TEA5767.

It runs ok with C, but not Python 3 smbus, or the Adafruit I2C driver, or pigpio.

It gives me Input Output error no 5, around 95% each time I send bytecodes to it to change the fm frequency. I wonder if it has anyhing to do with mismatching baud rate as it accepts the bytecode commands very occassionaly
www.linuxcircle.com

User avatar
joan
Posts: 14378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Change I2C speed

Mon Aug 10, 2015 7:57 am

LinuxCircle wrote:Hi I have been trying to program I2C Fm receiver namely TEA5767.

It runs ok with C, but not Python 3 smbus, or the Adafruit I2C driver, or pigpio.

It gives me Input Output error no 5, around 95% each time I send bytecodes to it to change the fm frequency. I wonder if it has anyhing to do with mismatching baud rate as it accepts the bytecode commands very occassionaly
I'd double check your connections, and if it still doesn't work I'd double check again but more carefully. It does sound like a poor connection. Ages ago I played with a RDA5807M (which from memory can work in TEA5767 compatibility mode) and don't remember any particular problems.

Perhaps a photo of your set up would be useful.

LinuxCircle
Posts: 26
Joined: Sat May 04, 2013 2:03 am
Contact: Website

Re: Change I2C speed TEA5767

Mon Aug 10, 2015 12:43 pm

Hi,
Connection is as follows:
http://www.svesoftware.com/images/pinou ... module.png

It is clearer if I type the connection here:
Raspberry Pi TEA5767 Board
3.3V Pin (Pin 0) <---> V pin
SDA Pin (Pin 3) <---> SDA pin
SCL Pin (Pin 5) <---> SCL pin
GND Pin (Pin 6 or 9) <---> GND pin


C code would work 100%. C code was posted and discussed in the Pi forum here:
viewtopic.php?f=44&t=53680

Code: Select all

[email protected] ~/Projects $ ./radio 100
RPi - tea5767 Philips FM Tuner v0.3 
Frequency = 100.000000
[email protected] ~/Projects $ ./radio 85
RPi - tea5767 Philips FM Tuner v0.3 
Frequency = 85.000000
[email protected] ~/Projects $ ./radio 87
RPi - tea5767 Philips FM Tuner v0.3 
Frequency = 87.000000
[email protected] ~/Projects $ ./radio 105.1
RPi - tea5767 Philips FM Tuner v0.3 
Frequency = 105.100000




Python 2 vs Python 3 test output

Code: Select all

#!/usr/bin/python
# -*- encoding: utf-8 -*-

import smbus

bus = smbus.SMBus(1)  # novejsi varianta RasPi (512MB)
#bus = smbus.SMBus(0)  # starsi varianta RasPi (256MB)

freq = 95       # pozadovana frekvence v MHz  (na 95.0MHz u nas vysila Radio Blanik)

# rozlozeni frekvence na dva bajty (podle katalogoveho listu)
freq14bit = int(4 * (freq * 1000000 + 225000)/32768)
freqH = int(freq14bit / 256 )
freqL = freq14bit & 0xFF

                             # popisy jednotlivych bitu v bajtech - viz. katalogovy list
bajt0 = 0x60                 # I2C adresa obvodu
bajt1 = freqH                # 1.bajt (MUTE bit ; frekvence H)
bajt2 = freqL                # 2.bajt (frekvence L)
bajt3 = 0b10110000           # 3.bajt (SUD  ;  SSL1,SSL2  ;  HLSI  ;  MS,MR,ML  ;  SWP1)
bajt4 = 0b00010000           # 4.bajt (SWP2 ; STBY ;  BL ; XTAL ; SMUTE ; HCC ; SNC ; SI)
bajt5 = 0b00000000           # 5.bajt (PLREFF  ;  DTC  ;  0;0;0;0;0;0)

blokdat=[ bajt2 , bajt3 , bajt4 , bajt5 ]
bus.write_i2c_block_data( bajt0 , bajt1 , blokdat )   # nastaveni nove frekvence do obvodu


Code was adopted from: http://www.astromik.org/raspi/38.htm

Python 2 would give 40-50% error, whereas Python 3 would give 95-100% error. Is there difference in bytecode format between the two version?

Code: Select all

[email protected] ~/Projects $ python3 radio-smbus.py
176
I2C: Writing list to register 0x30:
[80, 176, 16, 0]
[Errno 5] Input/output error
[email protected] ~/Projects $ python radio-smbus.py
176
I2C: Writing list to register 0x30:
[80, 176, 16, 0]
[email protected] ~/Projects $ 

Setting the baudrate down, doesn't effect anything. And the suspect wiring issue is unlikely because the compiled C program can work 100% of the time.

Very confusing :?
www.linuxcircle.com

User avatar
Gert van Loo
Posts: 2486
Joined: Tue Aug 02, 2011 7:27 am
Contact: Website

Re: Change I2C speed

Mon Aug 10, 2015 1:00 pm

Setting the baudrate down, doesn't effect anything.
Python code is A LOT! slower then C-code.
How much did you change the baudrate?

User avatar
joan
Posts: 14378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Change I2C speed

Mon Aug 10, 2015 1:17 pm

I missed the point about the C (wiringPi) version working 100%.

That does seem to rule out connections as the issue.

However wiringPi, Python2, Python3 (and pigpio depending on what you did) would all be using the underlying Linux SMBus driver. Have you ensured that you are using the same SMBus calls in your Python as are being used by wiringPi in the C version?

LinuxCircle
Posts: 26
Joined: Sat May 04, 2013 2:03 am
Contact: Website

Re: Change I2C speed

Wed Aug 12, 2015 6:23 am

Gert van Loo wrote:
Setting the baudrate down, doesn't effect anything.
Python code is A LOT! slower then C-code.
How much did you change the baudrate?
I set it down to 9600, no effect, and then down to 5000, same deal.

I finally found a workaround by sending the byte block command in a loop until 1 gets through. viewtopic.php?f=44&t=53680&p=800908&hil ... 67#p800908

But still curious about Python 3 i2C SMBUS capability. Is it an issue with smBUS or the language itself?
www.linuxcircle.com

User avatar
joan
Posts: 14378
Joined: Thu Jul 05, 2012 5:09 pm
Location: UK

Re: Change I2C speed

Wed Aug 12, 2015 6:31 am

Could you post the Python and the C code you are actually using. The snippets I have seen suggest they are using completely different SMBus calls. That would explain why they have different results.

LinuxCircle
Posts: 26
Joined: Sat May 04, 2013 2:03 am
Contact: Website

Re: Change I2C speed

Tue Aug 18, 2015 1:23 am

joan wrote:Could you post the Python and the C code you are actually using. The snippets I have seen suggest they are using completely different SMBus calls. That would explain why they have different results.
Here they are:
https://github.com/LinuxCircle/tea5767/ ... troller.py
https://github.com/LinuxCircle/tea5767/ ... scanner.py

Run it with sudo./tea5767controller.py

There is also the web interface if you are keen to run in on a web browser:
https://github.com/LinuxCircle/tea5767/ ... _server.py

Just need to specify the port: http://ipaddressofyourpi:10005

You can find how to prepare and use them here: http://www.linuxcircle.com/2015/08/17/t ... rt-2-of-3/
www.linuxcircle.com

whodat
Posts: 1
Joined: Mon Mar 14, 2016 11:31 am

Re: Change I2C speed

Mon Mar 14, 2016 11:36 am

This is a little late, but I do not belive that the I2C protocol lets you set just any baudrate. Actually, to be technical, SMBus only allows 100K and 400K (K=1000) baudrate, and that may be it. SMBus is an Intel protocol, vs Phillip / NXP's I2C ) is more restrictive than the revamped I2C which support much faster rates. Sparkfun has a good basic tutorial on I2C.

edwinlimlx
Posts: 1
Joined: Mon Sep 25, 2017 4:42 am

Re: Change I2C speed

Mon Sep 25, 2017 7:17 am

Hi,

I've tried all the following

sudo nano /etc/modprobe.d/i2c.conf
options i2c_bcm2708 baudrate=400000

sudo nano /boot/config.txt
dtparam=i2c_arm_baudrate=400000

sudo nano /etc/modules
i2c-bcm2708 baudrate=400000

sudo nano /etc/rc.local
modprobe -r i2c_bcm2708
modprobe i2c_bcm2708 baudrate=400000

but my stepper is still running at normal speed despite setting 240 or 255

rpi3

=(

amr beso
Posts: 2
Joined: Thu Oct 05, 2017 12:41 am

Re: Change I2C speed

Wed Oct 11, 2017 10:45 pm

you must do

Code: Select all

sudo reboot
after every changing.

brianmichalk
Posts: 2
Joined: Thu Aug 09, 2018 2:56 am

Re: Change I2C speed

Wed May 01, 2019 11:31 pm

Has anyone been able to change the i2c clock rate? I have about a 10 foot cable, and it's not working with the default speed.

In looking at alternatives, I could get a differential driver, but two of them will cost me $20 from SparkFun, and at that rate, I may as well buy another Pi0 and send the data over WiFi.

billyjake
Posts: 5
Joined: Tue Sep 17, 2019 7:12 pm

Re: Change I2C speed

Tue Nov 05, 2019 5:17 pm

I can change the I2C clock speed on my Pi 3B+ by editing the /boot/config.txt file and adding to the line
dtparam=i2c_arm=on
to make it
dtparam=i2c_arm=on,i2c_arm_baudrate=10000

Before making the change I measured the I2C clock pulses at about 8 microseconds long using an oscilloscope.
After making the change I mesured the clock pulses to be about 80 microseconds long.

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