文章目录

  • 一、简介
  • 二、硬件准备
    • 1、PCF8591 * 1
    • 2、KY-011双色LED模块 * 1
    • 3、树莓派4B * 1
    • 4、硬件引脚连线
  • 三、软件准备
    • 1、PCF8591.py
    • 2、main.py
    • 3、实验结果
    • 4、C程序
  • 四、知识准备
    • 1、PCF8591详解
      • 1.1、模块功能描述
      • 1.2、模块接口说明
      • 1.3、模块原理图
      • 1.4、模块原理说明
      • 1.5、D/A转换
      • 1.6、A/D转换
      • 1.7、PCF8591与Raspberry Pi的关系
      • 1.8、I2C协议通信
  • 五、主要参考资料

一、简介

  因为树莓派上没有内置的模数转换器(ADC),所以当我们需要用树莓派读取模拟量时需要外接一块具有模数转换功能的转换器(ADC),本文使用的是PCF8591中的HW-011,根据参考范例成功复现点亮led灯。

二、硬件准备

1、PCF8591 * 1

  PCF8591是一个单片集成、单独供电、低功耗、8-bit CMOS数据获取器件。PCF8591具有4个模拟输入、1个模拟输出和1个串行I²C总线接口。PCF8591的3个地址引脚A0, A1和A2可用于硬件地址编程,允许在同一个I2C总线上接入8个PCF8591器件,而无需额外的硬件。在PCF8591器件上输入输出的地址、控制和数据信号都是通过双线双向I2C总线以串行的方式进行传输。

2、KY-011双色LED模块 * 1

  ky-011分为红黄两色,(图中左侧)标注‘-’的管脚接GND,中间的管脚控制亮红灯,(图中右侧)标注"S"的管脚控制亮黄灯。

3、树莓派4B * 1

4、硬件引脚连线


  因为后期实验接线较多,为了方便接线,故使用了GPIO扩展板,这个在某宝随便一搜就能买到,一般也就几块钱到十几块钱不等,建议大家多花点钱买个好点的,毕竟这种东西还是一分钱一分货。上图是创乐博制作的接线图,对应有三十多个实验,有一套完整的开发套件,目前网上搜到的教程也大多是参考于此。

树莓派扩展板 PCF8591
SCL SCL
SDA SDA
5V VCC
GND GND

  此处将用Y代替黄灯引脚,R代表红灯引脚,*代表什么都不接,当然这一块接黄接红都一样,就是一个模拟实验,通过PCF8591输出信号给Led,使其亮灯。另外J6短路帽不能取下,其余随便

PCF8591 KY-011 Led
AOUT Y
* R
GND GND

三、软件准备

  原理很简单,就是通过PCF8591获取蓝色电位器调节的输入电压,并将其转化为数字值在终端显示,然后又将其转化成模拟值从AOUT输出达到亮灯的目的。

  另外要想实现效果,得先打开树莓派的I2C接口,其在树莓派中默认是关闭的,在使用该传感器的时候,我们必须首先允许I2C总线通信。

1、PCF8591.py

  PCF8591.py可以单独运行实现led亮灯的效果。

#!/usr/bin/env python
#------------------------------------------------------
#
#       This is a program for PCF8591 Module.
#
#       Warnng! The Analog input MUST NOT be over 3.3V!
#
#       In this script, we use a poteniometer for analog
#   input, and a LED on AO for analog output.
#
#       you can import this script to another by:
#   import PCF8591 as ADC
#
#   ADC.Setup(Address)  # Check it by sudo i2cdetect -y -1
#   ADC.read(channal)   # Channal range from 0 to 3
#   ADC.write(Value)    # Value range from 0 to 255
#
#------------------------------------------------------
#SMBus (System Management Bus,系统管理总线)
import smbus   #在程序中导入“smbus”模块
import time# for RPI version 1, use "bus = smbus.SMBus(1)"
# 0 代表 /dev/i2c-0, 1 代表 /dev/i2c-1 ,具体看使用的树莓派那个I2C来决定
bus = smbus.SMBus(1)         #创建一个smbus实例#在树莓派上查询PCF8591的地址:“sudo i2cdetect -y 1”
def setup(Addr):global addressaddress = Addrdef read(chn): #channelif chn == 0:bus.write_byte(address,0x40)   #发送一个控制字节到设备if chn == 1:bus.write_byte(address,0x41)if chn == 2:bus.write_byte(address,0x42)if chn == 3:bus.write_byte(address,0x43)bus.read_byte(address)         # 从设备读取单个字节,而不指定设备寄存器。return bus.read_byte(address)  #返回某通道输入的模拟值A/D转换后的数字值def write(val):temp = val  # 将字符串值移动到temptemp = int(temp) # 将字符串改为整数类型# print temp to see on terminal else comment outbus.write_byte_data(address, 0x40, temp) #写入字节数据,将数字值转化成模拟值从AOUT输出if __name__ == "__main__":setup(0x48) #在树莓派终端上使用命令“sudo i2cdetect -y 1”,查询出PCF8591的地址为0x48while True:print ('电位计   AIN0 = ', read(0))   #电位计模拟信号转化的数字值print ('光敏电阻 AIN1 = ', read(1))   #光敏电阻模拟信号转化的数字print ('热敏电阻 AIN2 = ', read(2))   #热敏电阻模拟信号转化的数字值tmp = read(0)tmp = tmp*(255-125)/255+125
# 125以下LED不会亮,所以将“0-255”转换为“125-255”,调节亮度时灯不会熄灭write(tmp)time.sleep(2)

2、main.py

  导入PCF8591,只打印电位器电压大小A/D转换后的数字值。

#!/usr/bin/env python
import PCF8591 as ADCdef setup():ADC.setup(0x48)def loop():while True:print ADC.read(0) #打印电位计电压大小A/D转换后的数字值(从AIN0借口输入的)#范围是0~255,0时LED灯熄灭,255时灯最亮ADC.write(ADC.read(0)) #将0通道输入的电位计电压数字值转化成模拟值从AOUT输出#给LED灯提供电源VCC输入def destroy():ADC.write(0)if __name__ == "__main__":try:setup()loop()except KeyboardInterrupt:destroy()

3、实验结果

  运行程序后,led灯被点亮,调节蓝色电位器,led灯的亮度出现变化。

  Shell显示电位计、光敏电阻、热敏电阻的数字值。

  但由于写入的tmp加了125的缘故,始终保持一个较亮的情况,所以调节电位器,led灯也并不会有明显的明暗变化,大家测试的时候可以将其去掉试试。

  手动将其调节为0,100,200,led灯明暗情况:

4、C程序

#include <wiringPi.h>
#include <pcf8591.h>
#include <stdio.h>
#include <time.h>//PCF8591默认的I2C设备地址
#define Address 0x48//模拟信号输入端的地址
#define BASE 0x40
#define A0 0x40
#define A1 0x41
#define A2 0x42
#define A3 0x43//供电(mV)
#define POWER 5000//函数声明
void ShowTime();
float AD_work(unsigned char channel);int main(void)
{//初始化wiringPi设置wiringPiSetup();//设置pcf8591的器件地址pcf8591Setup(BASE, Address);float AD_val;while (1){AD_val=AD_work(A0);//读取A0端口的电压值ShowTime(); //打印当前时间printf("A0 value: %fmV\n", AD_val); //打印A0引脚的输入电压//printf("asgydasg");delay(100);}
}//显示系统时间
void ShowTime()
{time_t t;struct tm *p;int hour = 0, min = 0, sec = 0;time(&t);p = gmtime(&t);hour = 8 + p->tm_hour; //获取当地时间,与UTC时间相差8小时min = p->tm_min;sec = p->tm_sec;printf("\nNow time: %.2d:%.2d:%.2d\n", hour, min, sec);
}float AD_work(unsigned char channel)
{float AD_val; //定义处理后的数值AD_val为浮点数unsigned char i;for (i = 0; i < 10; i++) AD_val += analogRead(channel); //转换10次求平均值(提高精度)AD_val /= 10;AD_val = (AD_val * POWER)/ 255 ; //AD的参考电压是单片机上的5v,所以乘5即为实际电压值return AD_val;
}


实验结果:

四、知识准备

1、PCF8591详解

  ​ PCF8591是一个8位模数转换器或8位数模转换器模块,这意味着每个引脚可以读取高达0 - 255的模拟值;该模块有四个模拟输入和一个模拟输出,同时适用于I2C通信;此外它需要2.5V - 6V电源电压并具有低待机电流,我们可以通过调节蓝色电位器的旋钮来控制输入电压。板上还有三个跳线。 J4连接选择热敏电阻接入电路,J5连接选择LDR /光敏电阻接入电路和J6连接选择0 - 5V可调电压接入电路。要访问这些电路,必须使用这些跳线的地址:J6为0x50,J5为0x60,J4为0x70。电路板上有两个LED,D1和D2 ,D1表示输出电压强度,D2表示电源电压强度。输出或电源电压越高,LED D1或D2的强度越高。

1.1、模块功能描述

  • 1 模块芯片采用 PCF8951
  • 2 模块支持外部 4 路电压输入采集(电压输入范围 0-5v)
  • 3 模块集成光敏电阻,可以通过 AD 采集环境光强精确数值
  • 4 模块集成热敏电阻,可以通过 AD 采集环境温度精确数值
  • 5 模块集成 1 路 0-5V 电压输入采集(通过蓝色电位器调节输入电压)
  • 6 模块带电源指示灯(对模块供电后指示灯会亮)
  • 7 模块带 DA 输出指示灯,当模块 DA 输出接口电压达到一定值,会点亮板上 DA 输出指示灯,电压越大,指示灯亮度越明显;

1.2、模块接口说明

本模块左边和右边分别外扩 2 路排针接口,分别说明如下:

左边 :

  • AOUT :芯片 DA 输出接口
  • AIN0 :芯片模拟输入接口 0
  • AIN1 :芯片模拟输入接口 1
  • AIN2 :芯片模拟输入接口 2
  • AIN3 :芯片模拟输入接口 3

右边 :

  • SCL :IIC 时钟接口 接单片机 IO 口
  • SDA :IIC 数字接口 接单片机 IO 口
  • GND :模块地 外接地
  • VCC :电源接口 外接 3.3v-5v

模块共有 3 个短路帽,分别作用如下:
J4 :接上 J4 短路帽,选择热敏电阻接入电路
J5 :接上 J5 短路帽,选择光敏电阻接入电路
J6 :接上 J6 短路帽,选择 0-5V 可调电压接入电路

注:如果需要使用四路外部电压输入,请将 3 个红色短路帽都取下

1.3、模块原理图


1.4、模块原理说明

  ​ PCF8591是AIN端口输入模拟电压,然后PCF8591将转换后的数字量通过I2C总线发送给单片机,或是单片机通过I2C总线给一个数字量,然后PCF8591通过AOUT端口将模拟电压输出。

第一字节:总线地址

  对于 PCF8591的使用,依旧是按照先寻地址,再读写相应寄存器的步骤,PCF8591芯片所能接收的地址包含固定部分和可编程部分。可编程部分必须根据地址引脚A0,A1,和A2来设置,在I2C总线协议中地址必须是起始条件后作为第一个字节发送,地址字节的最后一位用来设置对目标地址的读或写。地址字节格式如下所示:

  PCF8591采用典型的I2C总线接口器件寻址方法,即总线地址由器件地址、引脚地址和方向位组成。飞利蒲公司规定A/D器件地址为1001,引脚地址为A2A1A0,其值由用户选择,因此I2C系统中最多可接2的三次方=8个具有I2C总线接口的A/D器件。地址的最后一位为方向位R/ W,当主控器对A/D器件进行读操作时为1,进行写操作时为0。总线操作时,由器件地址、引脚地址和方向位组成的从地址为主控器发送的第一字节。

  对于PCF8591来说,其default address为0x48(十六进制数),转换为二进制数是1001000,所以可以知道他的A0、A1、A2三个引脚值均为0。需要再提前强调一点,Python代码中所有0x十六进制数,只有0x48代表Address,也只有PCF拥有Address,其余所有十六进制数都不代表Address。

第二字节:控制字节
  第一个字节是地址字节,那么第二个字节就是控制字节,控制字节发送到PCF8591的控制寄存器中,用于控制器件的功能,控制字格式如下所示:

简略图:

其中:

  • D1、D0 两位是A/D通道编号:00通道0,01通道1,10通道2,11通道3
  • D2 自动增量选择(0为禁止自动增量,1为允许自动增量),如果允许自动增量,则在每次A/D转换后,通道编号会自动递增。
  • D3 特征位:固定值为:0。
  • D5、D4 模拟量输入选择:00为四路单端输入、01为三路差分输入、10为两路单端与一路差分输入、11为两路差分输入。
  • D6 使能模拟输出AOUT有效(1为有效,0为无效)。
  • D7 特征位:固定值为:0。

  编程中遇到的“bus.write_byte(address,0x40) ” 语句就是发送控制字“0x40”,40就代表控制字“0100 0000”,主要表示模拟输出有效,四路单端输入,禁止自动增量,A/D通道为0。

  当系统为A/D转换时,模拟输出允许为0。模拟量输入选择位取值由输入方式决定:四路单端输入时取00,三路差分输入时取01,单端与差分输入时取10,二路差分输入时取11。最低两位时通道编号位,当对0通道的模拟信号进行A/D转换时取00,当对1通道的模拟信号进行A/D转换时取01,当对2通道的模拟信号进行A/D转换时取10,当对3通道的模拟信号进行A/D转换时取11。

  在进行数据操作时,首先是主控器发出起始信号,然后发出读寻址字节,被控器做出应答后,主控器从被控器读出第一个数据字节,主控器发出应答,主控器从被控器读出第二个数据字节,主控器发出应答…一直到主控器从被控器中读出第n个数据字节,主控器发出非应答信号,最后主控器发出停止信号。

1.5、D/A转换


  发送给PCF8591的第三个字节被存储到DAC数据寄存器,并使用片上D/A转换器转化成对应的模拟电压。

  我们可以通过转换公式,将AD转换后的数字量转换为对应的电压值,在数码管或液晶上显示。

#define fun(x) (int)(5*x/255.0*100+0.5)             //数字电压x转换为模拟电压的公式

1.6、A/D转换


  A/D转换器采用逐次逼近转换技术,在A/D转换周期将临时使用片上D/A转换器和高增益比较器,一个A/D转换周期总是开始于发送一个有效读模式地址给PCF8591之后,A/D转换周期在应答时钟脉冲的后沿被触发,并在传输前一次转换结果时执行。

1.7、PCF8591与Raspberry Pi的关系


  将整个系统看作一个进水/出水装置,装置有四根进水管,分别命名为AIN0, AIN1, AIN2, AIN3,还有唯一一根出水管,命名为AOUT。还有四个中转通道,分别命名为channel0, channel1, channel2, channel3,从四根进水管进来的水可以受控制地从某一个通道中流出,进入总管道,之后通过两根出水管道——SDA和SCL,进入一个水的加工处理储存设备。

  Raspberry PI是“MASTER”,PCF是“SLAVER”,他们之间是主从关系。如果主器件要发送数据给从器件,则会启动数据传输,并发送数据至从器件,最后终止数据传输;如果主器件想要接受从器件发来的数据,同样也是发出命令启动数据传输,接收从器件发来的数据,最后终止接收过程。强调一点:每次数据传输都是由“MASTER”主动开启的

1.8、I2C协议通信


   I2C就是一种沟通方式,所以这个数据传输流程,就可以理解为在I2C这种特定沟通方式下的一次沟通。讲的更通俗一点,就是一次聊天对话。

  聊天的第一步,是拿出手机打开微信。(对应START condition,当SDA和SCL两条线的电平同时满足某一特定条件时,传输开始。)

  打开微信后需要找一个联系人才能聊天,我们之前说“MASTER”有很多“SLAVERS”,这一步便是“MASTER”选择与某一个“SLAVER”对话。(对应ADDRESS。)

  第三步,“MASTER”确定这次对话的目的的给“SLAVER”分配活儿干,还是让“SLAVER”干完活后汇报。(对应R/W,R means read,W means write,控制这次数据传输的目的是树莓派写入一个值到PCF中,还是树莓派从PCF中读取一个值。)
可以看到有很多ACK。ACK means Acknowledge character,即确认字符,意思是数据接收者告诉数据传输者,“已收到”。

  之后便是数据传输,每传输一个byte的数据,都会反馈一个ACK确认数据收到。

五、主要参考资料

  • 树莓派基础实验12:PCF8591模数转换器实验 - 程序来源,博主有36个小实验可供参考!
  • PCF8591使用及Python控制 - 手绘图片来源,博主非常棒,讲的通俗易懂。
  • 树莓派实现AD转换(pcf8591模块) - 部分图片来源

树莓派与PCF8591模数转换器的那些事儿相关推荐

  1. 树莓派基础实验12:PCF8591模数转换器实验

    一.介绍    PCF8591 是单片.单电源低功耗8位CMOS数据采集器件,具有4个模拟输入(其中一个为电压模拟输入).一个模拟输出和一个串行I2C总线接口.3个地址引脚A0.A1和A2用于编程硬件 ...

  2. 【树莓派C语言开发】实验12:PCF8591模数转换器模块

    文章目录 前言 1.实验器材 2.实验原理 2.0 元件介绍 2.1 i2c总线 2.2 第一字节 2.3 控制字节 2.4 模块电路 2.5 电路接线 3.程序控制 3.1 在树莓派中开启I2C 3 ...

  3. 树莓派与GPS模块的那些事儿

    文章目录 一.简介 二.硬件准备 1.元器件清单 2.接线说明 三.软件准备 1.安装Python2 2.安装pynmea2库 3.配置mini串口 4.gps.py 四.知识准备 1.GPS数据解析 ...

  4. 【树莓派C语言开发】实验14:PS2游戏手柄模块(关联PCF8591)

    本次实验还是需要用到PCF8591模数转换器,莫非它要取代双色LED成为新的常驻嘉宾吗? 本次实验是摇杆实验.这个玩意可以用于操控机器人或者是树莓派的遥控小车.当然,生活中最常见的用途还是在游戏手柄上 ...

  5. 树莓派-5-GPIO的应用实验

    [树莓派4B学习]一.环境搭建.开机及登录树莓派4B [树莓派4B学习]二.树莓派4B介绍与一些必要的软件安装配置 [树莓派4B学习]三.接入USB摄像头,搭建Python2.7.16+OpenCV3 ...

  6. 树莓派基础实验20:火焰报警传感器实验

    一.介绍    火焰传感器模块通过捕获来自火焰的红外波长来执行检测.它可以用来探测火焰是否存在,在这个实验中,我们使用火焰传感器来检测火焰并发出报警信号. 二.组件 ★Raspberry Pi主板*1 ...

  7. 【树莓派C语言开发】实验15:电位计传感器(关联PCF8951)

    今天的这个实验需要用上两位常驻嘉宾! 它们就是PCF8591和双色LED! 文章目录 1.实验器材 2.实验原理 2.1基本原理 2.2接线图 3.实验效果 3.1代码示例 3.2实验效果 结语 1. ...

  8. 树莓派基础实验18:声音传感器实验

    一.介绍    声音传感器是一种接受声波并将其转换为电信号的组件,它像麦克风一样检测周围环境中的声音强度. 二.组件 ★Raspberry Pi主板*1 ★树莓派电源*1 ★40P软排线*1 ★PCF ...

  9. 树莓派基础实验14:PS2操纵杆实验

    一.介绍    操纵杆是一种输入设备,由一根可在基座上旋转,并向其控制的设备报告其角度或方向的操纵杆组成.操纵杆通常用于控制视频游戏和机器人.这里使用操纵杆PS2. 二.组件 ★Raspberry P ...

最新文章

  1. 计算机基础办公软件应用技能,计算机一级计算机基础及 ms office 应用考些什么...
  2. 想不到,那些让我半夜偷偷收藏的沙雕表情包,竟是出自 AI 之手
  3. TensorFlow基础2(张量)
  4. 编写你的第一个 Django 应用,第 5 部分
  5. STM32学习之普通定时器是否能定时1us?
  6. 捋一捋Android的转场动画
  7. Tivoli Storage Manager安装配置
  8. navigator、history对象
  9. 在iOS设备上安装Windows、Linux等操作系统!
  10. 小学生预习能力培养的策略和方法研究 开题报告
  11. 基于andoird的计步器(全代码)
  12. Ultra Librarian 的安装和使用
  13. L9110 L9110S SOP8 马达驱动 IC 芯片 H桥全桥 贴片
  14. 研究型论文_CICIDS2017 数据集中基于异常的入侵检测系统的机器学习基准测试(英文论文)
  15. SpringBoot整合Elastricsearch + LogStash + Kibana太简单了!
  16. PSGAN 网络再修改
  17. 什么是seo?seo的定义
  18. 算力网络 — 算力中心
  19. 如何用迅雷下载python_用Python调用迅雷批量下载excel表内的链接,并同时对文件重命名(使用的是openpyxl)...
  20. 思科员工离职恶意删除456个虚拟机,造成240w美元直接损失,或面临5年有期徒刑

热门文章

  1. RecyclerView使用GridLayoutManager 设置间距一致大小
  2. 记一次idea莫名其妙报错找不到依赖问题
  3. Spring Security 配置 Remember Me
  4. 人工智能软件怎么开发
  5. matlab:nargin,varargin,varargout
  6. 频谱仪和信号发生器的使用
  7. solaris 的ZFS操作
  8. WS小世界网络构建实验(Matlab版)
  9. Java密码学原型算法实现——第二部分:单钥加密算法
  10. STL vector :大理石在哪儿?