概述
DFRobot Gravity 12-Bit I2C DAC是一款I2C接口集成有EEPROM小巧易用的数模DA转换模块,能将数字量准确地转换成对应的直流电压信号(非PWM),满足各类小型创意项目或自动控制系统的需要。该模块兼容arduino、树莓派等各种3.3V或5V主控板,虽然这类主控板要实现模拟量输出可使用PWM模拟,但这种模拟的纹波很大,而且精度不高。如要得到稳定准确的直流电压信号,必须要用DAC。此外,DAC可用于一些有趣的应用,如用作为信号发生器产生正弦波、三角波甚至是任意波形。
本模块采用12位DAC芯片MCP4725,无需外部提供参考电压(供电电压VCC与参考电压一致),支持3.3~5V宽电压供电,板载I2C地址选择开关(两个I2C地址0x60或0x61可选),最大支持2个DA模块的级联。芯片内置EEPROM,可将需要输出的DAC值写入EEPROM中,断电保存,下次重新上电时模块立刻根据存储在EEPROM的DAC值输出相应的模拟电压信号。
特性
- 12-bit高精度数模转换
- 内置EEPROM,断电保存DAC数据
- Gravity I2C接口,即插即用,预留XH2.54 4P接口供扩展
- 宽电压输入,兼容3.3V/5V控制器
- 模块尺寸小巧,方便安装
应用场景
- 传感器校准
- 运动控制系统
- 函数信号发生器
技术规格
- 输入电压(VCC):3.3V~5.0V
- 输出电压:0~VCC
- 分辨率:12-bit
- 工作电流:< 0.2mA
- 通信接口:Gravity I2C (逻辑电平0-3.3V)
- 产品尺寸:27mm*22mm
- 重量:13.8g
接口说明
标号 | 名称 | 功能描述 |
---|---|---|
+ | VCC | 电源正极(3.3~5.0V) |
- | GND | 电源负极 |
C | SCL | I2C时钟线 |
D | SDA | I2C数据线 |
ADDR | I2C地址 | I2C地址选择开关,拨动选择I2C地址(0x60或0x61) |
VOUT | VOUT | DAC模拟电压输出(0~VCC) |
引脚说明
Arduino使用教程
准备
- 硬件
- Arduino UNO控制板(或类似控制板) x 1
- 12-Bit I2C DA数模转换模块 x 1
- Gravity 4P传感器连接线(或若干杜邦线) x 1
- 数字万用表(可选) x 1
- 软件
- Arduino IDE (1.0.x或1.8.x), 点击下载Arduino IDE
- Arduino MCP4725库,点击下载MCP4725库
连线图
校准与可调模拟电压输出
虽然DAC的电压输出精度受多种因素影响,使实际输出电压与用户所指定电压值产生误差,但MCP4725的DAC参考电压Vref与供电电压VCC相同,供电电压的不准(实际电压并非准确的5.000V或3.300V)往往使输出误差较大。这里提供一种简易的校准方法,消除由于参考电压不准造成的误差。若不进行校准,也可根据所使用的控制器电平将下方代码中的REF_VOLTAGE设为5000(如Arduino等5V控制器)或3300(如树莓派、FireBeetle等3.3V控制器)。
用户需要自备一块高精度(3位或以上)数字万用表来完成该校准,具体步骤如下:
- 将模块与Arduino按照上面的连线图相连,将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地修改下面代码中函数DAC.init()的第一个参数。
- 安装Arduino MCP4725库。如何安装库?
- 打开Arduino IDE,将下面的代码上传到Arduino UNO
- 使用万用表测量VOUT输出电压并将电压值写入REF_VOLTAGE。如:测得VOUT=4950mV,将“#define REF_VOLTAGE 5000”改为“#define REF_VOLTAGE 4950”。校准完成。
- 在变量OUTPUT_VOLTAGE输入不超过REF_VOLTAGE的指定电压值(单位:mV),即可输出误差较小的模拟输出电压。在使用下面的样例代码前,可先把校准数值写入REF_VOLTAGE,以获得更准确的输出电压。
/*
* file OutputVoltage.ino
*
* @ https://github.com/DFRobot/DFRobot_MCP4725
*
* connect MCP4725 I2C interface with your board (please reference board compatibility)
*
* Output a constant voltage value and print through the serial port.
*
* Copyright [DFRobot](https://www.dfrobot.com), 2016
* Copyright GNU Lesser General Public License
*
* version V1.0
* date 2018-1-15
*/
#include "DFRobot_MCP4725.h"
#include "Wire.h"
#define REF_VOLTAGE 5000
DFRobot_MCP4725 DAC;
uint16_t OUTPUT_VOLTAGE = 5000; // Input DAC output voltage (0~REF_VOLTAGE,unit: mV)
void setup(void) {
Serial.begin(115200);
/* MCP4725A0_address is 0x60 or 0x61
* MCP4725A0_IIC_Address0 -->0x60
* MCP4725A0_IIC_Address1 -->0x61
*/
DAC.init(MCP4725A0_IIC_Address0, REF_VOLTAGE);
}
void loop(void) {
Serial.print("DFRobot_MCP4725 output: ");
Serial.print(OUTPUT_VOLTAGE);
Serial.println(" mV");
DAC.outputVoltage(OUTPUT_VOLTAGE);
delay(500);
}
将DAC值存入EEPROM
- 将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地修改下面代码中函数DAC.init()的第一个参数。
- 打开Arduino IDE,将下面的代码上传到Arduino UNO,使用数字万用表测量VOUT输出电压。
- 用户可修改变量OUTPUT_VOLTAGE的值改变模拟电压的输出值。REF_VOLTAGE可采用在校准一节中所使用的值,若未进行校准,可根据所使用的控制器电平将其设为5000(如Arduino等5V控制器)或3300(如树莓派、FireBeetle等3.3V控制器)。
/*
* file OutputVoltageEEPROM.ino
*
* @ https://github.com/DFRobot/DFRobot_MCP4725
*
* connect MCP4725 I2C interface with your board (please reference board compatibility)
*
* Output a constant voltage value and write to the internal EEPROM.
*
* Copyright [DFRobot](https://www.dfrobot.com), 2016
* Copyright GNU Lesser General Public License
*
* version V1.0
* date 2018-1-15
*/
#include "DFRobot_MCP4725.h"
#include "Wire.h"
#define REF_VOLTAGE 5000
DFRobot_MCP4725 DAC;
uint16_t OUTPUT_VOLTAGE = 1000; // Input DAC output voltage (0~REF_VOLTAGE,unit: mV)
void setup(void) {
Serial.begin(115200);
/* MCP4725A0_address is 0x60 or 0x61
* MCP4725A0_IIC_Address0 -->0x60
* MCP4725A0_IIC_Address1 -->0x61
*/
DAC.init(MCP4725A0_IIC_Address0, REF_VOLTAGE);
}
void loop(void) {
Serial.print("DFRobot_MCP4725 write to EEPROM and output: ");
Serial.print(OUTPUT_VOLTAGE);
Serial.println(" mV");
DAC.outputVoltageEEPROM(OUTPUT_VOLTAGE);
delay(200);
}
结果
- 使用万用表可测得模块的VOUT产生1V电压信号。断开模块与Arduino的所有连接,利用模块上的焊盘,将VCC与GND分别与Arduino上的5V和GND相连,使模块重新上电,在VOUT上仍能测出1V电压。函数DAC.outputVoltageEEPROM()在输出一个指定的模拟电压信号的同时将该DAC值存储在EEPROM中,模块在重新上电的时候调用EEPROM中的DAC值,在VOUT恢复上次断电时的模拟输出电压。
正弦波模拟电压输出
- 将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地修改下面代码中函数DAC.init()的第一个参数。
- 打开Arduino IDE,将下面的代码上传到Arduino UNO,使用示波器观察VOUT输出电压波形。
- 用户可修改函数DAC.outputSin()中的参数改变输出正弦波的幅度,频率和直流偏置。
/*
* file OutputVoltage.ino
*
* @ https://github.com/DFRobot/DFRobot_MCP4725
*
* connect MCP4725 I2C interface with your board (please reference board compatibility)
*
* Output a constant voltage value and print through the serial port.
*
* Copyright [DFRobot](https://www.dfrobot.com), 2016
* Copyright GNU Lesser General Public License
*
* version V1.0
* date 2018-1-25
*/
#include "DFRobot_MCP4725.h"
#include "Wire.h"
#define REF_VOLTAGE 5000
DFRobot_MCP4725 DAC;
void setup(void) {
Serial.begin(115200);
/* MCP4725A0_address is 0x60 or 0x61
* MCP4725A0_IIC_Address0 -->0x60
* MCP4725A0_IIC_Address1 -->0x61
*/
DAC.init(MCP4725A0_IIC_Address0, REF_VOLTAGE);
}
void loop(void) {
/*Output a magnitude of 2500mv, the frequency of 10HZ, DC offset 2500mv sine wave*/
DAC.outputSin(2500,10,2500);
}
结果
- 可观察到一个幅值为2.5V(峰峰值约为5V),频率为10Hz,带有2.5V直流偏置的完整正弦波
void outputSin(uint16_t amp, uint16_t freq, uint16_t offset)
- 函数说明:产生一个Vo=Voffset+Vp*sin(2*pi*f*t)的正弦波信号。当Vo>REF_VOLTAGE时,取值REF_VOLTAGE;当Vo<0时,取值0。
- amp:单位(mV),设定正弦波幅度Vp。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE,取0时为直流信号。
- freq:单位(Hz),设定正弦波频率f。取值范围0~100,取值大于100时取100,取0时为直流信号。
- offset:单位(mV),设定正弦波直流偏置Voffset。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
三角波模拟电压输出
- 将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地修改下面代码中函数DAC.init()的第一个参数。
- 打开Arduino IDE,将下面的代码上传到Arduino UNO,使用示波器观察VOUT输出电压波形。
- 用户可修改函数DAC.outputTriangle()中的参数改变输出三角波的幅度,频率,直流偏置和占空比。
/*
* file OutputVoltage.ino
*
* @ https://github.com/DFRobot/DFRobot_MCP4725
*
* connect MCP4725 I2C interface with your board (please reference board compatibility)
*
* Output a constant voltage value and print through the serial port.
*
* Copyright [DFRobot](https://www.dfrobot.com), 2016
* Copyright GNU Lesser General Public License
*
* version V1.0
* date 2018-1-25
*/
#include "DFRobot_MCP4725.h"
#include "Wire.h"
#define REF_VOLTAGE 5000
DFRobot_MCP4725 DAC;
void setup(void) {
Serial.begin(115200);
/* MCP4725A0_address is 0x60 or 0x61
* MCP4725A0_IIC_Address0 -->0x60
* MCP4725A0_IIC_Address1 -->0x61
*/
DAC.init(MCP4725A0_IIC_Address0, REF_VOLTAGE);
}
void loop(void) {
/*Output amplitude 5000mv, frequency 10HZ,
*the rise of the entire cycle accounted for 50% of the DC offset 0mv triangular wave.
*/
DAC.outputTriangle(5000,10,0,50);
}
结果
- 可观察到一个幅值为5V(峰峰值约为5V),频率为10Hz,无直流偏置,占空比为50%的完整三角波
void outputTriangle(uint16_t amp, uint16_t freq, uint16_t offset, uint8_t dutyCycle)
- 函数说明:产生一个三角(锯齿)波信号Vo。当Vo>REF_VOLTAGE时,取值REF_VOLTAGE;当Vo<0时,取值0。
- amp:单位(mV),设定三角(锯齿)波幅度。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
- freq:单位(Hz),设定三角(锯齿)波频率。取值范围0~100。取值大于100时取100,取0时输出恒定0V。
- offset:单位(mV),设定三角(锯齿)波直流偏置。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
- dutyCycle:单位(%),设定三角(锯齿)波占空比。取值范围0~100,取值大于100时取100,取0或100时成为锯齿波。
- 在上述基础上其它参数不变,仅将占空比改为0,即“DAC.outputTriangle(5000,10,0,0)”可产生一个幅度为5V频率为10Hz的锯齿波
树莓派教程
本教程将演示如何在树莓派主控板上使用这款DA模块输出准确直流电压信号,EEPROM的使用和产生正弦波与三角波。
准备
- 硬件
- 树莓派3代B型(或类似)主控板 x 1
- 12-Bit I2C DA数模转换模块 x 1
- Gravity 4P传感器连接线(或若干杜邦线) x 1
- 数字万用表(可选) x 1
接线图
安装驱动
1.启动树莓派的I2C接口。如已开启,可跳过该步骤。
打开终端(Terminal),键入如下指令,并回车:
pi@raspberrypi:~ $ sudo raspi-config
然后用上下键选择“ 5 Interfacing Options ”, 按回车进入,选择 “ P5 I2C ”, 按回车确认“ YES ”即可。重启树莓派主控板。
2.安装Python依赖库与git,树莓派需要联网。如已安装,可跳过该步骤。
在终端中,依次键入如下指令,并回车:
pi@raspberrypi:~ $ sudo apt-get update
pi@raspberrypi:~ $ sudo apt-get install build-essential python-dev python-smbus git
3.下载驱动库,并运行。 在终端中,依次键入如下指令,并回车:
pi@raspberrypi:~ $ git clone
https://github.com/DFRobot/DFRobot_MCP4725.git
pi@raspberrypi:~ $ cd ~/DFRobot_MCP4725/RaspberryPi/python
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python $ sudo python DFRobot_MCP4725.py
校准与可调模拟电压输出
用户需要自备一块高精度(3位或以上)数字万用表来完成校准,具体步骤如下:
- 将模块与树莓派按照上面的连线图相连,将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地将代码中mcp4725.setAddr_MCP4725()的参数改为MCP4725A0_IIC_Address1。
- 打开python样例程序OutputVoltage.py,将REF_VOLTAGE和OUTPUT_VOLTAGE的值均改为5000(若模块使用3.3V,则均改为3300)并保存。
- 在终端中,依次键入如下指令并回车,运行样例代码:
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python $ cd OutputVoltage
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python/OutputVoltage $ sudo python OutputVoltage.py
- 使用万用表测量VOUT输出电压并将电压值写入REF_VOLTAGE。如:测得VOUT=4950mV,将“REF_VOLTAGE 5000”改为“REF_VOLTAGE 4950”。校准完成。
-
在变量OUTPUT_VOLTAGE输入不超过REF_VOLTAGE的指定电压值(单位:mV),即可输出误差较小的模拟输出电压。在使用后面的样例代码前,可先把校准数值写入REF_VOLTAGE,以获得更准确的输出电压。
-
可以通过下面两种方法打开并修改Python程序:
1.在图形化环境中使用IDLE集成开发环境修改Python程序。点击树莓派主界面上方菜单栏的“File Manager”,然后在地址栏输入“/home/pi/DFRobot_MCP4725/RaspberryPi/Python/OutputVoltage”,右击目录中的Python源码“OutputVoltage.py”,在弹出菜单中选择“Python 3 (IDLE)”,在弹出的窗口中即可编辑Python程序。完成编辑后使用快捷键“Ctrl+S”保存关闭窗口即可。
2.在Terminal环境中使用nano编辑器修改Python程序。在Terminal中输入如下指令:
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python/OutputVoltage $ nano OutputVoltage.py
输入指令后,即使用树莓派自带的nano编辑器打开了一个Python程序。完成代码修改后使用快捷键“Ctrl+O”保存,按回车确认,然后使用快捷键“Ctrl+X”关闭nano编辑器即可。
将DAC值存入EEPROM
- 将模块与树莓派按照上面的连线图相连,将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地将修改代码中mcp4725.setAddr_MCP4725()的参数改为MCP4725A0_IIC_Address1。
- 用户可修改Python例程OutputVoltageEEPROM.py中变量OUTPUT_VOLTAGE的值,以改变模拟电压的输出值。REF_VOLTAGE可采用在校准一节中所使用的值,若未进行校准,根据VCC供电的额定值输入5000(5V)或3300(3.3V)。
- 在终端中,依次键入如下指令并回车,运行样例代码:
pi@raspberrypi:~ $ cd ~/DFRobot_MCP4725/RaspberryPi/Python/OutputVoltageEEPROM
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python/OutputVoltageEEPROM $ sudo python OutputVoltageEEPROM.py
结果
- 使用万用表可测得模块的VOUT产生1V电压信号。拔出模块与树莓派的所有连接,然后再重新连接相应的供电5V和GND,使模块重新上电(但不通过I2C通信),在VOUT上仍能测出1V电压。函数mcp4725.outputVoltageEEPROM()在输出一个指定的模拟电压信号的同时将该DAC值存储在EEPROM中,模块在重新上电的时候调用EEPROM中的DAC值,在VOUT恢复上次断电时的模拟输出电压。
正弦波模拟电压输出
- 将模块与树莓派按照上面的连线图相连,将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地将修改代码中mcp4725.setAddr_MCP4725()的参数改为MCP4725A0_IIC_Address1。
- REF_VOLTAGE可采用在校准一节中所使用的值,若未进行校准,根据VCC供电的额定值输入5000(5V)或3300(3.3V)。
- 在终端中,依次键入如下指令并回车,运行样例代码:
pi@raspberrypi:~ $ cd ~/DFRobot_MCP4725/RaspberryPi/Python/OutputSin
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python/OutputSin $ sudo python OutputSin.py
- 使用示波器观察VOUT输出电压波形。
- 用户可修改函数mcp4725.outputSin()中的参数改变输出正弦波的幅度,频率和直流偏置。
结果
- 可观察到一个幅值为2.5V(峰峰值约为5V),频率为10Hz,带有2.5V直流偏置的完整正弦波
outputSin(amp,freq,offset)
- 函数说明:产生一个Vo=Voffset+Vp*sin(2*pi*f*t)的正弦波信号。当Vo>REF_VOLTAGE时,取值REF_VOLTAGE;当Vo<0时,取值0。
- amp:单位(mV),设定正弦波幅度Vp。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE,取0时为直流信号。
- freq:单位(Hz),设定正弦波频率f。取值范围0~40,取值大于40时取40,取0时为直流信号。
- offset:单位(mV),设定正弦波直流偏置Voffset。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
三角波模拟电压输出
- 将模块与树莓派按照上面的连线图相连,将模块上的ADDR拨至0x60设定I2C地址。若拨至0x61,需要相应地将修改代码中mcp4725.setAddr_MCP4725()的参数改为MCP4725A0_IIC_Address1。
- REF_VOLTAGE可采用在校准一节中所使用的值,若未进行校准,根据VCC供电的额定值输入5000(5V)或3300(3.3V)。
- 在终端中,依次键入如下指令并回车,运行样例代码:
pi@raspberrypi:~ $ cd ~/DFRobot_MCP4725/RaspberryPi/Python/OutputTriangle
pi@raspberrypi:~/DFRobot_MCP4725/RaspbeeryPi/python/OutputTriangle $ sudo python OutputTriangle.py
- 使用示波器观察VOUT输出电压波形。
- 用户可修改函数mcp4725.outputTriangle()中的参数改变输出正弦波的幅度,频率,直流偏置和占空比。
结果
- 可观察到一个幅值为5V(峰峰值约为5V),频率为10Hz,无直流偏置,占空比为50%的完整三角波
outputTriangle(amp,freq,offset,dutyCycle)
- 函数说明:产生一个三角(锯齿)波信号Vo。当Vo>REF_VOLTAGE时,取值REF_VOLTAGE;当Vo<0时,取值0。
- amp:单位(mV),设定三角(锯齿)波幅度。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
- freq:单位(Hz),设定三角(锯齿)波频率。取值范围0~40。取值大于40时取40,取0时输出恒定0V。
- offset:单位(mV),设定三角(锯齿)波直流偏置。取值范围0-REF_VOLTAGE,取值大于REF_VOLTAGE时取REF_VOLTAGE。
- dutyCycle:单位(%),设定三角(锯齿)波占空比。取值范围0~100,取值大于100时取100,取0或100时成为锯齿波。
- 在上述基础上其它参数不变,仅将占空比改为0,即“DAC.outputTriangle(5000,10,0,0)”可产生一个幅度为5V频率为10Hz的锯齿波
常见问题
Q1.为什么所提供的MCP4725库正弦波与三角波最高仅能输出100Hz(Arduino),40Hz(树莓派),频率可以更高吗? |
- A. MCP4725采用I2C与主控通信,使用Arduino等传统主控板时,最高只能使用快速模式Fast(400kbps)。实际测试中(Arduino),给DA模块赋值到电压出来一次的时间差不多要180us,加上正弦或者三角波运算后所消耗的时间,仅能勉强达到一百多Hz。MCP4725的I2C虽然支持高速High-speed(3.4Mbps),但大部分主控板不支持高速模式I2C,因此受限于通信接口,输出频率难以进一步提升。
更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。