wiki:epics/streamdevice/ondotori

Version 1 (modified by michkawa, 10 years ago) (diff)

--

T&D TR-73U おんどとり用IOC

今回は、RS-232Cで取得したバイナリデータをStreamDeviceでwaveformとして取得し、sequencerでデータ変換するパターン。

通信マニュアル

  • 会社サポートに問い合わせて、パスワードを教えてもらってダウロード

接続

T&D TR-73Uからデータを取得するには、専用のRS-232Cケーブル(TR-07C)で接続する必要がある。そこから先はいつも通りのMOXAのEther-Serialコンバータで接続する。

baud rate 19200
parity none
data bits 8
stop bits 1
flow ctrl none

通信フォーマット

現在値のデータを取得するコマンドだけを実装する。

データはlittle endian

  • 測定値要求コマンド

送信

項目名 サイズ(byte) 説明
SOH 1 0x01固定
コマンド 1
コマンド予備 1
データ長 2 データの長さ
データ 4~
SUM 2 チェックSUM SOH~データまでの総和

受信

項目名 サイズ(byte) 説明
SOH 1 0x01固定
コマンド 1
応答コード 1 ACK(0x06),etc
データ長 2 データの長さ
データ 0~
SUM 2 チェックSUM SOH~データまでの総和

データフォーマットはマニュアル?を参照。

protocol file

今回のデータは固定長なので、Max_Inputでデータ長を設定。
ターミネーター、セパレーターは"なし"に設定。
プロトコルファイルは以下の様になる。

Terminator = "";
#
setWakeup {
    out 0x00;
}

getData {
    ExtraInput   = Ignore;
    InTerminator = "";
    ReplyTimeout = 3000;
    MaxInput     = 26;
    separator    = "";

    out 0x01 0x33 0x00 0x04 0x00 0x00 0x00 0x00 0x00 0x38 0x00;
    in  "%0r";

    @replytimeout{;}
}

%0rのところをwaveformとして取り込んで、sequenceで処理する。

sequence file

必要なデータをwaveformから切り出して、データ用のレコードに設定する。
データ取得用レコードをPROCしてからデータが出力されるまでにタイムラグがあるので、0.5秒待ちを入れる。
データの収集間隔は現在は5秒に設定。

program sncTR73U

unsigned char wfByte[26];
assign wfByte  to "{user}:getData";

int wfProc;
assign wfProc  to "{user}:getData.PROC";

float vals[3];
assign vals[0] to "{user}:getTemperature";
assign vals[1] to "{user}:getHumidity";
assign vals[2] to "{user}:getPressure";

int wkup;
assign wkup    to "{user}:wakeup";

int ack;
int i;
int hsbIndex;
int lsbIndex;
/*unsigned short chkSum;*/
unsigned int shtVal;
float calcVal;

ss sncTR73U {
    state init {
        when () {
        } state getData
    }

    state getData {
        when (delay(5)) {
            wkup = TRUE;
            pvPut(wkup, SYNC);

        } state setWakeup
    }

    state setWakeup {
        when (pvPutComplete(wkup)) {

            for(i=0 ; i<26 ; i++) {
                wfByte[i] = 0;
            }

            wfProc = 1;
            pvPut(wfProc);
        } state waitGetData
    }
    state waitGetData {
        when (delay(0.5)) {
            pvGet(wfByte);
            ack = wfByte[2];
        } state calcData

        when (delay(3)) {
            printf("Read Timeout\n");
        } state getData
    }

    state calcData {
        when (ack == 0x06) {
            for(i=0, hsbIndex=5, lsbIndex=6 ; i<3 ; i++, hsbIndex+=2, lsbIndex+=2) {
                shtVal = (wfByte[hsbIndex] | (wfByte[lsbIndex] << 8));

                calcVal = shtVal;
                if(i != 2) {
                    calcVal -= 1000;
                }
                vals[i] = calcVal / 10.0;
                printf("Calc Val: vals[%d]=%.1f\n", i, vals[i]);
                pvPut(vals[i]);
            }
        } state getData
        when (ack == 0x00) {
        } state getData
    }
}

db file

record(bo, "$(user):wakeup")
{
    field(DESC, "Set wakeup device")
    field(DTYP, "stream")
    field(OUT,  "@TR73U.proto setWakeup $(DEV)")
}

record(waveform, "$(user):getData")
{
    field(DESC, "Get data binary")
    field(DTYP, "stream")
    field(INP,  "@TR73U.proto getData $(DEV)")
    field(NELM, "26")
    field(FTVL, "UCHAR")
}

record(ai, "$(user):getTemperature")
{
    field(DESC, "Get temperature")
    field(EGU,  "degC")
    field(PREC, "1")
}

record(ai, "$(user):getHumidity")
{
    field(DESC, "Get humidity")
    field(EGU,  "percent")
    field(PREC, "1")
}

record(ai, "$(user):getPressure")
{
    field(DESC, "Get atmosphere pressure")
    field(EGU,  "hPa")
    field(PREC, "1")
}

Attachments (2)

Download all attachments as: .zip