アフィリエイト広告
アフィリエイト広告

D/A コンバータを使って Arduino から正弦波を出力する (2)

ジャンク箱にあった 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() を使ってぱたぱたと作りました。

  1. // Sine wave oscillator 2020.12.15 by meyon230
  2. int diPin = 11;
  3. int clkPin = 13;
  4. int ldPin = 10;
  5. void setup() {
  6.   pinMode(diPin, OUTPUT);
  7.   pinMode(clkPin, OUTPUT);
  8.   pinMode(ldPin, OUTPUT);
  9. }
  10. void loop() {
  11.   int f = 50;
  12.   unsigned long t = micros();
  13.   byte AO = 0x08;
  14.   float y = (sin(TWO_PI*f*t*0.000001)+1.0)*0.5;
  15.   byte DI = y * 255;
  16.   digitalWrite(ldPin, LOW);
  17.   shiftOut(diPin, clkPin, MSBFIRST, AO);
  18.   shiftOut(diPin, clkPin, MSBFIRST, DI);
  19.   digitalWrite(ldPin, HIGH);
  20. }

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

出力波形です。

図 1 は周波数 50Hz 時の波形です。
細かなギザギザはありますが、正弦波です。見た目だけですケド (^_^;)

図 2 出力波形 100Hz

図 2 は周波数を 100Hz にしたときの波形です。
ギザギザがかなり大きくなっていますが、ローパスフィルターを通せば使えるんじゃないでしょうか。

それなりの正弦波ということではこの辺が限界でしょうかねぇ。

図 3 ラッチパルス LD

図 3 は Arduino の D10 から出力しているラッチパルス LD のようすです。

パルスが LOW のときに shiftOut() でデータを転送しています。その時間が約 0.23ms あります。shiftOut() は処理が遅いと言われますが、たしかにかなりの時間を占めています。
HIGH のときは他の処理、まぁほとんどは sin() の計算にかかっている時間だと思います。約 0.16ms です。

これじゃあ周波数を上げられないのも、よ〜くわかりますね (^_^;)

次回は SPI 通信を使ってみます

さて、shiftOut() でのデータ転送にすいぶん時間がかかっているようです。この部分を速くするには “SPI ライブラリを使え” とリファレンスに書いてあります。
次回は、スケッチを書き換えて SPI 通信を使ってみようと思います。

タイトルとURLをコピーしました