デジタルアナログ出力モジュールMCP4725を使いました。
マイコンからI2C経由で命令を送ることで、アナログ信号を出力することができます。
DACモジュールの使い方とDACボードの比較、マイコンから出力できるDACとの性能比較をします。
DACモジュール(MCP4725)
簡単紹介
電源電圧までの任意のアナログ電圧を出力する。
MCP4725基板を2枚使いました。
当ページではそれぞれを以下の紹介の呼称にします。
◆MCP4725-Red

◆MCP4725-Blue

MCP4725(MCP4725A0)ではI2Cアドレスを60(h)または61(h)のどちらかを選択できます。
この2枚の基板はI2Cアドレスの設定の方法が違います。
それぞれの設定方法についてはこちら。
◆関連記事
ピン配置
◆MCP4725-Red

◆MCP4725-Blue

外観
◆MCP4725-Red

◆MCP4725-Blue

使ってみた
◆開発環境
Arduino環境で開発しました。
制御するマイコンボードはRaspberry Pi Picoを使用しました。
ボードライブラリにはAdafruitの「Adafruit MCP4725 by Adafruit」を使用しました。
簡単な命令セットで扱いやすいです。
◆アナログ出力とPWM出力
DACによるアナログ出力とPWM出力の違いで、LEDの光り方の変化を見ました。
アナログ出力はLEDのVFになるまで発光せず、電圧が上昇してからゆっくり点灯ゆっくり消灯しました。
PWMはDutyの低いうちからゆっくり点灯します。
LEDの輝度調整はPWMの方が制御が簡単ですが、遅い周期のPWMは点滅のちらつきが気になることがあります。
◆アナログ出力
出力できる電圧範囲は0Vから電源電圧までです。
電源電圧を最小の2.7Vと最大の5.5Vまで入力し、三角波を出力しました。
出力電圧はオシロスコープ(HDS272)で読み取ります。
オシロスコープの1ch(黄)の三角波はDAC出力を読み取った波形です。
2ch(青)はDACモジュールの電源電圧です。
最大値は電源電圧まで変化しています。

こちらはサンプルスケッチにあった正弦波を出力した結果です。
綺麗な波形を読み取ることができました。

◆I2C通信
モジュールはI2Cで接続します。
通信を使うことで設定速度への影響を調査しました。
ベンチマークにADCを内蔵しているXIAO SAMD21の設定速度と比較しました。
約60倍XIAO SAMD21の方が早い結果でした。
MCP4725 | XIAO SAMD21 | |
---|---|---|
1秒間に実行できるADC設定(回) | 7,299 | 469,266 |
まとめ
簡単にアナログ波形の出力ができました。
今回2種類のボードを試しましたが、精度や分解能に差異はありません。
I2Cアドレスの設定方法が異なり、半田作業で固定して使うかピン配置で変更するの違いです。
気になる点としては通信(I2C)を使うため繰り返しの設定が遅く、DACをマイコンに搭載しているSAMD21やESP32-WROOMと比べると頻繁なアナログ出力の変更には不利です。
準備
◆開発環境
Arduino環境でRaspberryPi Picoを使用します。
Arduino環境の準備はこちらの記事で紹介しています。
◆ボードライブラリ
Raspberry Pi Picoを使用します。
Arduino IDEのボードマネージャからRP2040用のライブラリのインストールとボードの選択をします。
ボードライブラリには「Raspberry Pi Pico/RP2040 by Earle F. Philhower, III」を使用します。
Generic RP2040またはRaspberry Pi Picoを使用します。
追加のボードマネージャのURL | https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json |
検索 | RP2040 |
ボードライブラリ | Raspberry Pi RP2040 Boards(x.x.x)※ |
選択するボード | Raspberry Pi RP2040 Boards(x.x.x) > Raspberry Pi Pico |
◆モジュールライブラリ
モジュールライブラリには「Adafruit MCP4725 by Adafruit」を使用します。
ライブラリ名 | 検索 | 動作確認時バージョン |
---|---|---|
Adafruit MCP4725 by Adafruit | mcp4725 | 2.0.2 |
準備
◆I2Cアドレスの変更(MCP4725-Red)
I2Cアドレスは60(h)または61(h)を選択できます。
アドレスは基板上の「ADDR」のパターンショートすることで変更できます。
デフォルトは画像左側の60(h)で、パターンは左と中央がショートした状態です。

◆I2Cアドレスの変更(MCP4725-Blue)
I2Cアドレスは60(h)または61(h)を選択できます。
アドレスは基板上のA0が未接続で60(h)、電源をショートさせると61(h)に変更できます。
スケッチサンプル
三角波アナログ出力
説明
三角波を出力します。
最大出力電圧は3.3Vを入力し、MCP4725の分解能12bit(4095)分を1bitずつ加算し、最大値になったら1bitずつ減算します。
出力した波形はオシロスコープで読み取ります。
配線
配線はDACモジュールに3.3Vを印加しています。
DACの出力設定では3.3Vまで出力します。
DACから5Vを出力する場合は、DACモジュールのVCCの電源供給元にVBUSまたはVSYSを接続します。

スケッチ
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define MCP4725_SDA (0)
#define MCP4725_SCL (1)
Adafruit_MCP4725 dac;
void setup(void)
{
Wire.setSDA(MCP4725_SDA);
Wire.setSCL(MCP4725_SCL);
Wire.begin();
dac.begin(0x60);
while(1)
{
for (int16_t i = 0; i < 4095; i ++)
{
dac.setVoltage(i, false);
}
for (int16_t i = 0; i < 4095; i ++)
{
dac.setVoltage((4095 - i), false);
}
}
}
void loop(void)
{
}
結果
VCCに3.3Vを印加した場合と、5.0Vを印加した場合の結果です。
電源電圧により扱いたい電圧のレンジを設定できました。
どちらもリニアに変化しています。

三角波アナログ出力
説明
ADCの設定速度を測ります。
ベンチマークとしてADC機能のあるXIAO SAMD21を使います。
XIAO SAMD21を2つ使い、1つはMCP4725, 1つはDACを制御します。
それぞれ0 ~ 3.3V、3.3V ~ 0Vに設定するスケッチを書き込みます。
それぞれのアナログ出力をオシロスコープ(HDS272)でモニタし、設定速度を計測します。
XIAO SAMD21のADCは10bit(0 ~ 1023), MCP4725のADCは12bit(0 ~ 4095)です。
3.3Vまでの設定回数を同じにするため、MCP4725は0 ~ 1023までのインクリメントに4倍して設定しています。
メモ:直接ADCを使えるマイコンにはEspressifのESP32-WROOMもあります。
ESP32-WROOMのADCは8bit(0 ~ 255)分解能で、2ch使えます。
配線

スケッチ
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define MCP4725_SDA (D0)
#define MCP4725_SCL (D1)
Adafruit_MCP4725 dac;
void setup(void)
{
dac.begin(0x60);
}
void loop(void)
{
while(1)
{
for (int16_t i = 0; i < 1024; i ++)
{
dac.setVoltage(i << 2, false);
}
for (int16_t i = 0; i < 1024; i ++)
{
dac.setVoltage((4092 - (i << 2)), false);
}
}
}
#define DAC_PIN (0)
void setup()
{
}
void loop()
{
while(1)
{
for(int i = 0; i < 1024; i ++)
{
analogWrite(DAC_PIN, i);
}
for(int i = 0; i < 1024; i ++)
{
analogWrite(DAC_PIN, 1023 - i);
}
}
}
結果
XIAO SAMD21のADCとMCP4725のADCの設定速度を比べました。
三角波の波形は2046回の設定で1周期です。
MCP4725 | XIAO SAMD21 | |
---|---|---|
三角波1周期の時間(ms) | 280 | 4.36 |
1回のADC実行時間(us)※1 | 137 | 2.13 |
1秒間に実行できるADC設定(回) | 7,299 | 469,266 |
※1 : 三角波1周期の時間 ÷ 2046
応答速度はXIAO SAMD21 ADCが圧倒的に速い結果でした。
分解能が細かいMCP4725には設定値を4倍に計算する含まれていますが、結果に影響はないものと考えています。
MCP4725-RedとMCP4725-Blue
説明
MCP4725-RedとMCP4725-Blueのアナログ出力を比べます。
どちらも同じ値を設定し同じ変化をさせます。
オシロスコープで出力電圧をモニタし重ねて表示します。
MCP4725-BlueはI2Cアドレスを61(h)にするためにA0端子に3.3Vを印加しています。
配線

スケッチ
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define MCP4725_SDA (0)
#define MCP4725_SCL (1)
Adafruit_MCP4725 dac_r;
Adafruit_MCP4725 dac_b;
void setup(void)
{
Wire.setSDA(MCP4725_SDA);
Wire.setSCL(MCP4725_SCL);
Wire.begin();
dac_r.begin(0x60);
dac_b.begin(0x61);
while(1)
{
for (int16_t i = 0; i < 4095; i ++)
{
dac_r.setVoltage(i, false);
dac_b.setVoltage(i, false);
}
for (int16_t i = 0; i < 4095; i ++)
{
dac_r.setVoltage((4095 - i), false);
dac_b.setVoltage((4095 - i), false);
}
}
}
void loop(void)
{
}
結果
黄がMCP4725-Red、青がMPC4725-Blueのアナログ出力波形です。
完全に重なっているため青がほとんど見えません。
性能差は無いようです。

アナログ出力とPWM出力
説明
ADCの出力とPWMの出力でLEDの点灯の違いを確認します。
ADCは0 ~ 3.3Vまでを直線的に変化させます。
PWMもDuty 0 ~ 100%を直線的に変化させます。
ADCは分解能12bit(0 ~ 4095)の変化をする繰り返し文により設定しています。
PWMは同じ繰り返し文を使用しますが、分解能8bit(0 ~ 255)で回数が合わないため、4bit右シフトによりスケール調整してます。
配線

スケッチ
#include <Wire.h>
#include <Adafruit_MCP4725.h>
#define PWM_PIN (15)
#define MCP4725_SDA (0)
#define MCP4725_SCL (1)
Adafruit_MCP4725 dac;
void setup(void)
{
Wire.setSDA(MCP4725_SDA);
Wire.setSCL(MCP4725_SCL);
Wire.begin();
dac.begin(0x60);
while(1)
{
for (int16_t i = 0; i < 4095; i ++)
{
dac.setVoltage(i, false);
analogWrite(PWM_PIN, (i >> 4));
}
for (int16_t i = 0; i < 4095; i ++)
{
dac.setVoltage((4095 - i), false);
analogWrite(PWM_PIN, ((4095 - i) >> 4));
}
}
}
void loop(void)
{
}
結果
黄がADCによるアナログ電圧、青がPWM制御です。
LEDがゆっくり点灯ゆっくり消灯しました。
黄の消灯時間が長いのは、LEDのVF未達時間があり発光できないため。
青は通電中は3.3Vで通電時間の長短でなのでなめらかな輝度変化に見えます。
オシロスコープは黄LEDは黄波形、青LEDは青波形です。
黄は電圧が直線的に変化しています。
青はPWMによりLow時間とHigh時間の変化を示したかったのですが、波形がつぶれてしまいました。
コメント