実践Linux                 TOPへ  Cプログラミング目次へ

計測プログラミング  2011年7月

@秋月電子のデーターロガー(pico ADC-16)とUSB-シリアル変換器を使用したPC計測
Aトランジスタ技術増刊「今すぐ使えるパソコン計測USBマイコン基板」に付属のTRZ1102モジュールを使用したPC計測 →こちらへ


秋月電子のデーターロガー(pico ADC-16)とUSB-シリアル変換器を使用した計測プログラム

ここではシリアル接続用のpico ADC-16をUSB-シリアル変換器でUSB接続して使用してみる。

USB-シリアル変換ケーブル
秋月電子通商のUSB-シリアル変換モジュールK-01798を使用。
USB-RS232C変換チップはprolific社PL2303。
LinuxではたくさんのUSBシリアル変換ケーブルがサポートされているが、PL2303というチップを使ったものが一般的なようだ。

モジュールを接続すると、/dev/ttyUSB0が生成される。(システム→管理→ハードウェア(下方)→USB(下方)→PL2303 Serial Port→USB Vendor Specific Interface→PL2303 Serial Port→詳細 /dev/ttyUSB0)
このデバイスにはroot:uucpにrwの権限が与えられている。
# dmesg | grep tty  確認。
# stty -F /dev/ttyUSB0 -a でデバイスの設定がわかる。

# lsusb  USBデバイスの情報を確認する。
Bus 002 Device 002: ID 067b:2303 Prolific Technology. Inc. PL2303 Serial Port 等と表示される。
lsusbは/proc/bus/usb/devicesから情報を読み込んでいる。# cat /proc/bus/usb/devices
lsusb -vは、詳細表示。
lsusb -tは、USB階層をツリー形式で表示する。

pico ADC-16について
9600ボー、1ストップビット、パリティ無しの固定プロトコル。
入力範囲=±2500mvまで。

@スイッチを入れる
RTSを有効、DTRを無効にする。
立ち上がりまで1秒ぐらい待つ。

A計測要求
1バイトの制御データを送る。1チャンネル使用、分解能16ビットの場合、1Fを送る。
返信があるまで待ち時間を入れる=分解能16ビットの場合、0.7秒程度。

B返信
3バイトのデータが返される。1バイト=符号、2バイト=上位8ビット、3バイト=下位8ビット。

AとBを繰り返す。

picoのスイッチを入れる(ioctlを使う)
ioperm(=直接IOポートにアクセスする)を使う方法は?
PCにCOM1、COM2等とシリアル・ポートが標準装備されていたころはこれが使えた。
書式 ioperm(範囲の先頭のポート,範囲内のポート数,1は許可0は禁止);
例えば、picoをCOM2に接続してスイッチを入れる場合は、COM2のポートを許可しておいて、outb()でベースアドレス+4に2を送っていた。
COM1からCOM4のベ先頭アドレスは、それぞれ3F8、2F8、3E8、2E8となる(固定)。
 #define BASEPORT 0x2f8
 if(ioperm(BASEPORT,8,1)){perror(“ioperm”); exit(1)}
  outb(2,BASEPORT+4);
 if(ioperm(BASEPORT,8,0)){perror(“ioperm”); exit(1)}

しかし、USB-シリアル変換モジュールを使うとIOアドレスが不明なので、iopermでpicoをONにできない。
通常は、使用IOアドレスは、# cat /proc/ioports でわかる。

そこで、iopermではなくioctlを使う。
 int portstatus;
 ioctl(fd, TIOCMGET, &portstatus); // get current port status
 portstatus &= ~TIOCM_DTR; // drop the DTR bit
 portstatus |= TIOCM_RTS; // rise the CTS bit
 ioctl(fd, TIOCMSET, &portstatus); // set current port status


●汎用Makefile
プログラムソースをtest.cで保存して、Makefileを以下の内容で準備し、makeを実行する。
字下げはTabキーで行うこと。
直接IOポートにアクセスするioperm,outb,inb等を使用する場合には、-O2(最適化オプション)をつけてコンパイルする。

INCLUDE = /usr/X11R6/include/X11
LIB = /usr/X11R6/lib
CC = gcc
CFLAGS = -lX11 -lpthread
TARGETS = test
OBJ = ${SRC:.c=.o}
SRC = test.c

$(TARGETS):${OBJ}
  ${CC} -I ${INCLUDE} -L ${LIB} ${CFLAGS} ${OBJ} -o ${TARGETS}

${OBJ}:${SRC}
  ${CC} ${SRC} -c -o ${OBJ}

clean:
  rm -f *.o $(TARGETS)


●簡単な計測プログラム
Ctrl+Cキーで計測中止。

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h> //ioperm,lseek,close,read,write,termios
#include <sys/io.h> //ioperm
#include <sys/types.h> //lseek,open
#include <sys/stat.h> //open
#include <fcntl.h> //open
#include <termios.h> //termios
#include <signal.h>
#include <sys/ioctl.h> //ioctl

//#define BASEPORT 0x2f8 //COM2のベースポート(ここでは使わない)

int FD;
struct termios oldtio, newtio;

int main()
{
ssize_t len;
char ch1=0x1f; //計測要求の信号(1チャンネル、分解能16ビット)
unsigned char c[3]; //3バイトデータの受け取り用。unsignedにしておかないと返ってきたデータをうまく読めない。
void sig_fnc();
int portstatus;
int val;

if((FD=open(“/dev/ttyUSB0”,O_RDWR))==-1){perror(“open”);exit(1);}
printf(“open device:%d\n”,FD);

tcgetattr(FD, &oldtio);

bzero(&newtio, sizeof(newtio));
newtio.c_iflag |= (IXON | IXOFF);
newtio.c_oflag = 0;
newtio.c_lflag = 0;
newtio.c_cflag |= (CS8 | CREAD | CLOCAL);
newtio.c_cc[VTIME] = 1;
newtio.c_cc[VMIN] = 0;

cfsetispeed(&newtio, B9600);
cfsetospeed(&newtio, B9600);
tcflush(FD, TCIOFLUSH); //FDに残っているデータがあればフラッシュしておく。
tcsetattr(FD, TCSANOW, &newtio); //新しい設定をセット。


/* if(ioperm(BASEPORT, 8, 1)){perror(“ioperm”);exit(1);} //ここでは使わない。
outb(2,BASEPORT+4);
printf (“port4 value: %d\n”,inw(BASEPORT+4));
if(ioperm(BASEPORT, 8, 0)){perror(“ioperm”);exit(1);}
*/

ioctl(FD, TIOCMGET, &portstatus);
portstatus &= ~TIOCM_DTR;
portstatus |= TIOCM_RTS;
ioctl(FD, TIOCMSET, &portstatus);

usleep(1500000); //データロガーが起動するのを待つ。

signal(SIGINT,sig_fnc); //ターミナルでの割り込み許可をON(Ctrl+Cで終了)。

while(1){
write(FD,&ch1,1); //データロガーに計測要求の信号を送る。
usleep(1000000); //データロガーからの返信が変換されるのを待つ。
if((len=read(FD,c,3))>0) //データロガーからの応答データ(3バイト)を読み込む。
{
val=(int)((c[1]*0x100+c[2])*2500/65536); //±2500mvとしてビット配分。
if(c[0]==’-’){val=-val;}
printf(“value=%d mv\n”,val);
}
tcflush(FD, TCIOFLUSH); //FDに残っているデータはフラッシュしておく。
}
tcsetattr(FD, TCSANOW, &oldtio); //ttyUSB0の設定を元に戻しておく。

close(FD);
printf(“close device and end\n”);
exit(0);
}

void sig_fnc() //割り込み時の所作。
{
tcsetattr(FD, TCSANOW, &oldtio);

close(FD);
printf(“close device and end\n”);
exit(0);
}


応用プログラム

以下のプログラムは、ADC-16を使って@手動と、A一定時間ごとに自動で電圧をサンプリングするというものです。

プログラムのダウンロード(pico.tar.gz)       GTK+で作成したプログラムはもっとスマートです。

使用方法

pico.tar.gz をダウンロードして、解凍して下さい。
ファイルの権限を調整して下さい。(実行権限、読み書き権限等)
プログラムがうまく作動しない場合は、ソースのフォントの部分をシステムに合わせて入れ替えて、make しなおしてみて下さい。
 #define FONT1 “-urw-nimbus sans l condensed-medium-i-condensed--16-0-0-0-p-0-iso10646-1”
 #define FONT2 “-urw-nimbus sans l condensed-medium-i-condensed--70-0-0-0-p-0-iso10646-1”
の部分。
フォントの入れ替え方
xlsfontsコマンドでシステムフォントを一覧。 # xlsfonts -fn "*-iso10646-1"
iso10646-1は、ユニコードを意味する。
********--0-0-0-0-p-0-iso10646-1とかの最初の0を12などに変更すると文字サイズが指定できる。
********--12-0-0-0-p-0-iso10646-1

pico_m が手動測定用で、F1キーを押すとサンプリングできます。F2キーは終了となります。
pico_a が自動測定用で、端末からプログラムを開始して、案内に従って何回サンプリングするか、何秒おきにサンプリングするか入力して下さい。F1またはF2キーで終了となります。
計測結果は双方ともdataファイルとして保存されます。

実際の使用例(様々なセンサーを取り付けてみる)


Windowsのexcelでマクロを使って測定することも可能です。
ダウンロードしたら、まずインストールのシートを参照してください。
ダウンロード




TOPへ  Cプログラミング目次へ