「PIC AVR 工作室」サイトの日記的なブログです。
サイトに挙げなかった他愛ないことを日記的に書き残してます。
PIC AVR 工作室 ブログ



この間千石で買ってきたホールセンサIC「DN6851」を
arduinoに繋いでみました。

ホールセンサといえば、以前THS119を買ったまま死蔵
したままだったのですが、IC化されて使いやすくなって
いるDN6851ならもっと簡単に使えるだろうと
いうことで、DN6851を買ってきてみました。
約60円也。

ホールセンサは通常4本の足があって、2本は電源、
2本は差動出力です。
電源は定電流回路にするか定電圧回路にしないと
ならないし、出力電圧は微小かつ差動出力なので、
オペアンプを通して電圧差を増幅する必要が
ありました。扱いが面倒です。

一方DN6851のようにIC化されたホールセンサIC
は3本足。電源が2本で出力が1本。
アンプも内蔵されていて、出力段もトランジスタで
組まれているので、マイコンとの接続は一気に
簡単になります。

というわけで、まずは実際に繋いでみます。今回も
例によってreduino-nanoを使っています。


①はVCC
②はGND
③は出力

です。出力をそのままarduinoに繋げばOKとなって
います。

今回は、ホールICからの出力はアナログ0に繋いで
みました。アナログ0からの入力電圧をシリアルで
PC(arduino-IDEのシリアルモニタ)に表示
してみます。

手ごろな磁石が手元に無かったのですが、工具箱を
探したところ、秋月で買った2cmくらいのスピーカー
が出てきたので、これを磁石として使ってみました。

結果、ICから入力したアナログ値は、0Vと5Vの
どちらかの値を取ることが判りました。いわゆる
デジタル出力のICということになります。
扱いはとても簡単です。

なお、中間の値にはなりませんので、磁気の強さを
アナログ値として取り込むことは出来ません。

5V電源で使う場合、磁石が遠い時は0Vを、
磁石が近づくと5Vとなります。
N極、S極の極性を見ているようで、片側の極
しか検知しないようです。

使った磁石(というかスピーカーですが)の磁極は
どちらか判らないのですが、この辺りのことは
データシートに詳しく書かれています。

このICの動き方ですが、データシートのBlock Diagram
を読むと判ってきます。

まず、当然ホール素子が内蔵されているわけですが、
この素子の出力をアンプに通して増幅し、それを
シュミットトリガ回路を通すことでデジタル化、
さらにシュミットトリガの出力をトランジスタで
ドライブするという形になっています。

出力回路のインピーダンスは27kΩなので、
たくさんの電流を取り出すことは出来ませんが
マイコンの入力端子に繋ぐ分には特段の問題は
ないと思います。

内部にシュミットトリガ回路が組み込まれているので、
磁石を近づける時(0→1)と遠ざける時(1→0)
では出力信号が切り替わる距離(場所)が異なる点は
念頭においておく必要があるかもしれません。

近づく時はかなり近づいたところでようやく
ONになり、遠ざかる時はそれより少し離れたところ
でようやくOFFになります。

と言葉で書いても解り難いと思うので、あとで
サイト上にムービーを載せておきます。

(追伸:↓ムービーなどアップしました)
http://nekosan0.bake-neko.net/connection_hall.html

なお、出力回路がオープンコレクタになっている
DN6852というのも有りますが、出力が
オープンコレクタということ以外、内蔵回路は
全く一緒のようです。

いずれにしても、磁石が近くにあるかどうかを
デジタル的に判断するデバイスとして、凄く
使いやすいことは判りました。

個人的には、このICが各サーキット(ツクバやその他)
のスタートラインに埋め込まれている磁石を検知
することが出来るかが気になるところです。

これが検知できれば、マイコン野郎なら簡単に
ラップタイムの自動計測マシンを作れることに
なります。しかも、市販のラップタイマーより
高機能なものが簡単に作れてしまうことでしょう。


磁気についてははっきり言って全然詳しくないので、
データシートの読み方も良く解ってないし、
解ったとしても、各サーキットに埋め込まれている
磁気の強さも極性も明示されていないので、
現実的には実際に使ってみないと解らないという
ことになるのかと思います。

まぁ、サーキットで試してみるにしてもだいぶ先に
なるかとは思いますが。



コメント ( 0 )




なんとなく放って置くのはなんだか気持ち悪いので、
もう一度なにかいい方法がないかなぁとおもって
もう一回だけスケッチを読み直して見ました。

一つ、v-syncのトリガを上手くキャッチ出来るかも
知れない方法を思いつきました。
以下のような修正方法です。

(修正前)
 attachInterrupt(0, v_sync, RISING);
(修正後)
 attachInterrupt(0, v_sync, LOW);

こうすれば、一瞬の立下り信号を取りこぼしたと
しても、v-syncが発生している(=LOW)一定期間中
に一瞬でも拾えさえすれば、v-sync割り込みは
発生するはずです。

…やってみました。

思考実験だけで終らせてみようと思ったのですが、
ちょこっと回路組んでやってみました。

…だめでした。
こういう時の心境… _厂ト○ こんな感じ。

だめだ…。ソフトウェアシミュレーターくらいは
使えないと、こういう細かいことは検証できません。

LOWなら上手くいくんじゃないかと思ったんだけど、
これでも垂直同期期間の信号は拾えないみたい。

私の脳みそではこれ以上はどうすることも出来ないなぁ…


まぁ、こういうときはちゃんとロジアナとか持ち出して
信号を細かく見てみればいいんだろうけど、
ネコロジーの完成度は少し中途半端なままになって
いるのと、今回使ったシリアル版のarduinoも
ネコロジーも、共にシリアルi/f接続を使うという
ってことが引っかかっていて…

まぁ、どうしてもarduinoでやらないといけないという
必要も無いし、arduinoの場合は32個のレジスタの
push、popでどうせ処理時間がかかり、表示領域がかなり
狭くなっちゃうので、実用性という点ではTINY2313の
フルアセンブラにも劣ってしまいます。
(実用性って何?っていう突っ込みは無しです)

あまり脱線しつづけるのもなんなので、このお話は
ひとまず凍結することにします。
うーむ…。



コメント ( 0 )




引き続き、arduinoとLM1881でビデオのオーバレイ処理
の実験です。

自作したシリアル版のarduino(MEGA8登載機)でさらに
実験してみました。このボードなら、INT0、INT1の
両ピンは完全にフリーになっているので。

で、早速結果はというと…
c-syncはちゃんと検知できました。でもv-syncは
動作せず。

ラインカウンタはint型で定義しているので、
0クリアされずにずーーとカウントしつづけ、
16ビット数値がオーバーラップする時にちょっとだけ
画面に何か出ます。

実験的に、およそ1画面分のライン数で0クリアする
ようにしてみたら、こんな風な画面が出てきました。


垂直同期が取れないので、市松模様が上下にゆっくり流れて
しまっています(TへT)
なお、スケッチはこれ。
(不等号と&マークは全角に置き換えてます)

// arduino video overlay sketch
// with interrupt 0 (v sync)
// and interrupt 1 (c sync)
// output video signal on digital pin 4

#define video_out 4


volatile int line_no;

volatile boolean bitmap[12] = {LOW,HIGH,
HIGH,LOW,
LOW,HIGH,
HIGH,LOW,
LOW,HIGH,
HIGH,LOW,};


void v_sync()
{
digitalWrite(13, HIGH);
line_no = 0;
}


void c_sync()
{
int disp_line;
int i;
int n;


line_no ++;

if((line_no >= 40) && (line_no <= 135)){

disp_line = (line_no - 40) / 16; //line no now display

for (i=0;i<2;i++){
digitalWrite(video_out,bitmap[disp_line * 2 + i]); //display a bit
}
digitalWrite(video_out,LOW); //black
}

if (line_no == 262+10){
line_no = 0;
}

}



void setup()
{
Serial.begin(9600);
pinMode(video_out, OUTPUT); // set digital pin4 for output video signal
digitalWrite(video_out, LOW);

line_no = 0;
attachInterrupt(1, c_sync, RISING);
attachInterrupt(0, v_sync, RISING);
}

void loop()
{
Serial.println(line_no);
}


配列「bitmap」で定義したイメージがそのまま
画面に市松模様として表示されているのが
お判りいただけるかと思います。


LM1881を繋がずに単体で動作確認をすればv-sync
割り込みも機能してるし、INT1、INT0を差し替えて、
スケッチも逆に書き直してみましたが、やはり
v-syncだけは機能しません。
(つまり、ハードウェアの故障では無いということ)


少なくともc-syncは考えていたとおりに動くことは
判りました。なのでreduino-nanoでc-syncが動作
していなかったのは、やはりデジタル3ピンに繋がった
470Ωの抵抗のせいだろうと思います。

一方、v-syncが上手く機能しない理由はまだあまり
釈然としないのですが、なんとなく想像レベルでは
理由が思い浮かびます。

その理由は…

c-syncでの処理時間が長すぎるということが1点。
そして、割り込みからの復帰処理(arduino言語の
標準機能の内部処理)で、int0、int1どちらから
復帰する際にも両方のトリガーをクリアしてしまう
のでは、ということ。

AVRには32バイトのレジスタファイルが存在する
ので、高級言語の割り込み処理では、これら32個
のレジスタをドッカンとスタックに押し込んで
いるようです。(arduinoについてはまだ未確認ですが)

割り込み開始で32個一気にpush。割り込み終了時に
32個纏めてpopをすることになるわけですが、
これにかなりの時間を使ってしまうだろうという
のが1点。
さらに、高級言語なので元々処理速度が遅いという
のが2点目。

多分そこらへんの理由もあって、1回のc-sync割り込み
に要する時間は結構長いはず。

それは何に影響するのか?

特に垂直同期期間では、シンクロ信号に等価パルス
が入るので、走査線1本の時間は通常の半分しか
ありません。
そうなると、v-syncのトリガがc-sync処理中に発生
するという可能性が高まります。多分、実際c-sync
処理中にv-syncのトリガが引かれているかと
思われます。

その際、
  「v-sync割り込みが発生していたよ」
というトリガの履歴がc-sync割り込みからの復帰時にも
残されていれば、その後あらためてv-sync割り込みが
かかり、ラインカウンタがちゃんと0クリアされる
はずなんですが、c-sync割り込みからの復帰時に
v-sync割り込みがあったことの履歴も一緒にクリア
されてしまっているのではないか?と。

そこまでが想像です。
残念ながら、調べ方が思い浮かびません。

arduinoはシミュレーターが付いていないし、
オンボードデバッグするにしても、使えるのは
シリアル通信機能程度。シリアル通信機能は
あまり割り込み処理とはあまり相性良くないし、
ビデオ信号と比べて遅すぎて有効ではありません。

本当は、シミュレーター使ってc-sync割り込み1回
の処理時間(処理クロック数)を調べたい
のですが…

ひとまず、arduinoの処理速度や割り込み機能を
使う範囲では、このレベルが限界かなぁ…と。

どなたか頑張って、v-syncにきちんとシンクロさせる
ことに挑戦してみてください!


調査方法といえば、arduinoもWIN-AVRも
gccベースなので、上手いことWIN-AVRを
騙してシミュレーターを使えないかなぁと
考えてみたんですが、arduinoのファイル内に
使えそうなファイルは生成されていないみたい。

もう少し調べてみて、上手いことWIN-AVRで
シミュレーションできないか考えてみます。

さすがに組み込みマイコンでは、後付けで
コアダンプを引っ張り出すのは一筋縄で
行かないし、出来たとしても、デバッグ用の
情報をコンパイラが生成しておいてくれないと、
コアダンプも読み様がありませんしね。

本来は、MEGA168にはデバッグ用のワイヤーが
内蔵されているんですけど、arduinoでそれに
対応するくらいなら、最初からWIN-AVR
使いなさいよって話ですよねぇ…

せめてシミュレーター機能は欲しいなぁ…



コメント ( 0 )



   次ページ »