arduino_spi_slave.py

# この作品はMITライセンスの下で提供されています。
# Copyright (c) 2013-2023 OpenMV LLC. 全著作権所有。
# https://github.com/openmv/openmv/blob/master/LICENSE
#
# ArduinoをマスターデバイスとしOpenMV Camをスレーブとして使うSPI。
#
# OpenMV Camを次のようにArduinoに配線してください:
#
# OpenMV Cam Master Out Slave In (P0) - Arduino Uno MOSI (11)
# OpenMV Cam Master In Slave Out (P1) - Arduino Uno MISO (12)
# OpenMV Cam Serial Clock        (P2) - Arduino Uno SCK  (13)
# OpenMV Cam Slave Select        (P3) - Arduino Uno SS   (10)
# OpenMV Cam Ground                   - Arduino Ground

import pyb
import struct
import time

text = "Hello World!\n"
data = struct.pack("<bi%ds" % len(text), 85, len(text), text)  # 85は同期文字です。
# 送信するデータパケットの構築には "struct" を使用します。
# "<" は構造体内のデータをリトルエンディアン順に配置します。
# "b" はデータストリームに符号付きcharを配置します。
# "i" はデータストリームに符号付き整数を配置します。
# "%ds" はデータストリームに文字列を配置します。例: "Hello World!\n"(13文字)の場合は "13s"。
# https://docs.python.org/3/library/struct.html を参照してください

# 必ずお読みください!!!
#
# OpenMV CamがSPIマスターでない場合、応答を逃す可能性があることをご理解ください。
# SPIスレーブとしてデータを送信する際、"spi.send()" を割り込みコールバック内で呼び出しても
# 以下のメインループ内で呼び出しても同様です。そのため、通信プロトコルは必ず次のように設計する必要があります。
# スレーブデバイス(OpenMV Cam)が間に合わずに "spi.send()" を呼び出さなかった場合、
# マスター(Arduino)がSPI周辺機器から読み取ったゴミデータが破棄されるようにします。これを実現するために
# Arduinoが最初に読み取るバイトとして探す85(2進数で01010101)という同期文字を使用します。
# これが見つからない場合、SPIトランザクションを中止して再試行します。次に、
# SPI周辺機器の状態をクリアするために、常に4バイトの倍数と、追加の4バイトのゼロを送信し、
# SPI周辺機器が85になり得る古いデータを保持しないようにします。
# なお、OpenMV Camは割り込みを処理する必要があるため、"spi.send()" のタイミングをランダムに逃すことがあります。
# PCに接続している間は割り込みがはるかに多く発生します。

# OpenMV CamのハードウェアSPIバスは常にSPIバス2です。
# polarity = 0 -> クロックはアイドル時にLowになります。
# phase = 0 -> クロックの立ち上がりエッジでデータをサンプリングし、立ち下がりエッジでデータを出力します。
spi = pyb.SPI(2, pyb.SPI.SLAVE, polarity=0, phase=0)


# NSSコールバック。
def nss_callback(line):
    global spi, data
    try:
        spi.send(data, timeout=1000)
    except OSError as err:
        pass  # エラーは気にしないのでpassします。
        # エラーは3種類あり得ることに注意してください。タイムアウトエラー、汎用エラー、または
        # ビジーエラーです。それぞれのエラーコードは "err.arg[0]" に対して116、5、16です。


# マスターから要求されたときにデータを送信できるよう、NSS/CSをIRQモードに設定します。
pyb.ExtInt(pyb.Pin("P3"), pyb.ExtInt.IRQ_FALLING, pyb.Pin.PULL_UP, nss_callback)

while True:
    time.sleep_ms(1000)

###################################################################################################
# Arduinoコード
###################################################################################################
#
# #include <SPI.h>
# #define SS_PIN 10
# #define BAUD_RATE 19200
# #define CHAR_BUF 128
#
# void setup() {
#   pinMode(SS_PIN, OUTPUT);
#   Serial.begin(BAUD_RATE);
#   SPI.begin();
#   SPI.setBitOrder(MSBFIRST);
#   SPI.setClockDivider(SPI_CLOCK_DIV16);
#   SPI.setDataMode(SPI_MODE0);
# delay(1000); // OpenMV Camの起動を待ちます。
# }
#
# void loop() {
#   int32_t len = 0;
#   char buff[CHAR_BUF] = {0};
#   digitalWrite(SS_PIN, LOW);
# delay(1); // OpenMV Camがデータ送信の準備をする時間を与えます。
#
# if(SPI.transfer(1) == 85) { // 同期文字を検出?
# SPI.transfer(&len, 4); // 長さを取得
#     if (len) {
#       SPI.transfer(&buff, min(len, CHAR_BUF));
#       len -= min(len, CHAR_BUF);
#     }
# while (len--) SPI.transfer(0); // 残りのバイトを読み捨てます
#   }
#
#   digitalWrite(SS_PIN, HIGH);
#   Serial.print(buff);
# delay(1); // ループが速くなりすぎないようにします。
# }

results matching ""

    No results matching ""