Arduino UNOにはアナログ出力がないので、デジタル出力をアナログに変換する。
外部にDAコンバータを用意する方法もあるが、簡易にはデジタル出力を利用して抵抗でDA変換をしてみる。
この辺は以下のサイトが詳しい。
http://mitt.la.coocan.jp/pic/pic7_16.html
8ビットのDA変換をするために、D2〜D9を使って図のような回路を組んだ。
予めSinの計算をして、配列に格納しておいたデータを使ったが、周期は13ms(約77Hz)となった。その都度Sinの計算をしたときには67ms(約15Hz)であった。
スケッチの一部を書くと、
予め計算していたSinData[kakudo]の8bitデータ(0x0000〜0x00ff)を、1ビットずつデジタル出力にHIGH,またはLOWで書き出す方法である。
スケッチを工夫して速度を上げる
デジタル出力にパラレルに出力できたらいいのに、と思っていたら、ちゃんとあった。
上と同じ内容を次のように変更。
PORTDはデジタル出力の0から7だが、0と1はシリアル通信に使われているので、2bitシフトして使っている。その分PORTBで2ビットを出力している。
このプログラムでSin波を出力させると、Sin波形の途中に異なった値のデータが、ヒゲのように出てしまう。原因はPORTDとPORTBの出力に時間差があるためで、アナログ値がその間本来と異なった値となってしまったため。
途中にヒゲが出ている |
PORTDとPORTBの出力の時間差が原因であることを確認するために、②を挿入してみた。
②がないと、ヒゲはほとんどなく、②を入れると、その時間だけ異なったデータが出る。
ヒゲがなくきれいな波形となる |
5度おきに計算。階段状になる。 |
外部のDAコンバータ、MCP4726(12bit)を使用した場合
インターフェースはI2Cで、速さが100kHz、400kHz、3.4MHzと3段階あるようだが、その設定の仕方がよくわからない。しかし実際にSCL波形をオシロスコープで見ると、10μs周期なので、100kHzでの通信と考えられる。
予めSinθの計算をしたうえで出力させたが、12ビットで転送時間もかかるのか、出力の周期は115ms(約8.7Hz)となり、とても遅い。(単純計算では1度あたり320μsかかったことになる。通信量からするとこんなものか。)ただ、波形としてはヒゲもなく大変きれいである。0.5度ごとに計算して出力させるともっときれいになるだろう。
12ビットのDACなので、1度につき2バイト使って360度計算すると、RAMの54%を使ってしまった。
![]() |
波形はヒゲもなくきれい。しかし遅い。 |
I2Cは100kHzに対し、SPIは数十Mbpsも可能というので、次のような回路を組んでみた。
シフトレジスタは別基板に作った |
このICは秋月電商で販売している7セグメントLED用に使われているもので、SPI.transfer()のコマンドでデータを転送する。
スピードアップのため、予めSinθを計算させておいてSinData[]に保存、その後順に出力する。
この結果、Sin波形の周期は約4.5ms(222Hz)となった。ラッチの周期は12μsだが、8ビットのデータ転送自体は2μsで終了している。digitalWriteの時間が結構かかっているようだ。
そこで、digitalWriteの代わりにPORTBコマンドを使ってみたのが以下のプログラムである。
ラッチにD10を使用しているので、直接制御している。
この結果、Sin波の周期は1.1msと、Arduinoのデジタル出力に直接抵抗をつけた場合(PORTコマンド使用)とほとんど変わらなくなった。ラッチの周期は3μsである。波形としては当然ヒゲもなくきれいなSin波になっている。
信号のタイミングを見ると、上がラッチ出力で、下がシリアルデータである。ラッチをLにした後、シリアルデータを出力。8ビットのデータを約2μsで送出し、その後ラッチをHにすることで、シフトレジスタの出力が変化する。
0 件のコメント:
コメントを投稿