• 検索結果がありません。

RTLinuxによるADボード制御プログラミングチュートリアル

N/A
N/A
Protected

Academic year: 2021

シェア "RTLinuxによるADボード制御プログラミングチュートリアル"

Copied!
89
0
0

読み込み中.... (全文を見る)

全文

(1)

チュートリアル

RTLinuxによるADボード制御

プログラミング チュートリアル

(2)

商標/登録商標

本ドキュメントに掲載されている会社名,製品名は、それぞれ各社の商標または登録商標です。

保障の内容と制限

弊社はドキュメント内の情報の正確さに万全を期しています。万一、誤記または誤植等があった

場合、弊社は予告なく改訂する場合があります。ドキュメントまたはドキュメント内の情報に起

因するいかなる損害に対しても弊社は責任を負いません。

製品に含まれるバグ、あるいは製品の供給(納期遅延),性能、もしくは使用に起因する付帯的損害

もしくは間接的損害に対して、弊社に全面的に責がある場合でも、弊社はその製品に対する改良

(正常に動作する)、代品交換までとし、金銭面での賠償の責任は一切負わないものとしますので、

予めご了承ください。

ドキュメント内の図や表は説明のためであり、ユーザ個別の応用事例により変化する場合があり

ます。

著作権,知的所有権

弊社は本製品に含まれるおよび本製品に対する権利や知的所有権を保持しています。

本製品はコンピュータ ソフトウェア(プログラム),図,文章,写真等を含んでいます。

複製の禁止

弊社の許可なく、本製品(ドキュメント含む)の全て、または一部に関わらず、複製,改変等を行う

ことはできません。

責任の制限

弊社は、弊社または再販売者の予見の有無に関わらず、発生したいかなる特別損害,偶発的損害,

間接的な損害,重大な損害について、責任を負いません。

補償の内容

本ドキュメントで使用している弊社製品の補償については、各製品のマニュアルを参照してくだ

さい。

本書の内容の一部または全部を、無断で転載することを禁止します。

本書の内容は、将来予告なく変更することがありますので、あらかじめご了承ください。

© 2002, 2007 Interface Corporation. All rights reserved.

(3)

改訂履歴

Ver.

年 月

改 訂 内 容

1.7

2007年12月

●『第3章 3.1 RTLinux ADドライバの組み込み』

再コンパイルの説明追加。

●『第6章 リファレンス』更新

1.6

2006年8月

●対応型式追加

●『関数一覧』更新

●フォーマット変更

●技術資料一覧更新

1.5

2004年11月

●対応型式追加

●誤記修正

●技術資料一覧更新

1.4

2004年1月

●誤記修正

1.3

2003年7月

●対応型式追加

●API追加

1.2

2002年9月

●対応型式追加

●誤記修正

1.1

2002年7月

●誤記修正

『AdInputADExを使った周期的なサンプリングに手を加える』の

「module2.c修正」を修正

1.0

2002年6月

新規作成

本チュートリアルをご使用の際は、必ず各製品型式の最新のドキュメント(USER'S MANUAL,

Help)を併せて参照してください。また、最新のドライバソフトウェアをご使用ください。

USER'S MANUAL,

ドライバソフトウェアは弊社Web site(www.interface.co.jp)からダウンロードで

きます。(Helpはドライバソフトウェアに含まれています)

(4)

目 次

第 1 章 アナログ出力概要

7

1.1 A/Dコンバータ ... 7

1.2 A/Dコンバータの用途... 8

1.3 分解能と精度 ... 8

1.4 シングルエンド入力と差動入力... 10

1.5 バイポーラとユニポーラ... 11

1.6 変換時間とサンプリング周波数... 11

1.7 標本化定理 ... 12

1.8 マルチADC方式とマルチプレクサ方式 ... 12

1.9 データ転送方式... 14

1.10 アナログ入力製品を使用時の指針 ... 16

第 2 章 AD (Analog to Digital) on Linux

17

2.1 RTLinuxによるAD製品制御 ... 17

2.2 AD製品制御概略 ... 18

第 3 章 AD製品制御の第一歩

19

3.1 RTLinux ADドライバの組み込み ... 20

3.2 1 件のAD入力を行う ... 23

3.3 1 件のAD入力プログラムの解説... 26

第 4 章 より高度な処理を行う

29

4.1 AdInputADExを使った周期的なサンプリング... 29

4.2 AdInputADExを使った周期的なサンプリングの解説... 34

4.2.1 共通定義ファイルの役割 ... 35

4.2.2 RTLinuxモジュールの動き ... 37

4.2.3 Linuxプロセスの動き ... 39

4.2.4 まとめ ... 40

4.3 AdInputADExを使った周期的なサンプリングに手を加える ... 41

4.4 AdStartSamplingを使った永続的なサンプリング ... 43

4.5 AdStartSamplingを使った永続的なサンプリングの解説 ... 50

4.5.1 サンプリングの動き ... 51

4.5.2 RTLinuxモジュールの動き ... 53

4.5.3 Linuxプロセスの動き ... 58

4.6 AdInputADExとAdStartSamplingのどちらを使うべきか? ... 59

第 5 章 デバッグ手法

60

5.1 ドライバデバッグ支援機能の使用 ... 60

5.1.1 関数呼び出しトレース ... 61

(5)

第 6 章 リファレンス

64

6.1 関数一覧 ... 64

6.1.1 関数一覧 1 ... 64

6.1.2 関数一覧 2 ... 66

6.1.3 関数一覧 3 ... 68

6.1.4 関数一覧 4 ... 69

6.1.5 関数一覧 5 ... 71

6.1.6 関数一覧 6 ... 72

6.1.7 関数一覧 7 ... 73

6.1.8 関数一覧 8 ... 74

6.1.9 関数一覧 9 ... 75

6.1.10 関数一覧 10 ... 77

6.1.11 関数一覧 11 ... 78

6.1.12 関数一覧 12 ... 79

6.1.13 関数一覧 13 ... 80

6.1.14 関数一覧 14 ... 81

6.2 戻り値一覧 ... 82

技術資料紹介

84

(6)

はじめに

平素は格別のご高配を賜り、厚くお礼申し上げます。本冊子はRTLinux/Free上で弊社ADインタフ

ェースモジュールを制御したい方を対象に、ADインタフェースモジュールの概要, ソフトウェア

のインストール方法, プログラミング方法を記載しています。

RTLinux上での弊社ADインタフェースモジュールを使ったプログラミングにお役に立てれば幸い

です。

本書では、以下記載がない限り、「RTLinux」は「RTLinux/Free」のことを指します。

なお本冊子はRTLinuxバージョン3.1を対象に作成されています。RTLinuxのバージョンが異なる場

合、動作保証はいたしかねますので予めご了承ください。

●ご意見・ご要望

弊社へのご意見,ご要望がございましたら、下記までお問い合わせください。

www.interface.co.jp

E-mail:support@interface.co.jp

●本冊子で扱うソフトウェア

本冊子で扱うソフトウェア製品は下記の通りです。

ソフトウェア製品名

型 式

ADインタフェースモジュール Linux/RTドライバソフトウェア

GPG-3100

●ソフトウェアの入手方法について

ソフトウェアは弊社Web siteよりダウンロード(無料)できます。

CD-ROM等、媒体による提供は有償となります。価格に送料,消費税は含まれません。

※ ダウンロードするためには、ユーザID登録が必要になります。

(7)

●ADインタフェースモジュールのLinux/RTLinux対応ドライバソフトウェア(GPG-3100)のドキュ

メント構成について

各ドキュメントに掲載している内容は下記のとおりです。

ドキュメント

内 容

Readme

製品のインストール方法や、アンインストール方法, ファイル構成の他、製

品に関する最新情報を掲載しています。

このドキュメントを最初に確認してください。

Help

ドライバソフトウェアの仕様

,

関数の個別説明、および使用方法等の説明を掲載 しています。プログラム作成時に確認してください。

チュートリアル

本ドキュメントです。初めてRTLinux上でADインタフェースモジュールを制

御する時や、ADインタフェースモジュールを使用したシステム構築時の参考

として確認してください。

本ドキュメントの他、

RTLinuxの導入編のチュートリアルを合わせて参照して

ください。

RTLinuxのインストールや、基本的なプログラミング等が記載されています。

また、

本ドキュメントは、

予めRTLinuxのインストール、

および使用されるソフトウェア(GPG-3100)

のインストールを済ませた方を対象に記述しています。

●本書での表記について

コマンドの実行例において、行頭に「%」がつく場合は一般ユーザでの実行、「#」がつく場合

はrootでの実行を意味します。「%」や「#」は実際に入力する文字ではありませんのでご注意

ください。

(8)

対象環境

本チュートリアルは以下の制約事項があります。

対象型式

(PCI)

PCI-3120

PCI-3135

PCI-3161

PCI-3166

PCI-3171A

PCI-3174

PCI-3177C

PCI-3180

PCI-320416

PCI-3523A

PCI-360116

PCI-3126

PCI-3153

PCI-3163

PCI-3168C

PCI-3172A

PCI-3175

PCI-3178

PCI-320112

PCI-3521

PCI-3525

PCI-360216

PCI-3133

PCI-3155

PCI-3165

PCI-3170A

PCI-3173A

PCI-3176

PCI-3179

PCI-320412

PCI-3522A

PCI-360112

PCI-360810

対象型式

(CPZ)

CPZ-3120A

CPZ-3126

CPZ-3165

CPZ-3170

CPZ-3173

CPZ-3177

CPZ-3180A

CPZ-3182

CPZ-320416

CPZ-3523

CPZ-360116

CPZ-3120B

CPZ-3133

CPZ-3167

CPZ-3171

CPZ-3174

CPZ-3178

CPZ-3180B

CPZ-3183

CPZ-3521

CPZ-3525

CPZ-360810

CPZ-3120C

CPZ-3135

CPZ-3168

CPZ-3172

CPZ-3175

CPZ-3179

CPZ-3180C

CPZ-320412

CPZ-3522

CPZ-360112

対象型式

(CTP)

CTP-3120A

CTP-3126

CTP-3165

CTP-3170

CTP-3173

CTP-3177

CTP-3180A

CTP-3182

CTP-320416

CTP-3523

CTP-360116

CTP-3120B

CTP-3133

CTP-3167

CTP-3171

CTP-3174

CTP-3178

CTP-3180B

CTP-3183

CTP-3521

CTP-3525

CTP-360810

CTP-3120C

CTP-3135

CTP-3168

CTP-3172

CTP-3175

CTP-3179

CTP-3180C

CTP-320412

CTP-3522

CTP-360112

対象型式

(CSI)

CSI-320110

CSI-320412

CSI-320212

CSI-320416

CSI-320312

対象型式

(PEX)

PEX-320724

PEX-321116

PEX-321416

PEX-320910

PEX-321216

PEX-321012

PEX-321316

対象型式

(LPC)

LPC-320724

LPC-321116

LPC-321416

LPC-320910

LPC-321216

LPC-321012

LPC-321316

対象ユーザ 制御用電子機器および、コンピュータ等に関して基本的な知識を有している方。

※ 本冊子は上記の弊社製品型式のみに対応しています。

製品の詳細は弊社Web siteを参照してください。

(9)

第1章 アナログ出力概要

これまでに、アナログ(analog)という言葉を一度は耳にしたことがあると思います。

ではアナログとは何でしょう。しばしばデジタルという言葉と対比し使われますが、デジタルが

「1つ2つと区切って数えられる」のに対し、アナログとは「連続した量で、1つ2つと区切って数

えられない」ものを言います。

デジタル時計とアナログ時計を例に挙げてみます。

デジタル時計では、「1:53」と単純に読み取ればよいわけですが、アナログ時計で仮に小数点以

下を読み取っていくとしたらいかがでしょう。「1:53」, 「1:53.1」, 「1:53.124」, 「1:53.1245……..」

と、きりがありません。

1.1 A/Dコンバータ

私たちが普段の生活で目や耳にする「光」, 「音」の情報は全てアナログ信号です。

今のコンピュータでは音楽や映像の録音や録画ができますが、本来デジタル信号しか処理できな

いコンピュータが、一体どうやってこのようなアナログ信号を取り扱っているのでしょうか?

実は、ある段階でアナログ信号をデジタル信号に変換し、コンピュータに処理させているのです。

これをAD変換といいます。

アナログ信号からデジタル信号に変換する装置を、A/Dコンバータと言います。A/Dコンバータと

は、Analog to Digital Converterの略で、アナログ・デジタル変換器と訳され、これによりアナログ

信号をデジタル信号に変換することができるのです。

本冊子で紹介するアナログ入力製品もA/Dコンバータが搭載された、インタフェースモジュール

です。

「光」, 「音」, 「熱」等の変化は、専用の「センサ」を使用することで、電圧の変化として捉え

ることができます。この電圧はアナログ信号となり、A/Dコンバータによってデジタル信号に変

換され、ハードディスク等の記録媒体に記録されます。

(10)

1.2 A/Dコンバータの用途

私たちの身の回りにある、全ての事象はアナログ的な情報として成り立っています。しかし、コ

ンピュータは直接アナログ情報を扱うことができないため、A/Dコンバータでデジタル値に変換

して、処理を行います。

A/Dコンバータを使った主な用途としては、

・ 音声入力/音声認識

・ 画像入力/画像認識

・ 温度/湿度測定

・ レーダー

・ 電圧/電流の計測

等があります。

1.3 分解能と精度

アナログをデジタルに変換することは、連続した量を不連続な値に変換することを意味します。

ここで、0∼1.0Vの電圧値を2ビットのデジタル値に変換するとします。

2ビットで表現できる値は、「00」「01」「10」「11」の4つとなります。従って、電圧をアナロ

グ量からデジタル量に変換するには、これら4つのデジタル値のうちいずれか1つに変換しなけれ

ばなりません。つまり、0∼1.0Vまでの範囲を4で割った値(=0.25V)がデジタル値1つ分の幅となり

ます。

2つの電圧値V1とV2がこの幅(0.25V)を越えると、デジタル値が変化しV1とV2の差が区別できるよ

うになります。

V1 V2 V1 V2 アナログ値 アナログ値 デジタル値 デジタル値 0.25V 0.25V 2 つのアナログ値が 0.25V範囲外 デジタル値に差が出る 2 つのアナログ値が 0.25V 範囲内 デジタル値が同じ

(11)

この区別できる電圧の範囲、言い換えれば最小単位の1ビットに対するアナログ量を分解能といい、

LSB(Least Significant Bit)として表現されます。一般的には分解能nビットといった具合に表現され

ています。入力電圧が0∼5Vで分解能12ビットの時は、

5

÷ 4096 ≒ 0.00122(V)

が、1LSBとなります。

AD変換されたデジタル値は、1LSBを単位とした離散値になります。このように、それ以上分割

できない最小の単位(この場合LSB)に分割することを量子化といいます。

また、量子化することによって、連続した量が不連続な値になる際、誤差が必ず含まれてしまい

ます。この誤差のことを量子化誤差といいます。

上記の場合、精度が±1LSBならば、-1.22mV∼+1.22mVの範囲で誤差があることを示しています。

したがって、誤差がもっとも大きい場合、測定値+1.22mVまたは測定値-1.22mVとなります。

−1.22mV +1.22mV 最大誤差 測定値

分解能をnビットと表現する場合、本来の分解能はフルスケール(FSR:Full Scale Range)を2のビット

数乗で割った値となります。入力電圧が0∼+5Vの場合はFSR=5、入力電圧が-5V∼+5Vの場合は

FSR=10となります。

n

FSR

LSB

2

1

=

12ビットのAD変換では、最小値0, 最大値4095(FFFh)となり、精度±0.04%FSRの場合、入力電圧

が0∼+10Vならば、FSRの±0.04%、つまり-0.004V∼+0.004Vの範囲内で誤差があることを意味し

ます。

★レンジの上限値 変換データのデジタル値の最大値に相当する電圧は、レンジの上限になりません。 例えば、12ビット分解能,±5Vレンジの時は4095が最大値となり、それに相当する電圧は 10÷4096×4095−5≒4.9975V となります。 ★量子化誤差 高分解能のA/Dコンバータを使えば、より高精度のAD変換が可能です。 入力電圧が0∼+5Vの時、12ビット分解能と16ビット分解能では、以下の違いが生じます。 12ビット分解能:5÷4096 ≒0.00122V(1.22mV) 16ビット分解能:5÷65536≒0.00007629V(76μV) ただ、高分解能のA/Dコンバータは比例して高価なので、計測に要求される精度に合わせて選択する必要があ ります。

(12)

1.4 シングルエンド入力と差動入力

シングルエンド入力は、もっとも一般的な入力方式です。

信号源を、グランド線と信号線の2本の線で入力し、グランド線と信号線間の電圧が入力電圧とし

てAD変換されます。

これに対し、差動入力は信号源を3本の信号線で接続し入力する方式です。3本の信号線はそれぞ

れグランド線, 信号線(+), 信号線(−)です。入力するデータは、グランド線と信号線(+)間の電圧

(A)とグランド線と信号線(−)間の電圧(B)の差、つまりA−Bの値が入力電圧としてAD変換されま

す。

アナログ信号はノイズにより信号そのものが変化します。このような場合、差動入力を行うこと

で、同相ノイズの影響を受けにくくすることができます。一般的にノイズは、グランドに対して

影響することが多く、シングルエンド入力ではデータに影響がでますが、差動入力についてはA, B

の電圧は影響を受けますが、A−Bの値は、ノイズ分が相殺され影響を受けていないデータが得ら

れます。差動入力を図にすると下図のようになります。

ノイズが加わっても… ノイズの影響を差し引いた データが得られる ノイズ 入力A(+) 入力B(-) グランド 入力A-Bの差がデータ

差動入力の問題点は、入力に使用する信号線が、シングルエンド入力方式が2本の信号線で構成で

きるのに対して、3本の信号線を必要とすることです。

このため、

・入力に使用するチャンネル数を多く確保したい場合は、シングルエンド入力

・ノイズの影響をなるべく排したい場合は、差動入力

といった具合に、目的に応じて使い分けます。

(13)

1.5 バイポーラとユニポーラ

アナログ入力は、入力電圧域の違いにより「ユニポーラ(unipolar)」と「バイポーラ(bipolar)」に区

別することができます。ポーラとは「極」を意味し、それぞれ「単極性」, 「双極性」と訳され

ます。

電位差(最大入力電圧−最小入力電圧)が5Vの場合、ユニポーラでは最小入力電圧0Vから最大入力

電圧+5Vの入力を行います。一方、バイポーラでは0Vを中心に最小入力電圧-2.5Vから最大入力電

圧+2.5Vの出力を行います。

0 0.5 1 1.5 2 2.5 3 3.5 4 4.5 5 -2.5 -2 -1.5 -1 -0.5 0 0.5 1 1.5 2 2.5 ユニポーラ 電圧[V] バイポーラ 電圧[V] 時間→ 時間→

1.6 変換時間とサンプリング周波数

A/Dコンバータを用いて、アナログ信号をデジタル信号に変換する時、様々な方式を用いた回路

で変換が行われます。

(変換には、逐次変換型, 積分型, 並列型等と呼ばれる変換方式が用いられます)

アナログ信号をデジタル信号に変換するには、ある一定の時間が必要です。

カタログやマニュアルの仕様等に記載されている5

μsや0.2μs等の値は、A/Dコンバータがデジタル

信号に変換するために必要な時間を指します。

変換時間が5

μsとは、A/Dコンバータがアナログ信号からデジタル信号への変換を開始し、その結

果が得られるまでに、5

μsかかることを意味します。

★変換時間とデータの取得にかかる時間の違い A/Dコンバータが変換にかかる時間とコンピュータのプログラムが、そのデータを受け取る時間は、同じでは ありません。 変換時間とは、インタフェースモジュール上のA/Dコンバータが変換結果を算出する時間です。 実際には、そこからデータがPCI/CompactPCIバスのバス信号線を経由しCPUを通して、データを格納する領域 に値が書き込まれるまで、様々な要因が複雑に絡みます。 (それは、OS, 割込みのオーバーヘッド, メモリ, CPUの速度等です)

これとは別の速度指標として、「サンプリング周波数」という用語があります。

サンプリング周波数とは、1秒間に何回AD変換するかを示します。単位はHzで表されます。

例えば、

サンプリング周波数500Hzとは、

1秒間に500回周期的にAD変換させることを意味します。

お客様がデバイスドライバに対して指示する速度指標は、通常こちらが使われます。

(14)

1.7 標本化定理

下図は、9kHzの入力に対し10kHzでサンプリングした例です。

サンプリングした点を繋いでいくと、予想外の信号が現れてきます。

この予想外の擬似信号を「折り返し信号」と言います。

このように、音声等の入力信号に対し正確にサンプリング(標本化)を行うためには、入力信号の周

波数に対して、2倍以上の周波数でサンプリングする必要があります。

これを、標本化定理と言います。

1.8 マルチADC方式とマルチプレクサ方式

複数チャンネルの入力信号を取り扱う方式として、マルチプレクサ方式とマルチADC(同時変換)

方式があります。

マルチADC方式とは、1つのチャンネルに対して、1つのA/Dコンバータが対に対応している方式

です。

チャンネル 1 AIN1 COM1 A/D コンバータ チャンネル 2 AIN2 COM2 A/D コンバータ チャンネル 3 AIN3 COM3 A/D コンバータ

(15)

対して、マルチプレクサ方式とは、複数のチャンネルが1つのA/Dコンバータをマルチプレクサと

いう切り替えスイッチで共有する方式です。

チャンネル 1 AIN1 COM1 A/D コンバータ チャンネル 2 AIN2 COM2 チャンネル 3 AIN3 COM3 マ ル チ  プ レ  ク サ

このため、複数のチャンネルをサンプリングすると、マルチADC方式とマルチプレクサ方式で実

際のAD変換の時間にズレが生じます。

マルチ ADC 方式 マルチプレクサ方式 チャンネル 1 チャンネル 2 チャンネル 3 チャンネル 1 チャンネル 2 チャンネル 3 サンプリング サンプリング チャンネル 1 チャンネル 2 チャンネル 3 チャンネル 1 チャンネル 2 チャンネル 3

上図は、マルチADC方式とマルチプレクサ方式で、AD変換のタイミングを表したものです。

マルチADC方式では、各チャンネルに対してA/Dコンバータがあるため、同時にAD変換します。

対してマルチプレクサ方式では、複数のチャンネルをマルチプレクサによって切り替えながら使

用するため、AD変換の開始時刻に差が生じます。

両方式のメリット/デメリットを示します。

マルチADC方式

マルチプレクサ方式

メリット

各チャンネルのAD変換に時間的な

ズレは生じません。

A/Dコンバータが1つで済むため、比較的安

価に購入できます。

デメリット A/Dコンバータが複数搭載される

ため、どうしても高価になります。

各チャンネルのAD変換に時間的なズレが

生じます。

マルチプレクサ方式では時間的なズレは生じますが、位相は保たれています。

サンプリングの同時性を重視したい場合はマルチADC、複数信号の同時性は重要視されないなら

マルチプレクサ、という風に選択すると良いでしょう。

(16)

1.9 データ転送方式

アナログ信号からデジタル信号にAD変換された情報は、何らかの形でコンピュータ内のCPUに取

り込む必要があります。

このCPUが、AD変換された情報にアクセスする方式にも様々なやり方があります。

方 式

内 容

I/O方式 AD変換された情報は、CPUがI/Oポートを経由して1つずつアクセスします。

A/D コンバータ データ CPU データ取得

AD変換されたデータは、次のサンプリングが開始される前に、そのデータを

取り込まないと、次のデータで上書きされてしまいます。

システム構成は比較的簡素なため、一般に安価です。

FIFO方式 AD変換された情報は、一旦インタフェースモジュール内のFIFOと呼ばれる

バッファ領域に格納されます。

CPUは、このFIFOバッファにアクセスして、情報を取り出します。

A/D コンバータ データ CPU データ取得 データ データ FIFOバッファ

AD変換されたデータは、FIFOバッファに溜め込まれるため、バッファがオー

バフローしない限り、次のAD変換データに上書きされてしまうことはありま

せん。

このため、高速なサンプリングを行うのに向いています。

ただし、システム構成は複雑になるため、I/O方式に比べて高価になります。

(17)

方 式

内 容

メモリ方式 AD変換された情報は、インタフェースモジュール内のメモリ領域に書き込ま

れます。

CPUは、このメモリ領域にアクセスして、データを取り出します。

(コンピュータのメモリ空間に空いた窓から、インタフェースモジュールのメ

モリにアクセスするイメージです)

A/D コンバータ データ CPU データ取得 データ データ メモリ コンピュータのメモリ空間

A/Dコンバータとメモリは直結されており、AD変換されたデータが高速に書

き込まれていきます。

このため、非常に高速なサンプリングを行うのに向いています。

ただし、システム構成は複雑になるため、高価になります。

バスマスタ方式 AD変換された情報は、コンピュータ内の指定されたメモリ領域に対して書き

込まれます。

CPUは、このメモリ領域にアクセスして、データを取り出します。

A/D コンバータ データ データ データ CPU データ取得 特定のメモリ領域 コンピュータのメモリ空間

AD変換されたデータを書き込むメモリは、コンピュータのメモリに対して行

われるため、コンピュータのメモリを消費します。

しかし、メモリ方式と異なり、コンピュータのメモリが多ければ、それだけ多

くのバッファを確保できます。

(メモリ方式では、インタフェースモジュール上のメモリに左右されます)

メモリ方式同様、非常に高速なサンプリングを行うのに向いています。

ただし、システム構成は複雑になるため、高価になります。

(18)

1.10 アナログ入力製品を使用時の指針

アナログ入力製品を使って計測を行う際一番重要なのは、ノイズ等の外的要因を受けずに安定し

て計測できる環境を構築することです。

計測に望ましい環境の構築の指針を幾つか提示します。

・コンピュータあるいはユニットの電源を安定させる。

アナログ入力製品は、コンピュータ/ユニットから電源を供給されています。

従って、コンピュータ/ユニットの電源が安定すれば、自ずと測定環境も改善されます。

例えば、電源を供給する個所を主電源の近くに配置し、タコ足状態のタップに接続しない、あ

るいはノイズフィルタ付きのUPS等の装置を介して電源を供給する等、3端子コンセントを使用

し、グランドをアースする等の対策があります。

・計測環境と入力源とのグランドを同電位にする。

アナログ入力製品のグランドと入力源のグランドをケーブル等で接続し、同電位状態とします。

・絶縁タイプのインタフェースモジュールを使用する。

バス絶縁タイプと呼ばれるインタフェースモジュールを使用します。

インタフェースモジュール上のアナログ回路とデジタル回路が絶縁されているため、デジタル

ノイズがアナログ回路に混入するのを防ぐことができるので、計測に悪影響を及ぼす恐れを低

減できます。

・入力方式を差動入力にする。

差動方式を採用することで、ノイズによる計測の悪影響を抑えることが可能です。

高精度な計測を行う時、一番推奨できる入力方式です。

・アナログ入力製品と信号源との間を短くする。

短いケーブルを使用します。長いケーブルでアナログ入力製品と信号源を接続すると、それだ

け外部からノイズが混入する恐れが高まります。

アナログ信号の取り扱いには、オシロスコープ等の計測機器を扱うのと同程度の慎重さが求めら

れます。

環境によっては、計測精度は大きく異なりますので、これらの事項を参考に環境を整えてくださ

い。

(19)

第2章 AD (Analog to Digital) on Linux

RTLinuxは、Linux上でリアルタイム処理を可能にするOSです。そのRTLinux上でAD製品を動かす

ことにより、リアルタイム性が要求されるシステムを構築することが可能になります。

2.1 RTLinuxによるAD製品制御

RTLinux上で弊社AD製品を制御するには、お客様の作成するRTLinuxモジュールからRTLinux対応

ドライバソフトウェアの関数を呼び出すことで行います。

通常、RTLinuxモジュールではRTLinuxスレッドを生成し、ここから関数を呼び出して処理を行い

ます。

また、RTLinuxモジュールとLinuxアプリケーションがデータのやりとりを行う場合は、RT-FIFO

を使用します。

制御構成を簡単に示すと、下図のようになります。

AD I/Oモジュール RTLinux対応ドライバ モジュール(rcp3100.o) RTLinuxモジュール Linux アプリケーション 信号入力 計測対象 RTLinuxスレッド

RT-FIFO

RTLinux

上でのAD製品制御構成

● RTLinuxモジュール リアルタイム処理を行うモジュール本体です。お客様はRTLinux対応ドライバソフトウェアを使って、 AD製品を制御するために、このモジュールを作成する必要があります。 ● RTLinuxスレッド 実際にリアルタイム処理を行う際、RTLinuxモジュール下で動作するRTLinuxスレッドを作成します。こ のRTLinuxスレッドは通常のLinuxのプロセスよりも優先して実行されます。 ● RT-FIFO リアルタイムFIFOとも呼ばれます。RTLinuxスレッドとLinuxアプリケーション、またはRTLinuxスレッ ド同士のデータの受け渡しを行うために使用されます。 ★RT-FIFO RT-FIFOはデバイスとして扱われており、/dev/rtf0等という名前で存在しています。

(20)

2.2 AD製品制御概略

AD製品の制御は、下記の制御シーケンス(順番)で行います。

インタフェースモジュール 初期化

各種処理

終了処理

(3)

(2)

(1)

AD

製品の制御シーケンス

(1)インタフェースモジュールの初期化

AD製品への操作を行うため、まずインタフェースモジュールを利用可能な状態にします。

この処理がインタフェースモジュールの初期化です。インタフェースモジュールの初期化を行

うと、プログラムはインタフェースモジュールへのアクセスが可能となります。本処理が行わ

れないとインタフェースモジュールへのアクセスは行えません。

(2)各種処理

AD製品を使って、制御を行います。

(3)終了処理

インタフェースモジュールの使用終了を行うための手続きです。プログラム終了時に行います。

(21)

第3章 AD製品制御の第一歩

ここでは、実際に弊社AD製品を用いて、AD製品の制御プログラムを作成します。

この章では例として、以下の製品を使用しています。

PCI-3133

1枚:AD製品

ECO-7610

1本:50ピンハーフピッチ←→アンフェノール接続ケーブル

TNS-5000

1台:50点スモールタップ端子台

33120A

1台:ファンクションジェネレータ(アジレント・テクノロジー社製)

BNC

ケーブル

1本

下図に、接続構成を示します。

これは、ファンクションジェネレータの出力を、AD製品のチャンネル1とチャンネル2に、シング

ルエンド入力方式で接続する例です。

PCI-3133 ECO-7610 TNS-5000 ファンクションジェネレータ(33120A) BNCケーブル 赤 赤 黒 黒

RSW1

AD製品(PCI-3133)の製品識別用ロータリスイッチ(RSW1)を0に設定し、コンピュータに実装しま

す。

AD製品を、接続ケーブル(ECO-7610)を介して端子台(TNS-5000)に接続します。そこから、BNCケー

ブルを介して、ファンクションジェネレータに接続します。

お手持ちのAD製品で、どのように接続すれば良いかについては、ハードウェアマニュアルの『外

部接続』を参照してください。

(22)

製品をシステムに組み込んでから、動かすまでの流れは下記のようになります。

各項目に従って、RTLinux上でのAD製品制御プログラミングを行っていきましょう。

RTLinux

リアルタイムカーネルの

組み込み

RTLinux AD

ドライバ組み込み

プログラミング

コンパイル

実行

RTLinux上での製品制御までの流れ

3.1 RTLinux ADドライバの組み込み

RTLinuxのADドライバを組み込む前に、RTLinux導入編のチュートリアルを参照し、RTLinuxのイ

ンストールとRTLinuxモジュールを動かすために必要なリアルタイムカーネルのインストールを

行ってください。

参照箇所:

RTLinuxのインストール

第1章 RTLinuxの導入

リアルタイムカーネルの組み込み

第2章 RTLinuxのインストール

1.

スーパーユーザになります。

%su Password:---rootのパスワード

2. RTLinuxのリアルタイムモジュールを組み込みます。

#rtlinux start

3. GPG-3100のドライバモジュール, 共通モジュール, 割り込み共用モジュール

ドライバモジュールの組み込みを行います。

ドライバ組み込み用シェルスクリプトを実行してください。

例)インストールディレクトリがデフォルトの場合

#cd /usr/src/interface/gpg3100/(アーキテクチャ名)/rtl/drivers #sh insad.sh

(23)

4.

プログラムを作成し、デバイスの制御を行います。

プログラムの作成方法については、チュートリアルを参照してください。

5. RTLinuxのドライバモジュール等の組み込みの解除は、

ドライバ組み込み解除用シェルスクリプ

トを実行してください。

例)インストールディレクトリがデフォルトの場合

#cd /usr/src/interface/gpg3100/(アーキテクチャ名)/rtl/drivers #sh rmad.sh

●カーネルバージョンについて

予め用意しているドライバと異なるカーネルバージョンに組み込む場合は、警告が出たり、組

み込めない場合があります。

組み込めない場合や、組み込めても正常に動作しない場合は、次の手順でドライバをコンパイル

し直してください。

1.

「インストールディレクトリ/common」ディレクトリにある全てのモジュールに対してしてコン

パイルを行い、インストールします。

<dpg0100>

#cd /usr/src/interface/common/dpg0100/src #make #make install

<dpg0101>

#cd /usr/src/interface/common/dpg0101/src #make #make install

<dpg0102>

#cd /usr/src/interface/common/dpg0102/src #make #make install

2. RTLinuxのドライバのsrcディレクトリに移動し、モジュールのコンパイルを行い、インストー

ルします。

<RTLinuxの場合>

#cd /usr/src/interface/gpg3100/(アーキテクチャ名)/rtl/drivers/src #make #make install

3.

各ドライバに用意されているドライバ組み込み用シェルスクリプト(insad.sh)を同様に実行しま

す。

(24)

●テストドライバについて

本ソフトウェアは、デバイスが無くてもドライバの動きをテストできるテストドライバを提供し

ております。テストドライバの使用方法を下記に示します。

(テストドライバの詳細については、Helpを参照してください。)

<RTLinuxの場合>

通常のドライバを使用する場合は、モジュールrcp3100.oを組み込みますが、テスドライバを使用

する場合は、代わりにモジュールrcp3100t.oを組み込んでください。(rcp3100.oとrcp3100t.oを同時

に使用することはできません。)

#insmod rcp3100t

以上でテストドライバを使用できるようになります。

ドライバモジュールの組み込みは、insad.shスクリプトで簡単に行えます。

# cd /usr/src/interface/gpg3100/i386/rtl/drivers # sh insad.sh

モジュールが組み込まれているかどうかlsmodコマンドを使って確認します。

# lsmod

Module Size Used by

rcp3100 157872 0 (unused) dpg0102 790448 0 [rcp3100] dpg0100 6272 0 [rcp3100] rtl_sched 43200 0 [rcp3100 dpg0100] rtl_fifo 10016 0 (unused) rtl_posixio 7216 0 [rtl_fifo]

rtl_time 10064 0 [rcp3100 rtl_sched rtl_posixio] rtl 27184 0 [rcp3100 dpg0102 dpg0100 rtl_sched rtl_fifo rtl_posixio rtl_time]

dpg0100, dpg0102, rcp3100が組み込まれていることが分かります。

以上で、AD製品のリアルタイム制御を行うプログラミングまでの準備が整いました。

ドライバモジュールの取り外しは、rmad.shスクリプトで行います。

#cd /usr/src/interface/gpg3100/i386/rtl/drivers #sh rmad.sh

以上で準備は終わりです。次からいよいよプログラミングを行っていきます。

(25)

★スクリプトを使わずに組み込むには? ドライバモジュールを組み込みは、スクリプトを使用することが簡単なのでお奨めですが、直接ドライバモジ ュールを組み込むことも可能です。 以下にinsmodコマンドを使った場合の組み込み例を示します。 insmodコマンドを使って、ドライバモジュールを組み込む場合> # insmod dpg0100 # insmod dpg0102 # insmod rcp3100 rmmodコマンドを使って、ドライバモジュールを取り外す場合> # rmmod rcp3100 # rmmod dpg0102 # rmmod dpg0100

3.2 1件のAD入力を行う

ここでは、AdInputAD関数を使って、1件のAD入力を行うプログラムを作成します。

エディタを起動し、下記に示すプログラムを入力して、ファイル名を「sample1.c」として保存し

てください。

★プログラム中のコメントについて サンプルプログラムには、理解し易いよう、日本語コメントを用いています。 しかし、プログラム中に日本語を用いてコンパイルすると、正常にコンパイルできない場合があります。 その時は、日本語コメントを削除してコンパイルしてください。

sample1.c

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 #include <rtl.h> #include "fbiad.h"

#define CH_NUM 2 /* 1件のAD入力で取り込む総チャンネル数 */ #define DEVICE_ID 3133 /* 製品を特定する一意のID値(PCI-3133を表す) */ #define SUB_SYSTEM_ID 0x0001 /* 製品を特定する一意のID値(PCI-3133を表す) */ #define RSW_NO 0 /* 同一型式の製品を区別するRSW1設定値 */ int g_device_no = -1; /* AD製品のデバイス番号 */

/* 初期化関数(モジュールが組み込まれた時、呼ばれる関数) */ int init_module(void)

{

int i, ret;

ADSMPLCHREQ smp_ch_req[CH_NUM]; /* 1件のAD入力を行う際の情報を設定する構造体宣言 */ unsigned short ad_data[CH_NUM]; /* 1件のAD入力で取り込むデータ配列の宣言 */ rtl_printf("init_module called¥n"); EXPORT_NO_SYMBOLS; /* AD製品のオープン */

ret = AdOpenEx(DEVICE_ID, SUB_SYSTEM_ID, RSW_NO, &g_device_no); if(ret){

rtl_printf("AdOpenEx error [ret=%x]¥n", ret); return -1;

} else {

rtl_printf("AdOpenEx success!! [device no=%d]¥n", g_device_no); }

/* 1件のAD入力 */

for(i = 0; i < CH_NUM; i++){

smp_ch_req[i].ulChNo = 1 + i; /* チャンネルを指定(1, 2を順に指定しています) */ smp_ch_req[i].ulRange = AD_0_5V; /* レンジ:0∼+5Vを指定 */

}

(26)

38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 CH_NUM, /* 1件のAD入力時に取り込む、総チャンネル数 */ AD_INPUT_SINGLE, /* シングルエンド入力 */ smp_ch_req, /* 各チャンネルの情報設定 */ ad_data); /* 取り込むデータ配列のポインタを指定 */ if(ret){

rtl_printf("AdInputAD error [DeviceNo=%d ret=%x]¥n", g_device_no, ret); return -2;

}

/* 取り込んだデータの表示(バイナリ値で表示しています) */ for(i = 0; i < CH_NUM; i++){

rtl_printf("channel no=%d get data=%x¥n", smp_ch_req[i].ulChNo, ad_data[i]); } return 0; } /* 終了関数(モジュールが取り外される時、呼ばれる関数) */ void cleanup_module(void) { int ret; rtl_printf("cleanup_module called¥n"); /* AD製品のクローズ */ ret = AdClose(g_device_no); if(ret){

rtl_printf("AdClose error [DeviceNo=%d ret=%x]¥n", g_device_no, ret); } }

次に、下記に示すプログラムを入力し、ファイル名を「makefile」として保存してください。

これは、上記プログラムをコンパイルするメイクファイルです。

makefile

1 2 3 4 5 include /usr/include/rtlinux/rtl.mk all: sample1.o sample1.o:sample1.c

$(CC) $(INCLUDE) $(CFLAGS) -o sample1.o -c sample1.c

コンパイルすると、RTLinuxモジュールsample1.oが作成されます。insmodコマンドで、RTLinuxモ

ジュールを組み込みます。

# make # ls

makefile sample1.c sample1.o # insmod sample1.o

組み込む前にリスト中のrtl_printf関数の出力内容が画面で確認できるよう、X Windowで使用され

ている方は、コンソールをもう一つ立ち上げ、次のコマンドを入力してください。

# tail –f /var/log/messages

コンソール画面で作業されている方は、次のように打ち込んでください。

# tail –f /var/log/messages &

(27)

★/var/log/messagess syslogやcron等で実行されたサービスのログ等の情報は、「/var/log/」に保存されます。通常、ログは 「/var/log/messages」に保存されることが多いです。 RTLinuxでは、rtl_printf関数を使って、ここに出力し、デバッグプリントができるようになっています。 (そのままコンソール画面に出力されるようには、なっていません) 上の用例では、tailコマンドを使って、このログ出力を常に表示状態にしています。 コンソール画面の例で用いた&(アンパサンド)コマンドはジョブコマンドの一種で、tailコマンドをバック グランドで実行させています。 コンソール画面では、X Windowのように幾つもコンソールを起動することができないので、このように します。

sample1.oを組み込むと、1件のAD入力したデータが表示されます。

(以下は例です。お客様の環境で実行した際、AD入力された値は異なる場合があります)

# insmod sample1.o init_module called channel no=1 0012 channel no=2 0005

次に、組み込んだRTLinuxモジュールを取り外します。

コンソールに以下を入力し、Enterキーを押します。

# rmmod sample1

すると、コンソール画面は、以下のメッセージが表示されます。

# rmmod sample1 cleanup_module called

RTLinuxモジュールが取り外されたことが分ります。

何度かinsmodコマンドによるモジュール組み込みとrmmodコマンドによるモジュール取り外しを

繰り返してみてください。

その都度、メッセージが表示されることがわかります。

(28)

3.3 1件のAD入力プログラムの解説

それでは、先程のプログラムの解説を行います。

まず、このプログラムの動作概要を示します。

sample1.o RTLinuxモジュール RTLinux 組み込み(insmod) 取り外し(rmmod) init_module関数 cleanup_module関数

sample1

の動作概要

作成したRTLinuxモジュールをinsmodコマンドでRTLinuxに組み込む時、init_module関数が呼ばれ

ます。init_module関数ではAD製品のオープン処理と、1件のAD入力を行っています。

また、rmmodコマンドで取り外す時、cleanup_module関数が呼ばれます。cleanup_module関数では

AD製品のクローズ処理をしています。

製品の制御では、オープン処理を行わないと何の制御もできません。ファイルに読み書きする時、

open関数を使ってオープンしないと何もできないのと同じことです。

そして、製品の制御を終える時必ずクローズ処理を行う必要があります。

サンプルでも、この形式に従って処理を行っています。

以降で細かく動きを見ていきますが、この基本事項を守っていることに注意して読み進めてくだ

さい。

(23行目:AdOpenEx関数)

AD製品を制御する前段階として、AD製品をオープンするAdOpenEx関数を呼び出しています。

以下に引数と対応を示します。

引数名

内 容

wDeviceID

デバイスIDを指定します

wSubSystemIDと組み合わせて、製品の型式を指定します。

組み合わせについては、Helpを参照してください。

wSubSystemID

サブシステムIDを指定します。

bRSW1

製品識別用ロータリスイッチ(RSW1)の設定値を指定します。

pnDevice

上記の組み合わせに対するデバイス番号が、呼出し後にセットされます。

(29)

この引数を与えて関数を呼び出すと、ドライバモジュールは引数に適合するAD製品を検索し、合

致した製品に対してデバイス番号を割り振り第4引数に返します。

プログラマは、このデバイス番号を使って以降のAPIの呼び出しを行います。

★何故、AdOpenEx関数を使うのか? LinuxやWindowsプログラムでは、AdOpen関数を使用しますが、RTLinuxではAdOpenEx関数の使用を推奨して います。 これは、プログラムで使用するAD製品を、システム内で一意のID値を使用することで、他の環境にシステム を移築しても特定するためにあります。 AdOpen関数を使用した場合、第1引数で指定するデバイス番号は、RTLinuxシステム内でAD製品が認識された 順番に割り振られます。 この場合、複数のAD製品を使用していた場合、ユニット並びにコンピュータ内のAD製品の順番を変更した際、 想定外のデバイス番号が割り振られてしまう恐れがあります。 これを避けるため、RTLinuxプログラムでは、AdOpenEx関数を使い、AD製品を特定してデバイス番号を得る 仕組みを推奨しています。

(37行目:AdInputAD関数)

ここでは、AdInputAD関数を用い1件のAD入力を行っています。

1件のAD入力では、1から複数チャンネルのAD入力が可能です。関数を呼び出すと、ドライバモ

ジュールは引数で指定された各チャンネルのAD入力を1件だけ行い、第5引数で渡された配列に結

果を返します。返されるADデータは、バイナリ値です。

第5引数では結果を格納する配列のポインタを渡す必要があります。

配列の大きさは、以下の式で求めることができます。

配列の大きさ = AD入力に必要なデータサイズ

× チャンネル数(第2引数の値)

AD入力に必要なデータサイズは、AD製品の分解能で求めることができます。

分解能 データサイズ 8ビット 1バイト 12ビット 2バイト 16ビット 2バイト 24ビット 4バイト

後述しますが、AdInputAD関数と同カテゴリ関数のAdSetInputADEx関数およびAdInputADEx関数

の組を使用した場合、AD入力データはバイナリ値だけでなく、電圧値/電流値の形式で取得するこ

とが可能です。

この時、AD入力に必要なデータサイズは、分解能によらず、全て8バイト(double型のサイズ)とな

ります。

サンプルでは、2チャンネルのAD入力を行っていますが、例えば4チャンネルのAD入力を行う場

合、必要な配列の大きさは、2(バイト)

×4(チャンネル数)=8バイトとなります。

(30)

配列に格納されるAD入力のデータの順は、第4引数のチャンネル指定順となります。

サンプルでは、1, 2チャンネルの順にチャンネルを指定しているので、配列のデータも、1, 2チャ

ンネルの順に格納されます。

もし、2, 1チャンネルの順にチャンネルを指定すると、配列のデータも2, 1チャンネルの順に格納

されます。

(48∼50行目:AD入力データの出力)

ここでは、AdInputAD関数で得たAD入力のデータを、rtl_printf関数を使ってログに出力していま

す。

(63行目:AdClose関数)

AD製品の制御を終了するためには、AdClose関数を用います。

オープンしたAD製品は、使用後は必ずクローズしてください。

★AdClose関数を呼ばないと、どうなるか? AdClose関数を呼び出さないと、AD製品はオープンしたままの状態になります。 オープン状態なので、AdOpen関数を呼び出した場合、エラーが返ります。 こういう事態に陥った場合、対処方法としては、GPG-3100ドライバモジュール(rcp3100)を、一旦取り外す必 要があります。 オープンしたら必ずクローズしてください。

(31)

第4章 より高度な処理を行う

前述のプログラムは、RTLinuxモジュールの組み込みと取り外しの時にしか動作しないものです。

実際のプログラミングでは、誰かから(大抵は上位アプリケーション)指令を受け、その指令に従っ

て何らかのアクションを起こすのが普通です。

この章では、LinuxプログラムからRTLinuxモジュールを制御するプログラムを作成します。

4.1 AdInputADExを使った周期的なサンプリング

先程では、AdInputAD関数を使って1件のAD入力を行いました。

ここでは、同じく1件のAD入力を行うAdInputADEx関数を使い、周期的なスレッドを動作させて

周期的なサンプリングを実現します。

以下の4つのファイルを作成します。

ファイル名

備 考

sample2.h

LinuxプロセスとRTLinuxモジュールの双方で共有する定義ファイル

module2.c

RTLinuxモジュールのソースコード

sample2.c

Linuxプロセスのソースコード

makefile

上記ソースコードをコンパイルするためのmakefile

下記は、LinuxプロセスとRTLinuxモジュール間で、共通で使う定義ファイルです。ファイル名を

「sample2.h」として保存してください。

sample2.h 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 /* sample2.h 共通定義ヘッダファイル

Copyright 2002 Interface Corporation. All rights reserved. */

#if !defined(___SAMPLE2_H) #define ___SAMPLE2_H

#include "fbiad.h"

/* Constants --- */

#define FIFO_COMMAND 1 /* Linuxプロセスから指令を受け取るRT-FIFO */

#define FIFO_THRU_CMD 2 /*ハンドラからRTLinuxスレッドへ指令を受け渡しするRT-FIFO */ #define FIFO_RESULT 3 /* Linuxプロセスへ結果を送るRT-FIFO */

#define DEVICE_ID 3133 /* 製品を特定する一意のID値(PCI-3133を表す) */ #define SUB_SYSTEM_ID 0x0001 /* 製品を特定する一意のID値(PCI-3133を表す) */ #define RSW_NO 0 /* 同一型式の製品を区別するRSW1設定値 */ #define CH_NUM 2 /* 1件のAD入力の総チャンネル数 */

#define BUFF_SIZE 100 /* Linuxプロセスへ結果を送るRT-FIFOのサイズ */ typedef unsigned short AD_TYPE; /* ADデータの型 */

/* Command ID --- */ /* コマンドID群(周期サンプリング用スレッドへの指示用) */ enum CMD_IDS { ID_START, /* サンプリングのスタート指示 */ ID_STOP /* サンプリングのストップ指示 */ }; /* コマンド指示用の構造体 */ struct CMD_STRUCT {

enum CMD_IDS id; /* コマンドID */

/* 各コマンドに対する設定パラメータ */

long smp_period_ms; /* ID_START時使用:サンプリング周期の設定(ms単位) */ };

(32)

★ワンポイント お使いのAD製品がPCI-3133でない場合、sample2.hの16、17行目を使用している製品に合わせて修正してくだ さい。 型式とID値の対応は、HelpのAdOpenEx関数の説明を参照してください。 以下に、CTP-3166を使用する場合の例を示します。 #define DEVICE_ID 3166 ← 3133を3166に変更。 #define SUB_SYSTEM_ID 0x0101 ← 0x0001を0x0101に変更。 下記

は、RTLinuxモジュールのソースファイルです。ファイル名を「module2.c」として保存してく

ださい。

module2.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 /* module2.c RTLinuxモジュールのソースコード

Copyright 2002 Interface Corporation. All rights reserved. */ #include <rtl.h> #include <rtl_sched.h> #include <rtl_fifo.h> #include "sample2.h" pthread_t my_task_info;

int g_device_no = -1; /* AD製品のデバイス番号 */ /* サンプリングを行うRTLinuxスレッド */

void* my_task(void* arg) {

int ret; struct CMD_STRUCT cmd;

AD_TYPE ad_data[CH_NUM]; /* 1件のAD入力時に取り込むデータ配列 */

rtl_printf("my_task called arg=%d¥n", arg); /* RTLinuxスレッドが組み込み中、動作する永久ループ */ while(1){ /* 自スレッドを、次の周期までスリープさせる */ pthread_wait_np(); /* RT-FIFOからの指示があれば取り込み */ ret = rtf_get(FIFO_THRU_CMD, &cmd, sizeof(cmd)); if(ret == sizeof(cmd)){

rtl_printf("my_task: get command id=%d¥n", cmd.id); switch(cmd.id){ case ID_START: /* サンプリングのスタート */ rtl_printf("my_task: start!!¥n"); pthread_make_periodic_np(pthread_self(), gethrtime(), cmd.smp_period_ms * 1000 * 1000); break; case ID_STOP: /* サンプリングのストップ */ rtl_printf("my_task: stop!!¥n"); pthread_suspend_np(pthread_self()); break; default:

rtl_printf("my_task: unknown command!!¥n"); break;

} }

/* 1件のAD入力を行う */

ret = AdInputADEx(g_device_no, ad_data); if(ret){

(33)

57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 } } return 0; } /* Linuxプロセスからの指令を受け取るハンドラ */ int my_handler(unsigned int fifo)

{

int ret; struct CMD_STRUCT cmd;

rtl_printf("my_handler called fifo=%d¥n", fifo);

/* Linuxプロセスの指示を、RT-FIFOを介して、RTLinuxスレッドに横流しする */ while((ret = rtf_get(FIFO_COMMAND, &cmd, sizeof(cmd))) == sizeof(cmd)){

rtf_put(FIFO_THRU_CMD, &cmd, sizeof(cmd)); rtl_printf("my_handler: get command id=%d¥n", cmd.id); pthread_wakeup_np(my_task_info);

}

if(ret != 0){

rtl_printf("my_handler: error!!(%d)¥n", ret); return -EINVAL; } return 0; } /* 初期化関数(モジュールが組み込まれた時、呼ばれる関数) */ int init_module(void) { int i, ret;

ADSMPLCHREQ smp_ch_req[CH_NUM]; /* 1件のAD入力を行う際の情報を設定する構造体の宣言 */ rtl_printf("init_module called¥n"); EXPORT_NO_SYMBOLS; /* Linuxプロセスからの指示を受け取るハンドラとRT-FIFOを生成する */ rtf_destroy(FIFO_COMMAND);

rtf_create(FIFO_COMMAND, sizeof(struct CMD_STRUCT)); rtf_create_handler(FIFO_COMMAND, my_handler);

/* ハンドラとRTLinuxスレッドの間のRT-FIFOを生成する */ rtf_destroy(FIFO_THRU_CMD);

rtf_create(FIFO_THRU_CMD, sizeof(struct CMD_STRUCT));

/* Linuxプロセスへ結果を返すRT-FIFOを生成する */ rtf_destroy(FIFO_RESULT);

rtf_create(FIFO_RESULT, sizeof(AD_TYPE) * BUFF_SIZE);

/* AD製品のオープン */

ret = AdOpenEx(DEVICE_ID, SUB_SYSTEM_ID, RSW_NO, &g_device_no); if(ret){

rtl_printf("AdOpenEx error [ret=%x]¥n", ret); return -1;

} else {

rtl_printf("AdOpenEx success!! [device no=%d]¥n", g_device_no); }

/* 1件のAD入力の初期設定 */ for(i = 0; i < CH_NUM; i++){

smp_ch_req[i].ulChNo = 1 + i; /* チャンネルを指定(1,2を順に指定しています) */ smp_ch_req[i].ulRange = AD_0_5V; /* レンジ:0∼+5Vを指定 */

}

ret = AdSetInputADEx( g_device_no,

CH_NUM, /* 1件のAD入力時に取り込む、総チャンネル数 */ AD_INPUT_SINGLE, /* シングルエンド入力 */

smp_ch_req, /* 各チャンネルの情報設定 */ CONV_BIN); /* データをバイナリ値で取得 */ if(ret){

rtl_printf("AdSetInputADEx error [ret=%x]¥n", ret); return -2;

}

/* RTLinuxスレッドを作成、起動する */

(34)

133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 /* 終了関数(モジュールが取り外される時、呼ばれる関数) */ void cleanup_module(void) { int ret; rtl_printf("cleanup_module called¥n"); /* AD製品をクローズする */ ret = AdClose(g_device_no); if(ret){

rtl_printf("AdClose error [ret=%d]¥n", ret); } /* RT-FIFOを閉じる */ rtf_destroy(FIFO_COMMAND); rtf_destroy(FIFO_THRU_CMD); rtf_destroy(FIFO_RESULT); /* RTLinuxスレッドを終了させる */ pthread_cancel(my_task_info); pthread_join(my_task_info, NULL); }

下記は、Linuxプロセスのソースファイルです。ファイル名を「sample2.c」として保存してくださ

い。

sample2.c 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 /* sample2.c Linuxプロセスのソースコード

Copyright 2002 Interface Corporation. All rights reserved. */ #include <stdio.h> #include <fcntl.h> #include <unistd.h> #include <sys/time.h> #include <sys/ioctl.h> #include <rtl_fifo.h> #include "sample2.h" /* Linuxプロセスのメインルーチン */ int main(void) { int i, j; int fd_result, fd_cmd; fd_set rfds; struct timeval tv; struct CMD_STRUCT cmd;

AD_TYPE ad_data[CH_NUM]; /* 1件のADデータを格納する領域 */ char rt_fifo_name[80];

/* RTLinuxモジュールに指令を送るFIFOチャネルのオープン */ sprintf(rt_fifo_name, "/dev/rtf%d", FIFO_COMMAND);

if((fd_cmd = open(rt_fifo_name, O_WRONLY)) < 0){ fprintf(stderr, "Fail to open %s¥n", rt_fifo_name); return -1;

}

/* RTLinuxモジュールからの結果を受け取るFIFOチャネルのオープン */ sprintf(rt_fifo_name, "/dev/rtf%d", FIFO_RESULT);

if((fd_result = open(rt_fifo_name, O_RDONLY)) < 0){ fprintf(stderr, "Fail to open %s¥n", rt_fifo_name); return -2;

}

/* サンプリングの実行開始の指示 */ cmd.id = ID_START;

(35)

45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 } /* 100件のデータをサンプリングするまでループ */ for(i = 0; i < 100; i++){ FD_ZERO(&rfds); FD_SET(fd_result, &rfds); tv.tv_sec = 30; /* select関数のタイムアウト値の設定:30秒 */ tv.tv_usec = 0; /* サンプリングデータの受け取り */

if(select(FD_SETSIZE, &rfds, NULL, NULL, &tv) > 0){

if(FD_ISSET(fd_result, &rfds)){ /* fd_resultに対してFIFOの書き込みがあった */ read(fd_result, ad_data, sizeof(AD_TYPE) * CH_NUM);

for(j = 0; j < CH_NUM; j++){

printf("ch=%d data=%x¥n", j, ad_data[j]);

} } } } /* サンプリングの停止指示 */ cmd.id = ID_STOP; cmd.smp_period_ms = 0;

if(write(fd_cmd, &cmd, sizeof(cmd)) < 0){

fprintf(stderr, "fail to send the stop command¥n"); return -4; } printf("fd_cmd:%d¥n", close(fd_cmd)); printf("fd_result:%d¥n", close(fd_result));

printf("The Linux process is successfully completed.¥n"); return 0; }

下記は、上記ファイルをコンパイルするメイクファイルです。ファイル名を「makefile」として保

存してください。

makefile

1 2 3 4 5 6 7 8 include /usr/include/rtlinux/rtl.mk all: module2.o sample2

sample2: sample2.c

$(CC) $(INCLUDE) $(USER_CFLAGS) -O2 -Wall -o sample2 sample2.c

module2.o:module2.c

$(CC) $(INCLUDE) $(CFLAGS) -o module2.o -c module2.c

コンパイルし、insmodコマンドでリアルタイムモジュールを組み込みます。

# make ← コンパイルします

# ls ← コンパイルしたファイルを一覧表示します

makefile sample2 module2.c module2.o sample2.c sample2.h # insmod module2.o ← RTLinuxモジュールを組み込んでいます

次に、Linuxプログラムを実行します。

(36)

実行画面を以下に示します。(画面左上がLinuxプロセスを実行しているコンソール。画面右下の

はRTLinuxモジュールのログメッセージを表示させているコンソールです)

sample2

実行時の画面

sample2を実行させると、「ch=xx data=xxxx」と表示が繰り返し出力され、しばらくしてプログラ

ムが終了します。

4.2 AdInputADExを使った周期的なサンプリングの解説

それでは、前述のプログラムの解説を行います。

まず、LinuxプロセスとRTLinuxモジュールの関係を下図に示します。

main init_module cleanup_module my_task my_handler 生成 生成 指令 指令の転送 結果の通知 破棄 破棄 カーネル空間 ユーザ空間 Linuxプロセス(sample2) RTLinuxモジュール(module2.o) FIFO_COMMAND FIFO_THRU_CMD FIFO_RESULT LinuxプロセスとRTLinuxモジュールの相関関係

参照

関連したドキュメント

CE1 Series/ものさしくん

 医薬品医療機器等法(以下「法」という。)第 14 条第1項に規定する医薬品

2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017

直流抵抗 温度上昇 PART

品名(Part name) 数量(Quantity).. 品名(Part name) 数量(Quantity).. 品名(Part name) 数量(Quantity).. 部品番号 (Part No.) 品名(Part name)

          ITEC INTERNATIONAL 株式会社. 型名

Updated list of REACH SVHC substances – added 1 new substance according to ECHA list issued on 20 th June. Added Table “Restrictions to manufacturing processes used to

Reduced-Risk Products (RRP): 喫煙に伴う健康リスクを低減させる可能性のある製品。当社製品ポートフォリオにおけるheated tobacco sticks (HTS), infused-tobacco