前回はSTM32F401CCU6にMicroPythonを載せ簡易動作させましたが、今回は同じボードを2枚用意して片方をMasterにもう一方をSlaveにしてI2C通信を行ってみました。
なお結線ですが、SCLがB6, SDAがB7、どちらも5vトレラントのピンなので、2kΩで5vにプルアップしています。
まず、マスターからスレーブにデータを転送する例です。
スレーブ側
まずスレーブ側です。
今回は以上です。それでは、Happy coding!
なお結線ですが、SCLがB6, SDAがB7、どちらも5vトレラントのピンなので、2kΩで5vにプルアップしています。
まず、マスターからスレーブにデータを転送する例です。
スレーブ側
from pyb import I2C SLAVE_ADDR = 0x40 BAUD = 100000 i2c_slave = I2C(1, I2C.SLAVE, addr=SLAVE_ADDR, baudrate=BAUD)この状態ではslaveはscanにも反応しないので以下のようにして待ち受けさせます。
while True: try: data = i2c_slave.recv(4) except OSError as exc: if exc.args[0] == 5: # 5 == EIO ( bus scan ) print("I2C bus scan detected") elif exc.args[0] == 110: # 110 == ETIMEOUT pass else: print(exc) except KeyboardInterrupt: break else: print("RECV: %r" % data)続いてマスター側です。
from pyb import I2C SLAVE_ADDR = 0x40 BAUD = 100000 i2c_master = I2C(1, I2C.MASTER, baudrate=BAUD) i2c_master.scan() for i in range(63): i2c_master.send("%04i" % i, addr=SLAVE_ADDR) pyb.delay(100)成功するとスレーブ側が以下のようになります。
I2C bus scan detected RECV: b'0000' RECV: b'0001' RECV: b'0002' (中略) RECV: b'0060' RECV: b'0061' RECV: b'0062'次にスレーブからマスターへ送信する例です。
まずスレーブ側です。
import pyb # for adc from pyb import I2C SLAVE_ADDR = 0x40 BAUD = 100000 SENDTIMEOUT = 250 RECVTIMEOUT = 250 i2c_slave = I2C(1, I2C.SLAVE, addr=SLAVE_ADDR, baudrate=BAUD, dma=False) RESOLUTION=12 def send_cpu_temp(): adc = pyb.ADCAll(RESOLUTION) cpu_temparature = adc.read_core_temp() i2c_slave.send(str(cpu_temparature), timeout=SENDTIMEOUT) def send_vbat(): adc = pyb.ADCAll(RESOLUTION) core_vbat = adc.read_core_vbat() i2c_slave.send(str(core_vbat), timeout=SENDTIMEOUT) def send_vref(): adc = pyb.ADCAll(RESOLUTION) core_vref = adc.read_vref() i2c_slave.send(str(core_vref), timeout=SENDTIMEOUT) while True: try: data = i2c_slave.recv(2, timeout=RECVTIMEOUT) except OSError as exc1: if exc1.args[0] == 5: # 5 == EIO ( bus scan ) print("I2C bus scan detected") elif exc1.args[0] == 110: # 110 == ETIMEOUT pass else: print(exc1) except KeyboardInterrupt: break else: if data[0] == 0xFF and data[1] == 0x01: try: print("RECV: %r" % data) send_cpu_temp() except OSError as exc2: if exc2.args[0] not in (5, 110): break except KeyboardInterrupt: break else: pass if data[0] == 0xFF and data[1] == 0x02: try: print("RECV: %r" % data) send_vbat() except OSError as exc2: if exc2.args[0] not in (5, 110): break except KeyboardInterrupt: break else: pass if data[0] == 0xFF and data[1] == 0x03: try: print("RECV: %r" % data) send_vref() except OSError as exc2: if exc2.args[0] not in (5, 110): break except KeyboardInterrupt: break else: passマスター側です。
from pyb import I2C SLAVE_ADDR = 0x40 BAUD = 100000 RES_INT=10 MES_INT=10000 TIMEOUT_RETRY = 5000 DATA_LEN=6 i2c_master = I2C(1, I2C.MASTER, baudrate=BAUD, dma=False) def print_slave_sensor(param1, param2, unit_label): buf = bytearray(2) buf[0] = param1 buf[1] = param2 i2c_master.send(buf, addr=SLAVE_ADDR) pyb.delay(RES_INT) data = bytearray(DATA_LEN) res = i2c_master.recv(data, addr=SLAVE_ADDR) print("%s: %s" % (unit_label, res.decode())) while True: try: print_slave_sensor(0xFF, 0x01, "Temp") print_slave_sensor(0xFF, 0x02, "Vbat") print_slave_sensor(0xFF, 0x03, "Vref") pyb.delay(MES_INT - RES_INT*3) except OSError as exc1: if exc1.args[0] == 110: print("ETIMEOUT: Could not read data.") print("Waiting for %d ms." % TIMEOUT_RETRY) pyb.delay(TIMEOUT_RETRY) except KeyboardInterrupt: break else: pass正常に動作すると、マスター側は以下のようになります。
Temp: 28.518 Vbat: 1.6229 Vref: 3.2912初めはslave側のtimeoutを秒単位で大きく取っていてマスター側でtimeoutエラーが発生したのですが、slave側のtimeoutを250にするとマスター側でのtimeoutエラーが発生しなくなりました。パラメータの指定はまだ詰める必要はありそうですがとりあえず動いてはいるようなので、良しとしています。
今回は以上です。それでは、Happy coding!
コメント
コメントを投稿