AN 1006.TFCシグナルコンディショナからの測定値の取得

説明

このアプリケーションノートでは、電解チルトセンサとシグナルコンディショナからチルト測定を行う方法について説明します。フレデリックス社のシグナルコンディショナで利用可能な各プロトコルの回路図とコードをカバーしています。すべての例は、Arduino Unoのコードと回路を示すので、他のプラットフォームを使用する場合は、コードに違いがあります。各例では、センサーからの生出力をさまざまな単位で提供します。これらの単位は、アプリケーションノート1005で説明されている方法を使用して、度数に変換することができます。

アナログ

シグナルコンディショナー1-6200-007,1-6200-012ともに,アナログ出力があります。1-6200-007では、両軸と温度がそれぞれXA、YA、Tピンから出力されます。Arduino との接続は、シグナルコンディショナから Arduino のアナログ入力ピンに直接接続する必要があります。

図 1 1-6200-007 と Arduino をアナログで接続するための回路図

なお、シグナルコンディショナ 1-6200-012 にはアナログ温度出力がありませんので、RS-232 で温度を読み取る必要があります。1-6200-012 からの温度の読み取りについては、「RS-232」の項を参照してください。

回路を組み立てた状態で、ArduinoのanalogRead()関数を使ってデータを読み込むことができます。その例を以下に示します。

x = analogRead(A0).
y = analogRead(A1).
温度 = analogRead(A2).

このコードの結果は、アナログ・ピンの電圧を表す生の値になります。この測定の分解能は、電圧の読み取りに使用されるハードウェアに依存します。

PWM

1-6200-007シグナルコンディショナでは、PWM測定が可能です。PWM測定では、シグナルコンディショナのデジタルXP、YP端子からX、Yの傾斜角度を読み取ることができます。温度PWM出力はありませんので、アナログピンから読み取る必要があります。このセットアップの回路図を図 2 に示します。

図 21-6200-007 と Arduino を PWM で接続するための回路図

PWM出力は、PWMピンだけでなく、Arduino上の任意のデジタルピンに接続することができることに注意してください。この例では、D7とD8のピンを使用していますが、どちらもPWMピンではありません。

ArduinoでPWM信号を読み出すには、pulseIn()関数を使用するのが最適です。pulseIn()関数は、パルスがハイまたはローの状態でどれくらいの時間続くかを計測します。ここでは、ハイ・ステートの時間を設定します。

x = pulseIn(XPIN, HIGH).
y = pulseIn(YPIN, HIGH).
温度 = analogRead(A0).

char res[50].
sprintf(res, "X: %i, Y: %i, Temperature: %i", x, y, temperature).
Serial.println(res)

結果は、マイクロ秒単位のパルスの長さになります。pulseIn() 関数は 10μs という短いパルスを読み取ることができますが、これは 8ms までのパルスの測定が 10 ビット出力と同等の精度を持つことを意味します。この精度は、それを読み取るデバイスがより小さなパルスを検出できる場合に高くなります。

エスピーアイ

SPI は、1-6200-005シグナルコンディショナで利用可能な同期シリアル通信プロトコルです。このプロトコルは、4 つの接続を使用してマスター/スレーブ技術で動作します。MISO(Master In Slave Out)、MOSI(Master Out Slave In)、CLK(Serial Clock)、SS(Slave Select)の4つの接続を使用します。マスターはMOSI(1-6200-005のINと表示されている)を介してスレーブにコマンドを送信し、スレーブはMISO(1-6200-005のOUTと表示されている)を介して応答します。CLK はスレーブの通信を同期させるためにマスターが作成するクロックです。SS はスレーブをイネーブルにするために使用されます。このピンは SPI が 1 つのバス上で複数のデバイスをサポートする方法を示しています(詳細は「SPI バス」のセクションを参照)。

Arduino Unoには、MOSI、MISO、CL用の定義済みピンがあります。これらを以下の表に示します。

きんぞくさん D11
ミソ D12
CLK D13

これらをArduinoに接続するための回路図を図3に示します。

図 31-6200-005 と Arduino を SPI で接続するための回路図

センサーとの通信には、ArduinoのSPIライブラリを使用します。 SPI.begin()でSPIライブラリを初期化します(ただし、通信は開きません)。この回路はSPIデバイスが1つしかないので、10番ピン(SS)をLOWにして、そのピンで制御されるスレーブを有効にします。この状態はプログラム中ずっとLOWのままなので、この回路でスレーブを無効にする必要はありません。

void setup() {
    SPI.begin(); // initialize SPI
    digitalWrite(10, LOW); // enable slave 1
}

ライブラリを初期化したので、シグナルコンディショナーとの接続をオープンにする必要があります。これは、SPI.beginTransaction()関数を使用して行います。この関数は1つの引数、SPISettingsオブジェクトを取ります。このオブジェクトは、接続を作成するために必要なすべての情報を提供します。SPISettings オブジェクトには 3 つの引数があります。

  1. スレーブの最大クロック速度は、1-6200-005では20Mhzです。
  2. 2 番目の引数は、SPI インターフェイスが最上位ビットを使用するか最下位ビットを使用するかを決定します。1-6200-005 の場合、これは Most Significant Bit First ( またはMSBFIRST) です。
  3. 1-6200-005では、SPIモード2(CPOL=1, CPHA=0)が使用されます。
// オープンなSPI通信
SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2))。

SPI.transfer()関数はデータの送受信に使用されます。これは同時にコマンドを送信し、MISOピンから読み込んだものを返します。スレーブが応答するまでには常に1 クロックサイクルかかりますので、各コマンドの結果は次のサイクルまで受信できません。例えば、以下のコードでは、X 軸のローバイト要求を送信する関数は、この遅延のために X 軸のハイバイト値を返します。

0x39 コマンドは、良好な測定値を得るために不可欠であることに注意してください。このコマンドは、ボードに傾きの新しい測定値を取得するように指示します。以下のコードでは、最初に一度だけ送信され、if文の最後にもう一度送信され、低温ビットを受信しています。

    SPI.transfer(0x39); // update sensor data
    delay(1); // wait for SPI response
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1); // wait for SPI response

    if (res == 0x2A) { // verify sensor data updated successfully
        high = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (high << 8) | low; // merge low and high bytes into int

        delay(1); // wait for SPI response
        high = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (high << 8) | low; // merge low and high bytes into int

        delay(1); // wait for SPI response
        high = SPI.transfer(0x36); // get high temp byte, request low temp byte
        delay(1); // wait for SPI response
        low = SPI.transfer(0x39); // get low temperature byte, update sensor data
        temperature = (high << 8) | low; // merge low and high bytes into int
    }

    SPI.endTransaction(); // close the SPI communication

Note that the responses will be in separate high and low bytes. The code above converts these to 16-bit integers using the expression (high << 8) | low.

SPIバス

1-6200-005シグナルコンディショナをSPIバスで接続することも可能です。SPI バスでは、すべての SPI デバイスが CLK、MISO、MOSI 接続を共有することができます。ただし、各スレーブは独自のSS接続を取得し、マスターはどのスレーブと通信するかを選択できます。一度に使用できるSPIデバイスの数は、独立したSS接続の数によって制限されます。図 4 は、ピン D9 と D10 を SS 信号として使用する SPI バス上の 2 つのセンサの回路図を示しています。

図 41-6200-005 を 2 つの 1-6200-005 と Arduino を SPI バスで接続するための回路図。各デバイスの /SS 接続が別々になっていることに注意してください。

このコードは単一のSPIデバイスのコードと非常に似ていますが、どのスレーブと通信するかを制御するためにSSピンが変更されていることに注意してください。

// open SPI communication

    SPI.beginTransaction(SPISettings(20000000, MSBFIRST, SPI_MODE2));
    digitalWrite(10, LOW); // enable the slave controlled by D10

    SPI.transfer(0x39); // request status
    delay(1);
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1);

    if (res == 0x2A) {
        hi = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1);
        lo = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1);
        lo = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x36); // get high temperature byte, request low temperature byte
        delay(1);
        lo = SPI.transfer(0x39); // get low temperature byte
        temperature = (hi << 8) | lo;
    }

    digitalWrite(10, HIGH); // disable the slave controlled by D10
    digitalWrite(9, LOW); // enable the slave controlled by D9

    SPI.transfer(0x39); // request status
    delay(1);
    res = SPI.transfer(0x31); // get status, request high x byte
    delay(1);

    if (res == 0x2A) {
        hi = SPI.transfer(0x32); // get high x byte, request low x byte
        delay(1);
        lo = SPI.transfer(0x33); // get low x byte, request high y byte
        x = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x34); // get high y byte, request low y byte
        delay(1);
        lo = SPI.transfer(0x35); // get low y byte, request high temperature byte
        y = (hi << 8) | lo;

        delay(1);
        hi = SPI.transfer(0x36); // get high temperature byte, request low temperature byte
        delay(1);
        lo = SPI.transfer(0x39); // get low temperature byte
        temperature = (hi << 8) | lo;
    }

    digitalWrite(9, HIGH); // disable the slave controlled by D9
    SPI.endTransaction(); // close the SPI communication

2 つの SPI スレーブを同時に有効にしてメッセージを送信すると、信号が干渉してレスポンスが正しく読み込まれないことに注意してください。

RS-232

RS-232(TIA-232)は、一般的なシリアル通信プロトコルです。1-6200-0061-6200-012 には、3 線式の RS-232 があります。RS-232 の接続は、グランドを一緒に接続し、各 Rx を他の装置の Tx に接続することで構成されています。

このアプリケーションでは、ArduinoのSoftwareSerialライブラリを使用して、使用する仮想シリアルポートを作成します。このライブラリを使うことで、センサーとの通信に必要なポートの信号を反転させることができます。また、ハードウェアのシリアルポートを他の用途に利用できるようにしておきます。RS-232 用の回路を作成するには、D10(仮想 RX ピン)を OUT に、D11(仮想 TX)を IN に接続します。これは図 5 に示されています。

図 5 1-6200-006 と Arduino を RS-232 と SoftwareSerial ライブラリで接続するための回路図

SoftwareSerialを使用して、以下のコードで仮想シリアルポートを初期化することができます。

SoftwareSerial Sensor(10, 11, true); //RX, TX, inverse
void setup() {
    Sensor.begin(9600); //RX, TX, invert
}

UART TTLシリアルポート(Arduinoのような)を持つデバイスは、反転シリアル接続が必要で、そうしないと通信できないことに注意してください。Arduinoでは、仮想シリアルポートを作成する際に、第3引数でこれを行います(反転信号の場合は"true")。

RS-232 経由で傾きを読み取るには、まず、欲しいデータのコマンドを送信し、ポートからデータを読み込みます。X軸、Y軸、温度値を読み取るコードは以下の通りです。

Sensor.print('x'); // send command for x axis tilt
delay(50); // delay to give time for response
b = 0;
while (Sensor.available() != 0 && b < 8) {
    x[b++] = Sensor.read(); // read received bytes into char array
}

Sensor.print('y'); // send command for y axis tilt
delay(50);
b = 0;
while (Sensor.available() != 0 && b < 8) {
    y[b++] = Sensor.read();
}

Sensor.print('t'); // send command for temperature
delay(50);
b = 0;
while (Sensor.available() != 0 && b < 8) {
    temperature[b++] = Sensor.read();
}

すべてのRS-232コマンドの定義は,シグナルコンディショナのデータシートに記載されています。

このコードからのレスポンスは、改行文字とキャリッジリターン文字 (0x0a, 0x0d) で終わる 8 バイトの文字配列になります。これは文字列ではないので、ほとんどの場合文字列に変換する必要があります。必要であれば、int に変換することもできます。

// char配列を文字列に変換
    x[b - 2] = '\0'.

   // 文字列を16ビットのintに変換します.
    xInt = atoi(x)。

上のコードは、改行文字をヌル文字に置き換え、最後の文字の直後に文字列を終了させています。これはb変数を使用する必要があるので、測定を受信した直後に行う必要があるでしょう。b変数を使用せずにこれを実現するには、終了文字を配列の最後に配置することもできますが、これは末尾にスペースと文字を残すことになります。

RS-485

RS-485(TIA-485)は、長距離や電気的にノイズの多い環境でも動作するシリアル通信規格です。1-6200-008シグナルコンディショナーで利用できます。Arduino Unoは単体ではRS-485をサポートしていませんが、コンバータを使用することで、当社のRS-485製品との通信を容易にすることができます。

ほとんどの RS-485 コンバータでは、DI (Data In) と RO (Receive Out) がそれぞれ Rx と Tx となります。RE(受信イネーブル)とDE(データイネーブル)は、コンバータがRS-485データを送受信するタイミングを制御します。コンバータのAとBの接続は、シグナルコンディショナのAとBに接続されています。この回路の回路図を図6に示します。

図 61-6200-008 と Arduino を RS-485 で接続するための回路図。RS-485コンバータを仲介に使用

シグナルコンディショナとの通信に使用する RS-485 コマンドは以下の形式を使用します。

*xxyyy#

xx はコマンドの送信先アドレスです。デフォルトでは、1-6200-008では99になります。はコマンドの終了を示します。例えば、アドレス 99 の x 軸の傾きを読み取るコマンドは *9911# です。使用可能なコマンドはすべて、1-6200-008 データシートに記載されています。

RS-232 から RS-485 コンバータをインラインで使用すると、これらのコマンドは RS-232 を使用してコンバータに送信することができます。コンバータはRS-485のシグナルコンディショナにこれらのコマンドを送信します。セットアップ機能は RS-232 シグナルコンディショナと同じです。以下のコードは、この設定を使ってシグナルコンディショナからデータを読み出す方法を示しています。

// x axis tilt
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9911#"); // send x axis command
    digitalWrite(9, LOW); // enable reception
    delay(25); // wait for sensor to respond
    b = 0;
    while (Sensor.available()) {
        x[b++] = Sensor.read(); // store response in a char array
    }

    // y axis tilt
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9921#"); // send y axis command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        y[b++] = Sensor.read(); // store response in char array
    }

    // temperature
    digitalWrite(9, HIGH); // enable transmission
    Sensor.print("*9941#"); // send temperature command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        temperature[b++] = Sensor.read(); // store response
    }

RS-232 のように、応答は、改行とキャリッジリターンで終わる文字配列になります。もし配列を文字列として扱いたい場合は、ヌル文字('\0')を追加しなければなりません。

アドレス付きRS-485

1つのバスに最大 32 個の1-6200-008シグナルコンディショナを接続することができます。シグナルコンディショナにはアドレスを割り当てることができ、各センサが応答するかどうかを判断する方法を提供します。複数のセンサーを同じアドレスで接続すると、センサー同士の通信が干渉してしまいますので注意してください。

デフォルトでは、シグナルコンディショナーのアドレスは 99 になっています。変更するには、そのアドレスを持つ唯一の接続デバイスであることを確認してください。xx は現在のアドレス、zz は新しいアドレスです。例えば、以下のようになります。

Sensor.print("*9981A01#"); // アドレスを 99 から 01 に変更します

アドレスを変更すると、99で始まるコマンドを使用してセンサーにアクセスすることができなくなります。その代わりに、新しいアドレス01がすべてのコマンドで99 の代わりに使用されます。例えば、製品情報を読み取るコマンドは、上記のコマンドを実行すると*9980#から*0180#に変更されます。

各センサに固有のアドレスが割り当てられると、それらを回路に取り付けることができます。各シグナルコンディショナは、追加のコンポーネントや接続を必要とせず、同じバスに接続することができます。これを示す回路図を図7に示します。

図 71-6200-008 シグナルコンディショナ(4 台)を RS-485 で Arduino に接続するための回路図

複数のアドレスのRS-485センサから読み出すプログラムの例を以下に示します。このコードは、4 つのセンサ(アドレス 8~11)に接続された回路用に書かれています。

char addr[4][3] = {"08", "09", "10", "11"};
for (int i = 0; i < 4; i++) { // run this code for every address
    // x axis tilt
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s11#", addr[i]); // create x axis command
    Sensor.print(cmd); // send x axis command
    digitalWrite(9, LOW); // enable reception
    delay(25); // wait for sensor to respond
    b = 0;
    while (Sensor.available()) {
        x[b++] = Sensor.read(); // store response from sensor in a char array
    }

    // y axis tilt
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s21#", addr[i]); // create command
    Sensor.print(cmd); // send command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        y[b++] = Sensor.read(); // store response
    }

    // temperature
    digitalWrite(9, HIGH); // enable transmission
    sprintf(cmd, "*%2s41#", addr[i]); // create command
    Sensor.print(cmd); // send command
    digitalWrite(9, LOW); // enable reception
    delay(25);
    b = 0;
    while (Sensor.available()) {
        temperature[b++] = Sensor.read(); // store response
    }
}

応答は、16ビットの数値に対するASCII文字を含む8バイトの文字配列となります。