wiki:epics/arduino/simpleRead

Version 3 (modified by obina, 6 years ago) (diff)

--

Arduino と EPICS を使った簡単な例

家庭でも遊べるように、簡単なサンプルをつくることが目的。
「ArduinoはUSBシリアル経由でデータを垂れ流しにする」「EPICS IOC(Raspberry Pi) 側からコマンドは送らず、Listenするのみ」という構成にする。

準備

  • Arduino Uno
  • PC
  • Raspberry Pi
    • 今回はRaspberry Pi2 Model Bを使用した(Pi3でも可能のはず)
    • EPICSインストールについては別の記事を参照
  • USB ケーブル
  • ブレッドボード、ジャンパーケーブル等
  • 半固定抵抗と固定抵抗(今回は手元にあった 1kΩのモノを使用)

方針

最終的には
EPICS Client --(Ethernet)-- [RasPi (epics IOC)] --(USB)-- [Arduino AnalogIN #0] <-- 可変抵抗に5V印加
という構成にする。

  • アナログ入力を読み込み、シリアル経由でホストに通信。最初はPCを使って動作検証し、その後でEPICS化する。
  • Arduino Uno の場合、0-5Vを 10bit(0-1024)で読み込むことが可能
  • 5V 電圧+可変抵抗+固定抵抗(破損防止)で
    • 今回は手元にあった 1kΩの可変抵抗(半固定抵抗)+1kΩの固定抵抗
  • ブレッドボードに配線

動作確認

PCを使ってスケッチの検証

最初に
[PC] --(USBケーブル)-- [Arduino] <-- AnalogIN
という単純な構成で確認する。

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のカウント値が表示される。
この状態で可変抵抗を動かして、カウント値が変わることを確認する。

Raspberry Pi に接続

次にUSBケーブルをPCから抜いて、Raspberry Pi に Arduino を接続する。
まずは 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カウント値が表示される。
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 すると、とても遅い。セルフコンパイルなので仕方ない(クロスコンパイル環境を整えたい)
stream device のサイト http://epics.web.psi.ch/software/streamdevice/ も参照。

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

エラーが出ていないことを確認すること。

Client

別ターミナルを開いて、

camonitor TEST:READ_INT

とする。 あるいは、PC上でCSSを実行して、このレコードをモニター・グラフ表示する。

※ 以上の動作が確認できたら、Arduinoスケッチで Delay 1000 としているところを、 100 ms に設定すると 可変抵抗を動かしたときの応答が滑らかになる。Arduinoは10Hzという一定速度で電圧を測定しているのに対して、 EPICS IOC は値が変化したときのみクライアント側に通知する camonitor 機能がある。

Attachments (8)

Download all attachments as: .zip