成为订阅者(免费)

加入29,000名其他订阅者以获得用户销售折扣和 其他免费资源。
:
:
大学教师'担心 - 您的邮件地址完全是 安全的。我保证使用它 只要 to send you MicroZine.

PCF8591.


PCF8591.是具有4个模拟输入的ADC,可用作两个 差分输入。它使用I2C通信接口并执行a 连续近似转换过程 - 与操作相同 ADC在Arduino。它还具有允许模拟输出的DAC。

PCF8591. YL-40突破板模块

PCF8591.突破板

PCF8591.可能是一个不错的选择 如果您需要更多项目的模拟输入,只要您 don'T需要高分辨率(8bit) - 还有其他限制。

笔记: 该ADC(X4)只有8位分辨率,但包括DAC(X1)!

来自a的基本更新率 single ADC 是11khz - 与...相当 arduino. ADC. - 但只需更快 [否它慢一点参见分析和测试结果 这里]。

该设备的一个不寻常能力是使用内部DAC(8bit分辨率)的模拟输出。但是有 限制对DAC.

警告: DAC输出将不会超出 0.9xvcc. with a 10k load.

您可以在同一个I2C总线上添加多达七个额外筹码 为您提供32个模拟ADC输入和8个DAC模拟输出。

PCF8591.还具有单独的接地输入。使用此输入,您可以保持模拟和数字 grounds 分开(并仅在电源接地处连接它们)。这一站式 数字噪音 泄漏到模拟电路中,使您变得更好 result.

PCF8591.规范

  Parameter
PCF8591.
  Voltage Supply (Vs)
 2V5 ~ 6V0
  Abs. Max VDD.
-0v5〜8v0.
  Interface
I2C
  I2C rate
100kHz
  Resolution (ADC)
8 bit
  输入(单结束/差异)
4 / 2
  电源最大(AOUT OFF,AOUT开启)
250ua / 1ma.
  待机模式(无负载 - 典型,最大)
1ua,15ua.
  偏移错误(ADC,DAC)
20mv,50mv.
  Linearity error
±1.5lsb.
  Gain error
1%
  Conversion time
90us [看 这里]
  Sampling frequency
11.1khz. [看 这里]
  差分输入范围
-vfs / 2〜+ vfs / 2
  I2C地址(H / W被选中= 8off)
0x48〜0x4f.
  工作温度
-40°C〜85°C

PCF8591.数据表

下载PCF8591数据表 这里.

PCF8591.引脚向导

DIP版本和SO16(SMD)的引脚排列是相同的:

PCF8591.引脚向导
                                            [Source: Datasheet]

PCF8591.输入

可以将四个ADC通道配置为单端或 差分输入。对于单一结束的输入,这些工作相同 Arduino ADC输入I.它们与地面测量输入信号。

对于差异读取,两个ADC输入之间的差异是 测量(使用内部OP-AMP从中减去一个信号 其他)。这是你可以的东西'与ARDUINO一样,作为所有ADC输入 参考地面(Arduinos中没有内部OP-AMPS 除了可以进行差异ADC测量的Attiny85外。

那里 您可能想要这样做的两个原因:

1.    测量组件两端的电压 (当没有结束到地面时)。
2.    使用差分输入降低噪声 - 相同的噪声电压将在电阻上定位,因此消除。
3.    通过测量从地面弹跳来减少噪音 (参见下面的图中的选项01)使用虚拟地面(见下文)。

警告: 差分输入信号范围减半。您只能在-VFS / 2〜VFS / 2中具有信号。

地面弹跳

地面 反弹是由沉没和采购电流引起的 数字系统。当数字信号改变状态电流被绘制并将其转移到地面 飞机返回负电源。

这 地面平面的小阻力,在一个引脚和另一个销之间, 导致小的电压降 - 但添加多个更改即在 微控制器,你可以得到一个大地面反弹。从单身 结束ADC测量通过将输入电压与地进行比较, 地面反弹会导致错误。

使用单独的地面 飞机减少模拟电路的数字地面反弹(自以来 两架平面 - 数字地面和模拟地面 - 仅连接在 电源输入)。因此数字噪音没有泄露到 模拟地面平面。

另一种避免噪声的方法是创建虚拟地面 使用OPAMP和参考信号到该OP-AMP输出。 op-amp 可以使用模式01(下面)以这种方式使用;通过喂食OP-AMP 输出到下面的AIN3。

您还可以使用PCF8591混合和匹配单个结束或差分输入能力。例如,你可以拥有 两个单一结束输入(参考地面)和一个差异 输入。下表显示了可用的可编程选项。

PCF8591.模拟输入:单端或差异
                                             [Source: Datasheet]

PCF8591. I2C地址's

地址的较低三位由三个数字组成 输入A2,A1,A0,而上部位固定在1001xxx。最后一个 bit( LSB ' 'l)被忽略,因为它是读写位(R / WN)。所以 可用的地址是:

        0x48,0x49,0x4a,0x4b,0x4c,0x4d,0x4e,0x4f。

通过在硬件中设置输入A2..a0,通过设置输入A2..a0,有八个单独的地址。

PCF8591. DAC输出

PCF8591.具有内部DAC(数字到模拟转换器) 创建具有256个步骤的真正模拟信号。它的工作原理 切换不同的内部电阻。所以不像Arduino 使用PWM信号的模拟信号(并且需要滤波电容) 这是一个真正的模拟输出。

DAC需要执行模拟 数字转换,生成与之比较的模拟信号 输入信号(参见连续近似ADC的操作 这里)。在PCF8591中,该模拟信号也可以直接输出到 Aout pin.

由于DAC用于部分ADC转换过程 似乎不太可能为其他目的使用它。但是,DAC输出有轨道 并保持容纳输出常量的放大器 虽然DAC输出更改为不同的值。

因此,您可以在使用ADC输入的同时使用DAC输出。

提示: 您可以使用DAC模拟输出(AOUT),因为它具有轨道和保持放大器。

DAC输出电流

DAC输出存在略有问题,这是它的当前 靠近0V或VCC的输出变化 - 因此阻抗更改 在输出电压上。

数据表显示阻抗 DAC输出在范围的末端增加,如下所示:

轨道附近的DAC输出阻抗

           [Source: Datasheet]

这意味着你越靠近铁轨的电流就越少 因此,可用的阻抗在输出处呈现越高。

实际上,数据表给出了模拟中10K的负载的示例 输出,但输出电压然后限制为0.9x vDD.。请注意,对于空载,输出将一直到vDD. - 这意味着来自DAC的输出电流并不好。

警告: DAC不会转到正电源轨(10k负载)。

另一个问题是你可以'无论如何,T获得了很多电流 因此,使用opamp缓冲DAC输出是一个好主意。

数据表没有直接说出您可以画多少 指示何时偏离EUT关闭,电源电流为250UA。所以应该有 要玩750ua - 这意味着不要加载大量加载ZOUT, 肯定不到750A。

硬件

PCF8591. YL-40突破板示意图

PCF8591.突破板原理图

查看放大的图像 这里.

YL-40分量位置

突发板PCF8591

arduino. Board.

您可以使用此设备使用任何Arduino,因为芯片从2.5运行 到6.0伏特。这里使用Arduino或arduino nano。

您只需将设备连接到Arduino上的I2C引脚。 If you don'使用默认的I2C引脚然后arduino软件 将使用一位撞击(较慢)的方法来控制设备。 这意味着您可以在单个Arduino板上拥有多个I2C总线。

提示: 使用Arduino上的任何引脚作为I2C,用于额外的I2C总线(较慢)。

软件

PCF8591.库

下载并安装ZIP库:

    //github.com/overbog/PCF8591

......并安装进入'libraries'您的Arduino安装中的目录。

有关如何执行此操作的说明 这里 - 使用zip安装或手动安装方法,因为它无法通过图书馆管理器工具(Arduino IDE)提供。

PCF8591.功能

图书馆具有以下功能:
  • 初始化。
  • ADC Read / Bulk Read。
  • DAC写。
  • 芯片关闭。

一个有用的功能是power_save参数。每个ADC读取后,这会关闭芯片,节省电量。

有两种类型的读取操作:

  • 生的。
  • 调整(使用您提供的电压参考参数)。

PCF8591.省电

初始化对象时输入省电模式:

    PCF8591(UINT8_T ADDR,BOOL POWER_SAVE);

PCF8591. ADC读取原始

    uint8_t adc_raw_read(uint8_t频道);

相应的批量读取希望您提供4 x 8位数组指针:

    void adc_bulk_raw_read(uint8_t * res);

PCF8591. ADC阅读

这些功能镜像原始版本,但需要电压参考 价值。他们通过计算相对于浮点转换来工作 the reference value:

    Double ADC_READ(UINT8_T端口,双V_REF);

相应的批量读取希望您提供4 x 8位数组指针:

    void ADC_BULK_READ(DOUBLE * RES,DOUBLE V_REF);

提示: 提示:查找如何使用 arduino.内部电压参考 在链接中提高ADC读数的准确性。

PCF8591. DAC写道

    void dac_write(uint8_t值);

PCF8591.关闭

    void dac_shutdown();

此命令关闭芯片振荡器,可节省电源。

代码警告

图书馆掉电操作

在纠正DAC POSPOWDOW操作的库中有两个编辑(下):

图书馆编辑一个

库不初始化_dac_enable,因此在运行时未确定。因此,在PCF8591.h中编辑代码:


    bool _dac_enable;

到:

    bool _dac_enable = false;

......确保正确的断电操作。

图书馆编辑二

您还需要编辑DAC_shutdown函数(在PCF8591.cpp中)以包括_dac_enable设置,如下所示:


    void pcf8591 :: dac_shutdown()
    {
        _dac_enable = false;
        wire.begintroansmission(_i2c_addr);
        Wire.write( 0 );
        wire.endtransmission();
    }

笔记: 变量'_power_save'在功能PCF8591()中初始化,因此不需要在头文件中初始化。

PCF8591简单的Arduino素描

此示例将原始ADC值输出到串行终端, 每个模拟输入。在突破板上,这些连接到了 LDR(轻依赖电阻), 热敏电阻和电位计。

A2(AIN2)未连接到载电路中的任何内容。它是 浮动,可用于接受用于测量的外部电压。 使用所有输入,没有任何连接的电路电路 删除所有跳线。

在程序中,电位计ADC读数输出到模拟输出ZOUT。 因此,更改罐值将控制发送到D1(绿色)的电压并改变其亮度。 请记住等待程序循环更新,因为它设置为包括1秒的延迟。 changes won'直到经过一秒钟过去了!

警告: D1 LED和1K电阻向AOUT引脚提供大负载(参见 这里 for details). 因此,如果要具有正确的模拟OUT操作,则正确使用UNSORDER D1或R3可以停止此负载。 即便如此,您也应该使用Opamp缓冲区。

#include <Wire.h>
#include "PCF8591.h" // //github.com/overbog/PCF8591

PCF8591. pcf8591(0x48,0);

////////////////////////////////////////////////////////////////
void setup() {
    Wire.begin();
    Serial.begin(115200); // initialize serial communication
    pcf8591.begin();
}

////////////////////////////////////////////////////////////////
// Right align a value (type long) for column algined text output.
// For ADC can get large numbers and int too small.
void printLongRight(byte fieldSize, long v) {
char str[10];
   ltoa(v,str,10);
   在 t len = strlen(str);
   if (len>fieldSize) len = fieldSize;
   在 t spc = fieldSize-len;
   for( 在 t i=0;i<spc;i++) Serial.print(' ');
   for( 在 t i=0;i<len;i++) {
      Serial.print(str[i]);
   }
}

////////////////////////////////////////////////////////////////
void loop() {

   uint8_t res[4];

   在 t ana0V = pcf8591.adc_raw_read(0);
   在 t ana1V = pcf8591.adc_raw_read(1);
   在 t ana2V = pcf8591.adc_raw_read(2);
   在 t ana3V = pcf8591.adc_raw_read(3);

   Serial.print("A0 BRIGHT ");  printLongRight(6,ana0V);
   Serial.print(" A1 TEMP ");   printLongRight(6,ana1V);
   Serial.print(" A2 ANA  ");   printLongRight(6,ana2V);
   Serial.print(" A3 POT ");    printLongRight(6,ana3V);
   Serial.println();

   pcf8591.adc_bulk_raw_read(res);

   Serial.print("A3 raw ");Serial.println(res[3]);

   Serial.print("Read VCC (assumed  Vref of 5V): ");
   Serial.println(pcf8591.adc_read(3,5));

   // Write the ADC value from the pot to Aout.
   pcf8591.dac_write(pcf8591.adc_raw_read(3));
   delay(1000);
}

[pcf8591.ino]

PCF8591.运营分析

要了解一些关于我将定时器添加到上面的性能的信息 程序以查看芯片执行的快速(参见下面的草图)。令人惊讶的是 芯片执行大量。有提示 建议此性能限制的数据表:

特点和优惠

        "我给出的最大抽样率2C-Bus速度"

第8.4节A / D转换
        "
        PCF8591.第8-4节
        "

上面的最后一段显示了问题:

        "A / D转换周期始终是 发送有效的读取模式后开始         地址到PCF8591设备。"

这意味着转换直接与I2C总线时序直接捆绑在一起"我给出的最大抽样率2C-Bus速度"因此绝对是真的。

此设备必须在开始之前等待完整的IC交易 A / D转换。除此之外,输出结果始终是 自第二言声以来延迟了一个I2C交易:

        "A / D转换循环在后缘触发
        确认时钟脉冲和 在发送结果时执行         previous conversion."

这意味着获得一张迄今为止的ADC阅读,您可以读取读取,然后 将结果抛弃,然后进行第二个ADC阅读并保留!

PCF8591.误导数据表

你可以认为(就像我一样)采样频率11.1khz(或 转换时间段 - 90us)为您提供了良好的迹象 芯片的速度性能。

它不是!!!!

确定该设备操作速度的过播式参数 是I2C总线,它限于100kHz。 100khz听起来很好你 say:

听起来很好,但有三个相关事实:

  1. 您必须发送一个地址。
  2. 您必须执行2个读取以获得一个(见上文)。
  3. 当您想要快速传输数据时,100kHz非常缓慢(1 / 100k = 10us)。

PCF8591.时序分析

该设备中的关键钳口块是I2C接口的速度。

添加I2C字节交易时会消耗时间。

假设上述操作需要3 x I2C数据包;这是8. 数据位加上ACK,启动和停止。让我们也承担一圈时间 对于〜3位的处理器(相当于3bits的时间)。

这是一个猜测,所以绝对绝对准确,但将提供球园估计。所以我们需要执行I2C交易:

    3 *(字节+ ACK + START + STOP)+ 3 *处理器时间= 3 * 11 + 3 * 3 = 42位

在我们看到设备中的任何数据之前,这是42位。以100khz i2c速率执行此操作的时间是:

     42 *(1 / 100e3)= 0.42ms,1.0 / 0.42E-3 = 2380Hz

所以,如果您认为您将获得采样率(从芯片中取出) 11khz) - 再次想!实际上,测量结果比这更糟糕(见下面的测试)!

计时测试素描

#include <Wire.h>
#include "PCF8591.h" // //github.com/overbog/PCF8591

PCF8591. pcf8591(0x48,false);              // ADDR, power_save
PCF8591. pcf8591_power_save( 0x48, true ); // ADDR, power_save

////////////////////////////////////////////////////////////////
void setup() {
    Wire.begin();
    Serial.begin(115200); // initialize serial communication
    pcf8591.begin();
    pcf8591_power_save.begin();
}

////////////////////////////////////////////////////////////////
// Right align a value (type long) for column algined text output.
// For ADC can get large numbers and int too small.
void printLongRight(byte fieldSize, long v) {
char str[10];
   ltoa(v,str,10);
   在 t len = strlen(str);
   if (len>fieldSize) len = fieldSize;
   在 t spc = fieldSize-len;
   for( 在 t i=0;i<spc;i++) Serial.print(' ');
   for( 在 t i=0;i<len;i++) {
      Serial.print(str[i]);
   }
}
////////////////////////////////////////////////////////////////
// Takes a pointer to the object as power save set at initialisation.
void test_read_time(PCF8591. *ptr) {
uint8_t res[4];

   Serial.println("~~~~~~~~~~~~~~");
   unsigned long timeMicro = micros();
   for (在 t i=0;i<10;i++ )
      ptr->adc_bulk_raw_read(res);
   timeMicro = micros()-timeMicro;
   Serial.print("Block read takes : ");
   Serial.print(timeMicro/10);
   Serial.println(" micro seconds");
   Serial.print("Frequency : ");
   float fval =   1.0 / ( ( (float)timeMicro/10.0) *1e-6); // 1.0/((float)timeMicro/10.0
   Serial.print(fval);
   Serial.println("Hz");
   Serial.println("~~~~~~~~~~~~~~");

   Serial.println("~~~~~~~~~~~~~~");
   timeMicro = micros();
   for (在 t i=0;i<10;i++ )
      ptr->adc_raw_read(2);
   timeMicro = micros()-timeMicro;
   Serial.print("Single read takes : ");
   Serial.print(timeMicro/10);
   Serial.println(" micro seconds");
   Serial.print("Frequency : ");
   fval =   1.0 / ( ( (float)timeMicro/10.0) *1e-6); // 1.0/((float)timeMicro/10.0
   Serial.print(fval);
   Serial.println("Hz");
   Serial.println("~~~~~~~~~~~~~~");
}

////////////////////////////////////////////////////////////////
void loop() {

   在 t ana0V = pcf8591.adc_raw_read(0);
   在 t ana1V = pcf8591.adc_raw_read(1);
   在 t ana2V = pcf8591.adc_raw_read(2);
   在 t ana3V = pcf8591.adc_raw_read(3);

   Serial.print("A0 BRIGHT ");  printLongRight(6,ana0V);
   Serial.print(" A1 TEMP ");   printLongRight(6,ana1V);
   Serial.print(" A2 ANA  ");   printLongRight(6,ana2V);
   Serial.print(" A3 POT ");    printLongRight(6,ana3V);
   Serial.println();

   Serial.println("####################################");
   Serial.println("HIGH POWER MODE OSCILLATOR ON:");
   pcf8591.dac_write(127); // Enable dac which forces oscillator on.
   test_read_time(&pcf8591);

   Serial.println("####################################");
   Serial.println("LOW_POWER MODE WAIT FOR OSCILLATOR:");
   test_read_time(&pcf8591_power_save);

   Serial.print("Read VCC (assumed  Vref of 5V): ");
   Serial.println(pcf8591.adc_read(3,5));

   // Write the ADC value from the pot to Aout.
   pcf8591.dac_write(pcf8591.adc_raw_read(3));
   delay(1000);
}

[pcf8591_timing_test.ino]

计时测试的测试结果


#################################### HIGH POWER MODE OSCILLATOR ON: ~~~~~~~~~~~~~~ Block read takes : 951 micro seconds Frequency : 1050.86Hz ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ Single read takes : 665 micro seconds Frequency : 1503.31Hz ~~~~~~~~~~~~~~ #################################### LOW_POWER MODE WAIT FOR OSCILLATOR: ~~~~~~~~~~~~~~ Block read takes : 1180 micro seconds Frequency : 847.46Hz ~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~ Single read takes : 888 micro seconds Frequency : 1125.62Hz ~~~~~~~~~~~~~~ Read VCC (assumed Vref of 5V): 2.80 A0 BRIGHT 220 A1 TEMP 214 A2 ANA 178 A3 POT 143

笔记: 这些结果是PCF8591特定,因此它们也适用于在覆盆子PI上使用PCF8591。

时序分析结论

采样率最高为1.5kHz,但对于散装读数,降低到1kHz。 所以它比数据表导致你期望的10倍 (11kHz).

采样率甚至更低'low power mode' because of a delay 写入图书馆代码。延迟是100us延迟允许 芯片在关闭后启动,但延迟不是 在数据表中定义。

警告: 样品率比预期的约10倍。

PCF8591.结论

PCF8591. ADC不是最快的,没有大的分辨率。

您需要一些可以消除噪声的额外模拟输入(使用差分模式的对)是有用的。

采样率低

您可能从PCF8591中出来的最快采样率是 1.5khz(假设循环中的其余代码()不是很好 很多!)。用于立即读取所有四个ADC输入,试样减少 到1kHz。采样率由最大I2C速度控制和用于 该芯片指定为100kHz。

DAC有限

ADC不能超过0.9VCC的10K负载。这是一个 低负荷如此令人失望。另外,在极端的电压输出DAC 输出减少了电流即,在阻抗方面变得更糟。然而,它完全不是没有DAC!

成本

对于不需要高速操作但很多的项目 如果在散装中购买,模拟输入可能是一个不错的选择,因为它将较低的成本低于更有能力的筹码。它一定要是 对于仅需要低采样率,低分辨率的项目(8 比特)并且需要大量的模拟输入(最多32个)。

低噪声

由于可以配置多对模拟输入,因此可以配置差分输入 您可以轻松消除读取时的噪声电压。




新的! Comments

让你说到你刚刚阅读的东西!留下下面的框中的评论。




隐私政策 | 接触 | 关于我

网站地图 | 使用条款


ezoic.报告此广告

访问我们的Facebook页面:

   点击这里



最近的文章

  1. 如何使用ADS1115

    使用ADS1115精度16位ADC进行教程进行低功耗。

    阅读更多

  2. arduino.模拟输出...易模拟输出生成

    arduino.模拟输出:如何创建最精确的PWM模拟输出以及如何创建模拟PWM正弦波。

    阅读更多

  3. 数号和等效的快速宏。加快代码!

    了解DigitalWrite()的工作原理......现在使用17倍宏宏!

    阅读更多

  4. TCS230颜色传感芯片:如何运作以及如何使用它。

    如何使用TCS230(/ TCS3200)彩色检测器芯片并轻松将其添加到您的任何项目中。

    阅读更多

  5. 如何使用ADXL345进行运动感测等。

    使用ADXL345 Acellerometer,您可以检测到16G!您还可以了解如何使用它来点击检测等。

    阅读更多

  6. HMC5883L 3轴数字MAGENTOMTER如何运作

    HMC5883L - 如何制作数字罗盘,了解HMC5883L和QMC5883L之间的差异以及它们是否兼容。

    阅读更多



读者 Comments

"I wanted to thank
你这么好
对于所有信息
你已经提供了
你的网站's

高超极好的."

- 逃亡Potthath.

"This site really is
最好的和我最喜欢的。
我发现这里有很多很有用
项目和提示。"

- 米兰

Bursach.<at>gmail.com<

"Awesome site,
非常,非常容易和好
导航!"


-
镭_tr.<at>
wolf359.cjb.net.


学习微控制器

"Interested in
微控制器?"

注册
免费7天指南:

自由 GUIDE : CLICK HERE


"I am a newbie to PIC
我想说
 how great your
网站一直在为我。"


- 戴夫

de_scott.<at>bellsouth.net

"Your site is a great
和完美的工作。
恭喜。"


- SURESH.

IntegratedInfosys.<at>
Yahoo.com.

"I couldn't find the correct
要定义的词语
你的网页。

非常有用,揭开,
诚实明确。

非常感谢
你的时间和作品。
问候。"


- Anon.

回到顶部