2015年3月16日 星期一

Python 使用 I2C bus on Raspberry Pi



這篇文章介紹使用 Python 來對i2c介面做簡單的控制。

Python控制i2c會需要用到package "python-smbus" ,沒有的話就用apt來安裝吧。

apt-get install python-smbus 另外在熟悉程式開發期間,可以配合i2c-tools工具package來用,這是一個非常好用的工具。

此文章使用艾鍗學院提供的Pi I/O子板來練習,沒有板子的人也可以去買一顆for i2c 的eeprom晶片並參考下列網址的教學,來做連線。


http://coldnew.github.io/blog/2013/06/19_e5bcf.html
可以先用i2c-tools提供的i2cdetect指令來看看eeprom的i2c slave address是多少:

sudo i2cdetect -y 1
從列表裡可以知道,我們的 eeprom 在 i2c bus 上的 slave address 為 0x50。

順便說明一下, i2c 介面上面的指令都是對bus指定的slave address上的特定暫存器位置做存取的動作,而每個暫存器大都為 1 byte,而有時候 device 需要儲存16bit的數值資料時就會用2 個連續的暫存器。

這個 eeprom 裡面就有 256 個暫存器單純用來儲存數值所用,所以非常適合用來練習i2c介面的程式設計。

因為python上的 smbus package 和 linux kernel module: i2c-dev已經把i2c底層硬體的事情做完了,所以在python上面使用i2c會變得非常的平易近人。只需要知道devica的slave id之後,就可以開始寫程式了。

所以下面就先寫個python小程式來試看看。



import smbus i2c = smbus.SMBus(1) # 指定使用/dev/i2c-1 addr = 0x50 # eeprom 在 i2c bus 上的位置 reg = 0x00 # 打算要存取的暫存器位置 value = 0x64 # 等一下要寫入的值 i2c.write_byte_data(addr, reg, val) # 寫入的動作 print i2c.read_byte_data(addr,reg) # 把剛剛寫入的值讀出來確定一下 上面的程式一開始宣告了一個 smbus.SMBus(1) 的物件來控制 i2c 介面。引入的參數'1'指的是 /dev/i2c-1 這個裝置檔案。

Raspbian 系統一開始並不會產生 /dev/i2c-1 ,但可以透過手動載入module : i2c-dev 來產生。

sudo modprobe i2c-dev 成功之後,使用指令 lsmod 會看到 "i2c_dev" 這個模組掛載在其中。

之後只要透過 smbus 提供的 method:

read_byte_data(<I2C device addr>, <暫存器位置>) write_byte_data(< i2c device address>, <暫存器位置>, <要寫入的byte值>) 就可以對指定的i2c device 做指定暫存器的單一 byte 存取。
但是一般來說 i2c device 都會支援連續 byte 讀寫動作。是由下面這兩個 method 所支援。 read_i2c_block_data(< i2c device address>, <連續讀取暫存器起始位置>, <總共要讀取的byte 的 數量>) write_i2c_block_data(< i2c device address>, <連續讀取暫存器起始位置>, <要連續寫入的資料 list>) 舉例來說,我要從某個 i2c device (address = 0x40)中,從暫存器0x04開始先連續寫入 [0x01,0x03,0x05,0x08,0xff] 。

然後再從原來的0x04開始連續讀取8個byte的資料的話,code 寫出來是長這樣子的。

import smbus i2c = smbus.SMBus(1) addr = 0x40 reg = 0x04 len = 8 vals = [0x01,0x03,0x05,0x08,0xff] i2c.write_i2c_block_data(addr, reg, vals) data = i2c.read_i2c_block_data(addr, reg, len)
不過這邊要說明一下,有些 i2c device 要做一些設定才能做暫存器連續存取。像是之前用過的一個 i2c device : PCA9685。

就需要將其中一個控制暫存器的特定 bit (Auto Increment bit) 給設為 1 ,才能做連續存取的動作。








沒有留言 :

張貼留言