若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/102524577
各位读者,知识无穷而人力有穷,要么改需求,要么找专业人士,要么自己研究
红胖子(红模仿)的博文大全:开发技术集合(包含Qt实用技术、树莓派、三维、OpenCV、OpenGL、ffmpeg、OSG、单片机、软硬结合等等)持续更新中...(点击传送门)
树莓派开发专栏(点击传送门)
上一篇:《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)》
下一篇:《树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)》
前话
模拟量在物联网电路中开发也是较为重要的,本章使用ADS1115高精度数模转换芯片读取电压模拟量,使用的是树莓派Zero WH。
Demo运行效果
Demo:电压模拟量采集
ADS1115
实物
特点
注意:ADS1115可以调整测量增益,测量范围有八档:
引脚图与访问地址
ADS1115模块,设备地址默认有4个,先看器件引脚图:
根据ADDR引脚连接不到不同的引脚上,其I2C的访问地址是不同的:
- 当ADDR引脚连接到GND时,地址为:0x48(0100, 1000B)
- 当ADDR引脚连接到VDD时,地址为:0x49(0100, 1001B)
- 当ADDR引脚连接到SDA时,地址为:0x4A(0100, 1010B)
- 当ADDR引脚连接到SCL时,地址为:0x4B(0100, 1011B)
根据以上可以得到,我们一个I2C接口单层级联,可以同时连接4个ADS1115,也就是单层一个I2C接口可以同时测量16路16位的模拟电压量。
注意:数据手册还提供了分压的电路图,可以用于测量超过可测量电压的电压值,确保稳定。
多个ADS1115连接(单级最大4个)
4个ADS1115连接的电路图在数据手册上也提供了,所以ADS1115的数据手册还是比较详细的,如下图:
控制指令
特别注意,全程测量范围,输入的电压不应大于VDD+0.3V,否则可能烧坏元器件。
读取指令
先查看读取范围:0~32767。
开启I2C接口
sudo raspi-config
按照下图步骤选取
然后重启。
查看系统是否启动i2c,如下图:
电源原理图
实际接线图:
加了一个电阻分压,检测测量效果。
检测I2C设备是否在线
我们按照电路图连接好后,使用三方查看设备是否在线来判断设备是否正常连接。
sudo apt-get install i2c-tools sudo i2cdetect -y 1
关键代码
初始化代码
Ads1115Widget::Ads1115Widget(QWidget *parent) : QWidget(parent), ui(new Ui::Ads1115Widget) { ui->setupUi(this); QString version = "V1.1.0"; QString title = QString("树莓派Qt开发之Ads1115测量电压Demo %1 作者:红模仿-红胖子 QQ:21497936 blog:https://blog.csdn.net/qq21497936").arg(version); setWindowTitle(title); _pAds1115Manager = new Ads1115Manager(); startTimer(1000); }
每隔1s读取
void Ads1115Widget::timerEvent(QTimerEvent *event) { if(ui->checkBox_adc0->isChecked()) { float adc0 = _pAds1115Manager->readADC_singleEnded(0); ui->lineEdit_adc0->setText(QString("%1").arg(adc0)); }else{ ui->lineEdit_adc0->setText(QString("未进行测量")); } if(ui->checkBox_adc1->isChecked()) { float adc1 = _pAds1115Manager->readADC_singleEnded(1); ui->lineEdit_adc1->setText(QString("%1").arg(adc1)); }else{ ui->lineEdit_adc1->setText(QString("未进行测量")); } if(ui->checkBox_adc2->isChecked()) { float adc2 = _pAds1115Manager->readADC_singleEnded(2); ui->lineEdit_adc2->setText(QString("%1").arg(adc2)); }else{ ui->lineEdit_adc2->setText(QString("未进行测量")); } if(ui->checkBox_adc3->isChecked()) { float adc3 = _pAds1115Manager->readADC_singleEnded(3); ui->lineEdit_adc3->setText(QString("%1").arg(adc3)); }else{ ui->lineEdit_adc3->setText(QString("未进行测量")); } }
模块代码
Ads1115Manager.h
#ifndef ADS1115MANAGER_H #define ADS1115MANAGER_H #include <QObject> #include "i2c.h" #include <QDebug> // I2C ADDRESS/BITS #define ADS1115_ADDRESS (0x48) // 1001 000 (ADDR = GND) // CONVERSION DELAY (in mS) #define ADS1115_CONVERSION_DELAY (8) // POINTER REGISTER 通过写入不同的地址进入不同的寄存器 #define ADS1115_REG_POINTER_MASK (0x03) #define ADS1115_REG_POINTER_CONVERT (0x00) // 转换寄存器 #define ADS1115_REG_POINTER_CONFIG (0x01) // 配置寄存器 #define ADS1115_REG_POINTER_LOWTHRESH (0x02) #define ADS1115_REG_POINTER_HITHRESH (0x03) // CONFIG REGISTER #define ADS1115_REG_CONFIG_OS_MASK (0x8000) // [15] 无效 #define ADS1115_REG_CONFIG_OS_SINGLE (0x8000) // 启动一次转换 #define ADS1115_REG_CONFIG_OS_BUSY (0x0000) // 读取时使用,设备正在执行转换 #define ADS1115_REG_CONFIG_OS_NOTBUSY (0x8000) // 读取时使用,设备当前没有执行转换 #define ADS1115_REG_CONFIG_MUX_MASK (0x7000) // [14:12] 输入多路复用器配置(仅适用于ADS1115) #define ADS1115_REG_CONFIG_MUX_DIFF_0_1 (0x0000) // 000 : AINP = AIN0, AINN = AIN3 : #define ADS1115_REG_CONFIG_MUX_DIFF_0_3 (0x1000) // 001 : AINP = AIN0, AINN = AIN3 : #define ADS1115_REG_CONFIG_MUX_DIFF_1_3 (0x2000) // 010 : AINP = AIN1, AINN = AIN3 : #define ADS1115_REG_CONFIG_MUX_DIFF_2_3 (0x3000) // 011 : AINP = AIN2, AINN = AIN3 : #define ADS1115_REG_CONFIG_MUX_SINGLE_0 (0x4000) // 100 : AINP = AIN0, AINN = GND : 单测量AIN0使用 #define ADS1115_REG_CONFIG_MUX_SINGLE_1 (0x5000) // 101 : AINP = AIN1, AINN = GND : 单测量AIN1使用 #define ADS1115_REG_CONFIG_MUX_SINGLE_2 (0x6000) // 110 : AINP = AIN2, AINN = GND : 单测量AIN2使用 #define ADS1115_REG_CONFIG_MUX_SINGLE_3 (0x7000) // 111 : AINP = AIN3, AINN = GND : 单测量AIN3使用 #define ADS1115_REG_CONFIG_PGA_MASK (0x0E00) // [11:9] 可变成增益放大器配置 #define ADS1115_REG_CONFIG_PGA_6_144V (0x0000) // 000 : +/-6.144V range = Gain 2/3 #define ADS1115_REG_CONFIG_PGA_4_096V (0x0200) // 001 : +/-4.096V range = Gain 1 #define ADS1115_REG_CONFIG_PGA_2_048V (0x0400) // 010 : +/-2.048V range = Gain 2 (default) #define ADS1115_REG_CONFIG_PGA_1_024V (0x0600) // 011 : +/-1.024V range = Gain 4 #define ADS1115_REG_CONFIG_PGA_0_512V (0x0800) // 100 : +/-0.512V range = Gain 8 #define ADS1115_REG_CONFIG_PGA_0_256V (0x0A00) // 101/110/111 : +/-0.256V range = Gain 16 #define ADS1115_REG_CONFIG_MODE_MASK (0x0100) // [8] 设定运行模式 #define ADS1115_REG_CONFIG_MODE_CONTIN (0x0000) // 0 : 连续转换模式 #define ADS1115_REG_CONFIG_MODE_SINGLE (0x0100) // 1 : 单次模式或掉线状态(默认) #define ADS1115_REG_CONFIG_DR_MASK (0x00E0) // [7:5] 数据数率 #define ADS1115_REG_CONFIG_DR_8SPS (0x0000) // 000 : 8 samples per second #define ADS1115_REG_CONFIG_DR_16SPS (0x0020) // 001 : 16 samples per second #define ADS1115_REG_CONFIG_DR_32SPS (0x0040) // 010 : 32 samples per second #define ADS1115_REG_CONFIG_DR_64SPS (0x0060) // 011 : 64 samples per second #define ADS1115_REG_CONFIG_DR_128SPS (0x0080) // 100 : 128 samples per second (default) #define ADS1115_REG_CONFIG_DR_250SPS (0x00A0) // 101 : 250 samples per second #define ADS1115_REG_CONFIG_DR_475SPS (0x00C0) // 110 : 475 samples per second #define ADS1115_REG_CONFIG_DR_860SPS (0x00C0) // 111 : 860 samples per second #define ADS1115_REG_CONFIG_COMP_MODE_MASK (0x0010) // [4] 该位匹配比较器工作模式,该位在ADS1113上不起作用 #define ADS1115_REG_CONFIG_COMP_MODE_TRAD (0x0000) // 0 : 传统比较器 #define ADS1115_REG_CONFIG_COMP_MODE_WINDOW (0x0010) // 1 : 窗口比较器 #define ADS1115_REG_CONFIG_COMP_POL_MASK (0x0008) // [3] 比较器极性 #define ADS1115_REG_CONFIG_COMP_POL_ACTVLOW (0x0000) // 0 : 低电平(默认) #define ADS1115_REG_CONFIG_COMP_POL_ACTVHI (0x0008) // 1 : 高电平 #define ADS1115_REG_CONFIG_COMP_LAT_MASK (0x0004) // [2] 所存比较器(仅ADS1114和ADS1115) #define ADS1115_REG_CONFIG_COMP_LAT_NONLAT (0x0000) // 0 : 非锁定比较器(默认) #define ADS1115_REG_CONFIG_COMP_LAT_LATCH (0x0004) // 1 : 锁存比较器 #define ADS1115_REG_CONFIG_COMP_QUE_MASK (0x0003) // [1:0] 比较队列和禁用(仅用于ADS1114和ADS1115) #define ADS1115_REG_CONFIG_COMP_QUE_1CONV (0x0000) // 00 : 一次转换后置位 #define ADS1115_REG_CONFIG_COMP_QUE_2CONV (0x0001) // 01 : 两次转换后置位 #define ADS1115_REG_CONFIG_COMP_QUE_4CONV (0x0002) // 10 : 在四次转换后置位 #define ADS1115_REG_CONFIG_COMP_QUE_NONE (0x0003) // 11 : 禁止比较器并将ALERT/RDY引脚设置为高阻抗(默认) class Ads1115Manager : public QObject { Q_OBJECT public: explicit Ads1115Manager(uchar devAddr = 0x48, QObject *parent = 0); signals: public slots: bool isOpened(); float readADC_singleEnded(int channel); protected: float getVoltageFromDigit(int adc); private: I2c _i2c; bool _opened; uchar _i2cAddress; }; #endif // ADS1115MANAGER_H
Ads1115Manager.cpp
#include "Ads1115Manager.h" #include <QDebug> #include <QThread> #include <QMessageBox> #include <QElapsedTimer> #include <QApplication> Ads1115Manager::Ads1115Manager(uchar devAddr, QObject *parent) : QObject(parent) { _i2cAddress = devAddr; _opened = _i2c.open(devAddr); if(!_opened) { QMessageBox::warning(0, "Error", "Failed to open ads1115"); } } bool Ads1115Manager::isOpened() { return _opened; } float Ads1115Manager::readADC_singleEnded(int channel) { if(!_opened) { return -1; } if (channel > 3) { return 0; } // 使用默认值 uint16_t config = 0x00; … _i2c.writeData16(ADS1115_REG_POINTER_CONFIG, config); #if 1 QElapsedTimer t; t.start(); while(t.elapsed() < 5) { QApplication::processEvents(); } #endif // 读取配置,若一直在转换则循环读取 int readConfig; do { readConfig = _i2c.readData16(ADS1115_REG_POINTER_CONFIG); }while(readConfig & 0x8000 == 0); int data = 0; float voltage; data = _i2c.readData16(ADS1115_REG_POINTER_CONVERT); … voltage = getVoltageFromDigit(data); return voltage; } float Ads1115Manager::getVoltageFromDigit(int adc) { // 当前设定测量范围0~4.096V, ADS1115_REG_CONFIG_PGA_4_096V float voltage = 0.0f; … return voltage; }
运行效果
上一篇:《树莓派开发笔记(九):CSI口的摄像头拍照(同样适用USB摄像头)》
下一篇:《树莓派开发笔记(十一):蓝牙的使用,BlueZ协议(双树莓探测rssi并通过蓝牙互传获取的rssi信号强度)》
若该文为原创文章,转载请注明原文出处
本文章博客地址:https://blog.csdn.net/qq21497936/article/details/102524577