« MicroArray Challengeをかじってみる | Home | MicroArray Challenge ヒント2が出た »

PICとRでオシロスコープもどき

By kmgs | 11 月 24, 2008

RからUSB経由(FT232R)で書き込み/シリアル通信ができるようになったので、A/Dコンバータの値をひたすら読むだけのオシロスコープもどきを作成してみました。PICを使った電子工作のネタ的にはよくあるもので、後閑氏のサイトをはじめとして、いろいろなところで作成例が紹介されています。私の工作の新奇性は、単にインターフェースがRになっている点だけでしょう。
トリガも垂直・水平軸調整もなく、どうしようもないプロトタイプですが、出発点の記念としてソースを載せておきます。
まずはPIC側。いつものようにPIC24HJ12GP202を使っています。AD0とAD1を10bitモードで同時サンプリングし、それぞれ8ビット分のみ128ポイントのバッファに蓄積します。128ポイント読み終えたら、UARTでデータを送信します。

#include <p24HJ12GP202.h>
#define BUF_LEN 128


int main(void) {
	unsigned char tmp;
	unsigned int i;
	unsigned char buf0[BUF_LEN];
	unsigned char buf1[BUF_LEN];

	// RP7をU1RXに (データシート 103ページ、register 9-7)
	RPINR18bits.U1RXR = 7;

	// RP6をU1TXに (データシート 95ページ、table 9-3)
	RPOR3bits.RP6R = 3;

	TRISB = 0xffbf;
	U1BRG  = 11; // 19200 bps @ Fcy = 3.73MHz
	U1MODE = 0x8000;
	U1STA  = 0x0400;

	// A/D converter
	AD1PCFGL = 0x0000; // AN0-AN9の全部をアナログ入力に
	AD1CHS0 = 0x0001; // AN0: sample A0、AN1: sample B
	AD1CHS123 = 0x0000;
	AD1CON1 = 0x00e8; // internal clock, SIMSAM
	AD1CON2 = 0x0100;
	AD1CON3 = 0x0200; // table 21-38: sampling time min. 2Tad, clock min. 76ns
	AD1CON1bits.ADON = 1;

	_U1RXIF=0;
	while (1) {
		while (_U1RXIF == 0);  // 入力待ち
		tmp = U1RXREG;

		for (i = 0; i <BUF_LEN; i++) {
			IFS0bits.AD1IF = 0;
			AD1CON1bits.ASAM = 1;
			while (!IFS0bits.AD1IF);
			AD1CON1bits.ASAM = 0;

			buf0[i] = (ADC1BUF0 >> 2) & 0x00ff;
			buf1[i] = (ADC1BUF1 >> 2) & 0x00ff;
		}

		for (i = 0; i <BUF_LEN; i++) {
			while (U1STAbits.UTXBF); // 送信バッファーの空き待ち
			U1TXREG = buf0[i];
		}

		for (i = 0; i <BUF_LEN; i++) {
			while (U1STAbits.UTXBF); // 送信バッファーの空き待ち
			U1TXREG = buf1[i];
		}

		_U1RXIF=0;
	}
}

そしてR側。osci()関数がデータを読み込んでプロットするもので、ほかは以前のエントリからの流用です。

# デバイス初期化関数
init_COM <- function(port="COM1", baud=19200) {
	dyn.load("serial.dll")
	a <- .C("init_COM", port=c(charToRaw(port), raw(1)), baud=as.integer(baud), errno=as.integer(0))

	if (a$errno != 0) {
		stop(a$errno)
	}
}

# デバイスを閉じる
close_COM <- function() {
	if (is.loaded("close_COM")) {
		a <- .C("close_COM", ret=as.integer(0))
		if (a$ret != 0) {
			stop(a$ret)
		}
		dyn.unload("serial.dll")
	}
}

# データ受信
read_COM <- function(len) {
	a <- .C("read_COM", raw(len), as.integer(len), errno=as.integer(0))
	if (a$errno != 0) {
		stop(a$errno)
	}
	a[[1]]
}

# データ送信
write_COM <- function(buf) {
	b <- as.raw(buf)
	a <- .C("write_COM", b, len=as.integer(length(b)), errno=as.integer(0))
	if (a$errno != 0) {
		stop(a$errno)
	}
}

oci <- function() {
	mat <- matrix(0, 128, 2)
	while (1) {
		write_COM(as.raw(1))
		mat[,1] <- as.integer(read_COM(128))
		mat[,2] <- as.integer(read_COM(128))
		matplot(mat, ty="l", ylim=c(0, 255))
	}
}

実行。停止はESCキーです。

source("serial_dll.r")
init_COM(port="COM4", baud=19200)
ocsi()
close_COM()

WaveGeneで4kHzの正弦波を出力したものを観測した結果。PIC側は2ch同時に処理できるものの、回路が1ch分(黒)しか接続していないので、赤線は入力なし。
WaveGene、4KHz sine wave

WaveGene、4KHz sine wave



TODO:

Topics: FT232R, PIC24HJ12GP202, R, オシロスコープ |

Comments

*
画像に書かれた文字を入力してください

スパム対策用画像
ログインすると画像認証なしで投稿できます

ホットワード オシロスコープ padding margin 統計 処理
割引クーポンまとめ情報 - クー割