0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

JetsonでUSB-IOを使う

Last updated at Posted at 2020-06-04

#はじめに
JetsonNano/JetsonXavierNXには、RasberryPI互換のGPIOがあります。
一方でJetsonで多く使われるカメラはUSBに接続され、USBケーブルはリピータなどをいれることでかなり距離を稼ぐことができます。
カメラの方向のコントロールなどをGPIOを介して行った場合、USBケーブルと別にパラレルインタフェースに必要なGPIOを引き回す必要があり煩雑です。
今回はUSBにUSB接続デジタル入出力モジュール USB-IO2.0(AKI)をつないでパラレル入出力を行うことで、カメラと同様にUSBケーブルだけで本体と距離のあるなにかをコントロールします。#する予定です
難しいとこはないですが、setup.pyの変更部分がわからず苦労したので、備忘録として。。

#やったこと
Pythonからお気楽にLチカ (AKI-USBIO2)を参考にcython-hidapiをビルド、インストールしました。
環境はJetsonXavierNX + Jetpack4.4 (+Docker )です。

#事前準備
cython , libusb , libusb-devをインストールする必要があります。

apt update
apt install libusb-1.0.0
apt install libusb-dev
apt install python3-pip
pip3 install cython
git clone https://github.com/gbishop/cython-hidapi.git

#ビルド
python3 setup.py build
python3 setup.py install
でビルド、インストールが出来ますが、jetpack4.4上で実装するとinstall時に
“hid.so: undefined symbol: libusb_open”
と言われます。
import hid in python results in error “hid.so: undefined symbol: libusb_open
にあるようにsetup.pyを変更します。
setup.pyのなかのsetup部分を

setup(
    cmdclass = {'build_ext': build_ext},
    ext_modules = [Extension("hid", ["hid.pyx", "hid-libusb.c"],
                  libraries=["usb-1.0", "udev", "rt"])]
)

にし、usb-1.0とudevを明記します。
でもって、

python3 setup.py build
sudo python3 setup.py install 

でインストールが出来ます。

Python3

実際に使おうとすると

hid.pyx
def write(self, buff):
      '''Accept a list of integers (0-255) and send them to the device'''
      buff = ''.join(map(chr, buff)) # convert to bytes
      cdef unsigned char* cbuff = buff # covert to c string
      return hid_write(self._c_hid, cbuff, len(buff))

python3だとbuffがstringになるので
cdef unsigned char* cbuff = buff # covert to c string
がエラーになります。
cythonがよくわかってないんですが。。。適当に

hid.pyx
def write(self, buff):
      '''Accept a list of integers (0-255) and send them to the device'''
      buff = bytearray( buff )
      cdef unsigned char* cbuff = buff # covert to c string
      return hid_write(self._c_hid, cbuff, len(buff))

bytearrayに変換するようにしました。
同じのがあと一カ所あります。使わないですが

Dockerでの実行

私自身は開発をDocker上でやっているので、Dockerでの実行時には
コンテナ上でusbのhidデバイスをブラウズ、アクセス出来る必要があります。
docker run に以下のどちらかをつけて起動する必要があります。
前者は、デバイス全部がコンテナからみえるようになり、
後者はUSBデバイスへの直接アクセスが出来るようになります。(/dev/videoなどはたとえUSB上でも別途オプションが必要なままです)

--previledged
もしくは
--device /dev/bus/usb:/dev/bus/usb

がいります。

#利用
私は出力しかつかわないので、入力はためしてません
買った直後はP2が入力?かな?なので、システム設定用フラッシュロム書き込みコマンドで書き換える必要があります。ただ、Pythonで実装しても挿抜しないと反映されないため、あまり楽しくないのでWindowsから付属のユーティリティで全部出力に書き換えることとしPython側では実装していません。どうせ購入後1度しかつかいませんので。
必要であれば、下記のコード上のCMD_CONFIG_WRITEを実装して
km-netさんのページのコマンドで4バイト目と5バイト目を書き換える必要があります。
出力に設定してあれば、下記のコードで
import USBIO
usb = USBIO()
usb.write( 0x55,0x55 )
とかやるとP1に0x55 P2に0x5が出力されます。#HIDデバイスをあけるのにSUDOがいります。
もしくは
import USBIO
usb = USBIO()
usb.setPinLevel( 5 , 0 ) # 5はピン番号で0−11、0はレベルで0でLow,1でHigh
usb.outputToPin() # ここでここまでのsetPinLevelが一度に反映されます。
##HIDデバイスをあけるのにSUDOがいります。

USBIO.py
import hid

class USBIO:
    VENDOR_ID = 0x1352       # Km2Net
    PRODUCT_ID = 0x0121  # USB-IO2.0(AKI)
    lock = threading.Lock()
# Command list
    CMD_READ_WRITE = 0x20
    CMD_CONFIG_READ = 0xf8
    CMD_CONFIG_WRITE = 0xf9
    usb = hid.device(VENDOR_ID, PRODUCT_ID)
    def __init__(self  ):
        #writePin( 0,0 )
        self.pin = [0] *12

    def writePin(self,p1,p2):   # Prioro to use this , all pins need to be configured as output pins
        data = [0] * 64
        data[0] = self.CMD_READ_WRITE
        data[1] = 1
        data[2] = p1
        data[3] = 2
        data[4] = p2
        data[63] =89    # dummy to confirm USB-IO recognition
        self.lock.acquire() # make sure just a thread using USB
        self.usb.write(data)
        self.lock.release()
        return(self.usb.read(64))

        
    def setPinLevel(self, pin_no , level ):
        self.pin[pin_no] = level

    def outputToPin( self ):
        p1 =      self.pin[0]    + self.pin[1] * 2 + self.pin[2] * 4 + self.pin[3] *8
        p1 = p1 + self.pin[4]*16 + self.pin[5] * 32+ self.pin[6] * 64+ self.pin[7] *128
        p2 =      self.pin[8]    + self.pin[9] * 2 + self.pin[10]* 4 + self.pin[11]*8
        self.writePin( p1 , p2 )

LockはこのあとSteppingモータ回した時に1個目と2個目をパラで動かすためのコードなので、単体ではどうでも良いです。

#修正部分のリスト
Jetsonだからなのか、Linuxだからなのか、時間がたったからなのか、Pythonからお気楽にLチカ (AKI-USBIO2)の通りには動きませんでした。

  • Openを独立して呼んでますが、ここがかわってます。
  • コマンドを送るときにダミーの1バイトがいることになっていますが、必要ありませんでした。
  • python3でやるとcython-hidのオリジナルだとエラーになりました。(python3の項参照)

予定

1,USB-IOのコントロール ーいまここ
2,USB-IO経由でステッピングモータのコントロール
3,レーザポインタを物体検出するためのYOLO学習データの作成
4,レーザポインタを追いかけるカメラ

0
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?