DongshanPI-D1s开发板使用教程之使用ADS1115提供ADC(模数转换)功能

经过 DongshanPI-D1s开发板使用教程之SHT30温湿度传感器(I2C)数据读取DongshanPI-D1s开发板使用教程之使用LCD1602(I2C)液晶显示屏DongshanPI-D1s开发板使用教程之使用U8g2驾驭SSD1306 OLED(I2C)液晶显示屏的学习研究,已经可以熟练使用I2C设备了。

在此基础上,想要多多挖掘板子的功能。经过查看原理图,以及官方资料,发现在V1.1版本中,增加了GPADC按键,但是不能被我们做通用的ADC功能。

一块板子,要是没有AD/DA功能,就少了很多韵味了。

刚好,我手头有一个ADS1115模块,可以用作ADC功能,经过一番研究,顺利为D1s扩展ADC功能。
ADS1115是一款非常常用的ADC模块,用途非常的官方,某宝某ADS1115介绍如下:

看到没,用词:偉大,虽然是店家介绍,但足以说明ADS1115不是浪得虚名。

其具体参数如下:

实物模样如下:

ADS1115,采用I2C接口,有4个通道可用于测量,使用起来,那是相当方便了。
关于ADS1115数模转换的原理等,这里就不想详细说明了,大家可以在网上查找资料,非常丰富。

下面,就将具体使用方式,分享给大家。

一、硬件材料

  1. D1s开发板:DongshanPI-D1s开发板
  2. ADS1115模块:I2C接口
  3. IoT Power:数字电源,方便模拟实际电压测试
  4. 连接线:杜邦线若干,需要2.0转2.54线;手头没有转接线,直接用测试钩

二、原理图
通过查看DongshanPI-D1s开发板的原理图,了解到I2C接口使用和连接:

在上图核心板的左下角,可以看到:
PE12:SCL
PE13:SDA
需要注意的是,默认系统中,开启的是I2C2。

上图中的测量点,用于接入需要实际测量的电压点位。注意,测量设备需要和D1s板子共地,也就是把GND接到板子上即可。

三、实物接线



ADS115供电电压使用D1s板子的5V输出即可。
数字电源的输出+接到ADS1115的A0输入口,GND接到D1s板子的GND即可。

上图中的手机可有可无,主要用于方便显示程序运行的结果,和数字电源设定的电压作对比。

四、编译固件
参考 DongshanPI-D1s开发板使用教程之SHT30温湿度传感器(I2C)数据读取 进行。
如果已经编译烧录过,则不用重新编译烧录,直接使用即可。

五、I2C设备检测
DongshanPI-D1s开发板启动后,参考 DongshanPI-D1s开发板使用基础文档【编译、烧录、adb、gpio-led、c】 使用OTG接口通过adb连接,再进行下面的操作。

  1. 执行i2cdetect -l 查看当前的I2C控制器:

    可以看到,当前可用的i2c设备为i2c-2
  2. 执行i2cdetect -r -y 2,查看识别的I2C外部设备:

可以看到,ADS1115的地址0x48被识别出来了。
ADS1115可以设置地址,请仔细查阅所用设备的说明。如果设置或者不为0x48后续代码中,也要做对应的处理。

如果在列表中,没有看到ADS1115(I2C)的地址,请仔细检查ADS1115的I2C的接线是否正常。
如果因为程序错误,导致I2C设备打开后,进入busy状态,那就把开发板断电,然后重新上电启动,再次进行检查。

六、编写代码
在网上,有很多STM32或者Arduino上使用ADS1115的资料。
我使用的是 adafruit/Adafruit_ADS1X15: Driver for TI’s ADS1015: 12-bit Differential or Single-Ended ADC with PGA and Comparator (github.com),也就是Adafruit为Arduino提供的ADS1X15扩展库。

不过,这个库,只支持Arduino平台。经过一番研究,改造改造,能够支持在Linux上使用了。修改后的代码,已经给官方提交PR了。
如果着急使用的话,可以从我的fork地址下载: HonestQiao/Adafruit_ADS1X15: Driver for TI’s ADS1015: 12-bit Differential or Single-Ended ADC with PGA and Comparator (github.com)

在这个库中,Adafruit_ADS1X15.cpp、Adafruit_ADS1X15.h 为调用库,examples/linux/下面为Linux环境下的测试文件。这个测试文件,参考Arduino下的测试文件来的。
关于调用库的具体信息,请大家查看源码,重点讲解测试文件。

测试文件内容具体如下:

#include "../../Adafruit_ADS1X15.h"

Adafruit_ADS1115 ads; /* Use this for the 16-bit version */
// Adafruit_ADS1015 ads;     /* Use this for the 12-bit version */

void setup(void) {
  // Serial.begin(9600);
  // Serial.println("Hello!");

  // Serial.println("Getting single-ended readings from AIN0..3");
  // Serial.println("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015,
  // 0.1875mV/ADS1115)");
  printf("Getting single-ended readings from AIN0..3");
  printf("ADC Range: +/- 6.144V (1 bit = 3mV/ADS1015, 0.1875mV/ADS1115)");

  // The ADC input range (or gain) can be changed via the following
  // functions, but be careful never to exceed VDD +0.3V max, or to
  // exceed the upper and lower limits if you adjust the input range!
  // Setting these values incorrectly may destroy your ADC!
  //                                                                ADS1015
  //                                                                ADS1115
  //                                                                -------
  //                                                                -------
  // ads.setGain(GAIN_TWOTHIRDS);  // 2/3x gain +/- 6.144V  1 bit = 3mV 0.1875mV
  // (default) ads.setGain(GAIN_ONE);        // 1x gain   +/- 4.096V  1 bit =
  // 2mV      0.125mV ads.setGain(GAIN_TWO);        // 2x gain   +/- 2.048V  1
  // bit = 1mV      0.0625mV ads.setGain(GAIN_FOUR);       // 4x gain +/- 1.024V
  // 1 bit = 0.5mV    0.03125mV ads.setGain(GAIN_EIGHT);      // 8x gain   +/-
  // 0.512V  1 bit = 0.25mV   0.015625mV ads.setGain(GAIN_SIXTEEN);    // 16x
  // gain  +/- 0.256V  1 bit = 0.125mV  0.0078125mV

  if (!ads.begin(ADS1X15_ADDRESS, 2)) {
    // Serial.println("Failed to initialize ADS.");
    printf("Failed to initialize ADS.");
    while (1)
      ;
  }
}

void loop(void) {
  int16_t adc0, adc1, adc2, adc3;
  float volts0, volts1, volts2, volts3;

  adc0 = ads.readADC_SingleEnded(0);
  adc1 = ads.readADC_SingleEnded(1);
  adc2 = ads.readADC_SingleEnded(2);
  adc3 = ads.readADC_SingleEnded(3);

  volts0 = ads.computeVolts(adc0);
  volts1 = ads.computeVolts(adc1);
  volts2 = ads.computeVolts(adc2);
  volts3 = ads.computeVolts(adc3);

  // Serial.println("-----------------------------------------------------------");
  // Serial.print("AIN0: "); Serial.print(adc0); Serial.print("  ");
  // Serial.print(volts0); Serial.println("V"); Serial.print("AIN1: ");
  // Serial.print(adc1); Serial.print("  "); Serial.print(volts1);
  // Serial.println("V"); Serial.print("AIN2: "); Serial.print(adc2);
  // Serial.print("  "); Serial.print(volts2); Serial.println("V");
  // Serial.print("AIN3: "); Serial.print(adc3); Serial.print("  ");
  // Serial.print(volts3); Serial.println("V");
  printf("-----------------------------------------------------------\n");
  printf("AIN0: %d %f V\n", adc0, volts0);
  printf("AIN1: %d %f V\n", adc1, volts1);
  printf("AIN2: %d %f V\n", adc2, volts2);
  printf("AIN3: %d %f V\n", adc3, volts3);

  delay(1000);
}

int main(int argc, char *argv[]) {
  setup();
  while (true) {
    loop();
  }
}

上述代码的逻辑如下:

  • 实例化ADS1115对象:Adafruit_ADS1115 ads
  • 设置放大倍数:ads.setGain(GAIN_TWOTHIRDS),可以不用,使用默认值
  • 开启设备I2C通信:ads.begin(ADS1X15_ADDRESS, 2),两个参数,一个为ADS1115的地址0x48,一个为/dec/i2c-2的序号
  • 读取数据:ads.readADC_SingleEnded(0),表示读取通道0的数据,也就是A0;可用通道为0~3
  • 电压转换:ads.computeVolts(adc0);表示转换adc0的数据到实际的电压值

ads.setGain()设置表示测量的范围和精度,具体值如下:

  • GAIN_TWOTHIRDS:+/- 6.144V 1 bit = 3mV
  • GAIN_ONE:+/- 4.096V 1 bit = 2mV
  • GAIN_TWO:+/- 2.048V 1 bit = 1mV
  • GAIN_FOUR:+/- 1.024V 1bit = 0.5mV
  • GAIN_EIGHT:+/- 0.512V 1 bit = 0.25mV
  • GAIN_SIXTEEN:+/- 0.256V 1 bit = 0.125mV

基本的使用只需要上面即可步骤即可。更丰富的使用,可以查看Arduino的示例。

七、编译代码并执行
这里需要注意的是,编写、编译、上传、执行,是在不同的环境:

  • 编写:可以在编译固件的环境,也可以在主机环境编写好以后在编译环境编译
  • 编译:在编译固件的环境中编译
  • 上传:在主机环境,通过adb上传到开发板
  • 执行:在开发板上执行

那就先编译代码:

# 设置编译工具路径
export PATH=/sdk/tina-d1-h/prebuilt/gcc/linux-x86/riscv/toolchain-thead-glibc/riscv64-glibc-gcc-thead_20200702/bin/:$PATH

# 编译
cd Adafruit_ADS1X15/examples/linux/
riscv64-unknown-linux-gnu-gcc -o singleended singleended.cpp ../../Adafruit_ADS1X15.cpp

# 查看结果
ls -lh singleended
  -rwxr-xr-x 1 root 18K Nov  9 13:35 singleended

编译完成后,在主机上,使用adb上传:

cd Adafruit_ADS1X15/examples/linux/
adb push singleended /root/

最后,在开发板上执行:

/root/singleended

实际的显示结果如下:

因为最开始,数字电源的输出是关闭的,所以读数只有接近0V。
打开数字电源输出,设定输出为3V,实际2.999V,所以AIN0的数值从接近0上升到了2.999…

此时,数字电源实际电压设置如下:

通过上面的实例,可以学习到,使用ADS1115,可以很方便的为D1s提供ADC功能扩展,能够极大地丰富D1s的功能,值得好好使用!

1 个赞