元高専生のロボット作り

元高専生のロボット作り

主にプログラミング, 電子系について書きます。たまに機械系もやります。メモ代わりの記事ばっか書きます

ラズベリーパイとmbedでI2C通信する

ラズパイとmbedでi2c通信してみました。

ラズパイはI2C Slaveにはなれないようなので、マスターになっています。

mbedがスレーブで受信割り込みで自動で値を受け取るようにしました。

レジスタ指定で、4バイトの送受信が可能です。

使用したものはRaspberry Pi 2 model Bと、mbedLPC1768です。

はいコードです。


ラズパイ側

import smbus

addr = 0x1D

class I2CMaster():
    
    def __init__(self):
        
        self.i2c = smbus.SMBus(1)
        
    def writeSomeData(self, addr, reg, data, size):
        
        DATA = [size, 1]
        tmp = [(data>>i*8)&0xFF for i in range(size)]
        self.i2c.write_i2c_block_data(addr, reg, DATA)
        self.i2c.write_i2c_block_data(addr, tmp[0], tmp[1::])
        
    def getSlaveRegistarData(self, addr, reg, size):

        DATA = [size, 2]
        self.i2c.write_i2c_block_data(addr, reg, DATA)
        val = self.i2c.read_byte_data(addr, 1)
        return val
    
    def getSlaveData(self, addr, reg, size):
        val = 0
        for i in range(size):
            val |= self.getSlaveRegistarData(addr, reg*4+i, 1) << i*8
        return val
        
i2c = I2CMaster()
#レジスタ0に12345(4バイト送信)
i2c.writeSomeData(addr, 0, 12345, 4)
#レジスタ0の値4バイトを受信
data = i2c.getSlaveData(addr, 0, 4)
print(data)
#レジスタ1に6543(4バイト送信)
i2c.writeSomeData(addr, 1, 6543, 4)
#レジスタ1の値4バイトを受信
data = i2c.getSlaveData(addr, 1, 4)
print(data)

mbedはライブラリをあげときました。cppファイル中のサンプルコードで動きます。

os.mbed.com

まあそんな解説することもないです。

mbedの方のレジスタ登録は

union U{
    int8_t _Registar[0x40];
    int32_t Registar[0x10];
};
union U u = { 0 };
i2cslave slave(p28, p27, u._Registar);

としておいて、4バイトの方のレジスタを使用するといいです。

基本的にラズパイ側で使用する関数は、

writeSomeData(self, addr, reg, data, size)
getSlaveData(self, addr, reg, size)

だけです。

mbedとラズパイではI2Cアドレスの表記の仕方が下位1bitを書くか書かないかで異なるので、そこはmbedの方で修正するようにしてます。

こんな感じ

#define ADDR 0x1D
#define _ADDR ADDR<<1   //on raspi

あとは、スレーブからマスターにデータ送信するときの

case WriteRequired:
                I2CSlave::read(DATA, 1);    //捨て受信
                
                int8_t tmp = *(Registar+reg);
                I2CSlave::write(tmp);
                I2CSlave::write(tmp);
                I2CSlave::write(tmp);

あたりがこだわりポイントですかね。。。

I2CSlave::write(tmp);

を2つとかにすると動かないんですよ。

これmbedとラズパイの遅延時間とかの問題だと思うんですけど、waitを入れてもやはり動かなくて、

やけくそでI2CSlave::write(tmp);を連打してみたら動いたみたいな感じです。

すごく気持ち悪いので直したらすぐ修正しときます。