= Arduino と EPICS を使った簡単な例 = [[PageOutline]] 家庭でも遊べるように、簡単なサンプルをつくることが目的。[[br]] 「ArduinoはUSBシリアル経由でデータを垂れ流しにする」「EPICS IOC(Raspberry Pi) 側からコマンドは送らず、Listenするのみ」という構成にする。 == 準備 == * Arduino Uno * PC * Arduino 統合開発環境(IDE)を公式サイト( https://www.arduino.cc/en/Main/Software )からダウンロード・インストールする * 今回は Windows / ver 1.8.7 を使用した * Raspberry Pi * 今回はRaspberry Pi2 Model Bを使用した(Pi3でも可能のはず) * EPICSインストールについては[wiki:epics/raspberrypi 別の記事を参照] * USB ケーブル * ブレッドボード、ジャンパーケーブル等 * 半固定抵抗と固定抵抗(今回は手元にあった 1kΩのモノを使用) == 方針 == [!RasPi (epics IOC)] --(USB)--[Arduino AnalogIN] -- 可変抵抗に5V印加 [[br]] * アナログ入力を読み込み、シリアル経由でホストに通信。最初はPCを使って動作検証し、その後でEPICS化する。 * Arduino Uno の場合、0-5Vを 10bit(0-1024)で読み込むことが可能 * 5V 電圧+可変抵抗+固定抵抗(破損防止)で * 今回は手元にあった 1kΩの可変抵抗+1kΩの固定抵抗 * ブレッドボードに配線[図] = 動作確認 = == PCを使ってスケッチの検証 == 構成としては [PC] --[USB]--[Arduino]--AnalogIN という単純な構成。[[br]] 1秒に1回、ADCの値をシリアル経由でホストPCに送るスケッチを作成する。 {{{ int analogPin = 0; int val = 0; void setup() { Serial.begin(19200); } void loop() { val = analogRead(analogPin); Serial.println(val); delay(1000); } }}} Arduinoにダウンロードし、IDEで「シリアルモニター」を開くと、1秒に1回ADCのカウント値が表示される。[[br]] この状態で可変抵抗を動かすと、カウント値が変わることを確認する。 [[Image(aruduino002.png, 40%)]] == Raspberry Pi に接続 == 次にUSBケーブルをPCから抜いて、Raspberry Pi に Arduino を接続する。[[br]] まずは dmesg を確認 {{{ [ 3433.753691] usb 1-1.2: new full-speed USB device number 6 using dwc_otg [ 3433.898077] usb 1-1.2: New USB device found, idVendor=2a03, idProduct=0043 [ 3433.898099] usb 1-1.2: New USB device strings: Mfr=1, Product=2, SerialNumber=220 [ 3433.898109] usb 1-1.2: Product: Arduino Uno [ 3433.898120] usb 1-1.2: Manufacturer: Arduino Srl [ 3433.898129] usb 1-1.2: SerialNumber: [ 3433.938398] cdc_acm 1-1.2:1.0: ttyACM0: USB ACM device [ 3433.939634] usbcore: registered new interface driver cdc_acm [ 3433.939644] cdc_acm: USB Abstract Control Model driver for USB modems and ISDN adapters }}} のように、ttyACM0 として認識されている。となればあとは簡単で、rootになってから適当なターミナルプロ ラムで接続すれば良い。ここでは使いなれた GNU Screen を使って、デバイス名と通信速度を指定する {{{ pi@raspberrypi:~ $ sudo su - root@raspberrypi:~# screen /dev/ttyACM0 19200 }}} 正常に接続できれば、1秒ごとにターミナル上にADCカウント値が表示される。[[br]] GNU Screenを終了するにはホットキー(デフォルトではCTRL-a)を押してから、kを押せば良い(killコマンド)。 ※分からなければgoogleで 「GNU Screen の使い方」を検索 = EPICS IOC 作成 = == makeBaseApp == ここまでくれば、あとはEPICSのIOCを書く。 単純に Stream Device で読み込むだけで良いので、 simpleReadという名前でapplicationを作る。 {{{ pi@raspberrypi:~/epics/app/arduino $ makeBaseApp.pl -t ioc simpleRead pi@raspberrypi:~/epics/app/arduino $ makeBaseApp.pl -i -t ioc simpleRead Using target architecture linux-arm (only one available) The following applications are available: simpleRead What application should the IOC(s) boot? The default uses the IOC's name, even if not listed above. Application name? pi@raspberrypi:~/epics/app/arduino $ }}} configure/RELEASEを編集 {{{ pi@raspberrypi:~/epics/app/arduino $ vi configure/RELEASE ASYN=/opt/epics/R315.5/modules/soft/asyn/4-31 STREAM=/opt/epics/R315.5/modules/soft/stream/2-7-7 }}} == src ディレクトリでの作業 == srcディレクトリで、MakefileにstreamDeviceの * SerialPortドライバーを追加 * asyn ライブラリを追加 の2つを追記 {{{ pi@raspberrypi:~/epics/app/arduino/simpleReadApp/src $ vi Makefile # simpleRead.dbd will be made up from these files: simpleRead_DBD += base.dbd # Include dbd files from all support applications: simpleRead_DBD += asyn.dbd simpleRead_DBD += stream.dbd simpleRead_DBD += drvAsynSerialPort.dbd # Add all the support libraries needed by this IOC simpleRead_LIBS += asyn simpleRead_LIBS += stream }}} == Database ディレクトリでの作業 == Dbディレクトリでdatabaseファイルを追加。スキャンを"I/O Intr"にすることで、シリアル経由でデータが来たときのみレコードをプロセスする。 {{{ vi read1.db record(longin, "TEST:READ_INT") { field(DESC, "adc raw input") field(DTYP, "stream") field(INP, "@simple.proto getval PS1") field(SCAN, "I/O Intr") } }}} Dbディレクトリの Makefile に db ファイルを追加 {{{ pi@raspberrypi:~/epics/app/arduino/simpleReadApp/Db $ vi Makefile DB += read1.db }}} Dbディレクトリに protocol file を作成。数値を"%d"で変換するのみなので単純。エラー時に {{{ pi@raspberrypi:~/epics/app/arduino/simpleReadApp/Db $ vi simple.proto Terminator = CR LF; getval { in "%d"; } }}} make すると、とても遅い。セルフコンパイルなので仕方ない(クロスコンパイル環境を整えたい)[[br]] stream device のサイト http://epics.web.psi.ch/software/streamdevice/ も参照。[[br]] == startup == startupディレクトリで st.cmd コマンド編集 {{{ pi@raspberrypi:~/epics/app/arduino/iocBoot/iocsimpleRead $ vi st.cmd dbLoadRecords("db/read1.db") epicsEnvSet("STREAM_PROTOCOL_PATH", ".:../../simpleReadApp/Db") drvAsynSerialPortConfigure ("PS1","/dev/ttyACM0") asynSetOption ("PS1", 0, "baud", "19200") }}} {{{ pi@raspberrypi:~/epics/app/arduino/iocBoot/iocsimpleRead $ chmod +x st.cmd pi@raspberrypi:~/epics/app/arduino/iocBoot/iocsimpleRead $ sudo ./st.cmd }}} エラーが出ていないことを確認すること。[[br]] == Client == 別ターミナルを開いて、 {{{ camonitor TEST:READ_INT }}} とする。 あるいは、PC上でCSSを実行して、このレコードをモニター・グラフ表示する。[[br]] ※ 以上の動作が確認できたら、Arduinoスケッチで Delay 1000 としているところを、 100 ms に設定すると 可変抵抗を動かしたときの応答が滑らかになる。Arduinoは高速で動いているのに対して、EPICSを使うことで camonitor 機能があるため値が変化したときのみデータ通信を行うことが実現できている。 [[Image(aruduino004b.png, 40%)]][[Image(aruduino005.png, 40%)]]