ジャンク箱にあった D/A コンバータ「8BIT 12CH D-A CONVERTER WITH BUFFER AMPLIFIERS」M62352AGP を使って、Arduino から正弦波を出力してみようと考えています。
前回「D/A コンバータを使って Arduino から正弦波を出力する (1)」で D/A コンバータに渡すデータのフォーマットを確認しましたので、今回は回路とスケッチを作ってみました。
Arduino と D/A コンバータの回路図
D/A コンバータにつなぐのは、DI 、CLK 、LD の 3 本です。
DI (17) は 12 ビットのシリアルデータで、Arduino の D11 ピンから出力します。
データは MSB ファーストで、最初の 4 ビットがアナログの出力チャンネルを、次の 8 ビットが出力するアナログの値を指定します。
CLK (16) はデータ転送の同期クロックで、Arduino の D13 ピンから出力します。
データビットは、クロックパルスの立ち上がりで読み込まれます。
LD (15) はデコーダのラッチパルスで、立ち上がりでレジスタから指定したチャンネルの D/A コンバータへデータが送られます。
Arduino の D10 ピンにつないであります。
基準電圧の VDD 、VSS はそれぞれ電源電圧の 5V と GND としました。
抵抗 R1 は出力抵抗です。出力できる電流は 1mA 程度なのかな。大きくないので注意です。
出力には 100pF 以下のコンデンサを入れるのが推奨されているのですが、部品箱に、ないです (^_^;)
shiftOut() を使ったスケッチ
シリアルデータを出力するってことなので、shiftOut() を使ってぱたぱたと作りました。
- // Sine wave oscillator 2020.12.15 by meyon230
- int diPin = 11;
- int clkPin = 13;
- int ldPin = 10;
- void setup() {
- pinMode(diPin, OUTPUT);
- pinMode(clkPin, OUTPUT);
- pinMode(ldPin, OUTPUT);
- }
- void loop() {
- int f = 50;
- unsigned long t = micros();
- byte AO = 0x08;
- float y = (sin(TWO_PI*f*t*0.000001)+1.0)*0.5;
- byte DI = y * 255;
- digitalWrite(ldPin, LOW);
- shiftOut(diPin, clkPin, MSBFIRST, AO);
- shiftOut(diPin, clkPin, MSBFIRST, DI);
- digitalWrite(ldPin, HIGH);
- }
14 行目で正弦波の周波数を指定しています。単位は Hz です。
16 行目はアナログの出力チャンネルです。今回は一つの出力でよいので、AO1 を指定しています。なお、shiftOut() では 1 バイトの出力になるので、頭に 0 が 4 ビットあります。
18 行目で正弦波を発生させています。sin() の出力は -1 ~ +1 なので、0 ~ +1 に変換。その後 0x00 ~ 0xFF のビット列にしています。
21 ~ 24 行目でシフトレジスタへデータを送っています。データは 1 バイトごとの出力になります。最初にアナログ出力チャンネルとして 8 ビット送りますが、次のアナログ出力データ 8 ビットを送ると、頭の 4 ビットはシフトレジスタから溢れることになります。
ブレッドボードのようす
毎度のブレッドボードです。
上は電源です。
下のブレッドボードに Arduino NANO と変換基板に載せた D/A コンバータ M62352AGP があります。
回路的には簡単なので、それだけです (^_^;)
出力波形
出力波形です。
図 1 は周波数 50Hz 時の波形です。
細かなギザギザはありますが、正弦波です。見た目だけですケド (^_^;)
図 2 は周波数を 100Hz にしたときの波形です。
ギザギザがかなり大きくなっていますが、ローパスフィルターを通せば使えるんじゃないでしょうか。
それなりの正弦波ということではこの辺が限界でしょうかねぇ。
図 3 は Arduino の D10 から出力しているラッチパルス LD のようすです。
パルスが LOW のときに shiftOut() でデータを転送しています。その時間が約 0.23ms あります。shiftOut() は処理が遅いと言われますが、たしかにかなりの時間を占めています。
HIGH のときは他の処理、まぁほとんどは sin() の計算にかかっている時間だと思います。約 0.16ms です。
これじゃあ周波数を上げられないのも、よ〜くわかりますね (^_^;)
次回は SPI 通信を使ってみます
さて、shiftOut() でのデータ転送にすいぶん時間がかかっているようです。この部分を速くするには “SPI ライブラリを使え” とリファレンスに書いてあります。
次回は、スケッチを書き換えて SPI 通信を使ってみようと思います。