« 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分(黒)しか接続していないので、赤線は入力なし。
TODO:
- OPアンプLMC6482を用いた反転増幅回路をバッファ(+単電源用バイアス)に使っているため、波形をソフト的にひっくり返す
- バッファ部分のドキュメンテーション
- 2チャンネル目のバッファを作る
- エッジトリガをつける
- アンチエイリアシング・フィルタを入れる
- FFT
Topics: FT232R, PIC24HJ12GP202, R, オシロスコープ |

