树莓派3B上用Python编程获取TSL2561光传感器数据
在树莓派3B上用Python编程,通过I2C协议,利用TSL2561光照强度传感器获取环境光强
嵌入式萌新一枚,文章有解释不清或者错误的地方希望大佬能在评论区指正,感激不尽!
大概原理: 通过TSL2561芯片资料可以找到,TSL2561光照传感器上有两个采集环境光强的探测器,一个探测器采集红外光和可见光的数据,另一个探测器采集红外光的数据,每个探测器采集的数据按高八位和低八位分别存到两个寄存器上,所以我们一共要读取4个寄存器的数据。将四个寄存器的数据按特定的公式进行运算就可以得到环境可见光数据。
为什么要采集红外光的数据呢? 为了减小误差。因为红外光对传统硅探测器的影响比较大,所以干脆将红外光单独采集出来,两个探测器的数据进行一定的处理就可以得到精度较高的环境可见光数据。
Python编程大概思路:通过封装好的I2C协议函数进行读取数据操作。 先写两个函数,一个函数对传感器进行初始化配置,然后启动光传感器进行采集数据,然后将采集的数据存入数组,再将该数组作为返回值返回。第二个函数将第一个函数的返回值作为形式参数传入,再对其返回值按照公式进行处理 ,最后将处理完的数据打印出来
- 下图是TSL2561的寄存器分布图,我们采集光强要用到的寄存器分别是上面两个COMMAND和CONTROL寄存器和下面四个数据寄存器,它们的地址分别是0,1,C,D,E,F 。
我们所有寄存器控制都要通过命令寄存器也就是COMMAND寄存器来控制,所以给寄存器发送命令时高八位的最高位必须为1,低八位即为寄存器地址
控制寄存器CONTROL:传感器上的探测器需要通过此寄存器才能开启,给此寄存器发送命令0x03时,开启探测器功能,发送命令0x00时,关闭探测功能
- 下图是将采集到的数据按照此种方式进行处理
- 开始上代码,先将代码拆分进行解释,文末给出完整代码Pythin代码以及用C语言写的源代码
首先在命令行输入i2cdetect -y 1以查看传感器设备地址
pi@raspberrypi:~ $ i2cdetect -y 10 1 2 3 4 5 6 7 8 9 a b c d e f
00: -- -- -- -- -- -- -- -- -- -- -- -- --
10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
20: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
30: -- -- -- -- -- -- -- -- -- 39 -- -- -- -- -- --
40: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- --
70: -- -- -- -- -- -- -- --
我们可以看到I2C协议总线里只有一个从设备,那就是TSL2561传感器,地址为0x39
接着在命令行通过vim命令进入代码编辑界面
pi@raspberrypi:~ $ vim light.py
开始将两个包包含进来
#!/usr/lib/python3
import wiringpi
import time
开始定义第一个函数sum_Lux,将第一个数据寄存器地址赋值给reg_addr,定义一个长度为4的空列表(类似于C语言里面的数组),再传入一个空列表,用以存储处理后的数据
def sum_Lux(ch_a):reg_addr=0x8Creg_data=[0,0,0,0]
调用wiringpi包里的wiringPiI2CSetup()函数,返回值赋值给一个变量
该函数的原型为:int wiringPiI2CSetup(int devId);该函数会获取树莓派的版本幵依据此打开/dev 目录下对应的设备。返回值是标准的 Linux 文件句柄,如果有错误,则返回-1。
i2cfd = wiringpi.wiringPiI2CSetup(0x39)
接下来调用wiringpi包里的wiringPiI2CWriteReg8()函数,给控制寄存器发送命令0x03,使其开始探测功能
该函数的原型为:int wiringPiI2CWriteReg8(int fd, int reg, int data);
控制寄存器地址为0,给该寄存器发送命令的地址却是0x80,因为两个字节的地址高八位最高位是COMMAND寄存器,数值必须为1,所以第一个字节为8,第二个字节为控制寄存器地址
wiringpi.wiringPiI2CWriteReg8(i2cfd,0x80,0x03)
然后调用time包里的sleep函数,使程序延迟一段时间
因为传感器开启探测功能后需要有400ms时间让探测器探测数据并将数据存到数据寄存器里
time.sleep(0.5)
接着用一个for循环依次将数据寄存器的值取出来,并存到实现定义好的空列表里
利用wiringPiI2CWrite函数给寄存器发送命令,通知寄存器我将要读取你的数据
再调用wiringPiI2CReadReg8()函数读取寄存器数据
因为数据寄存器地址依次是C,D,E,F。所以地址加1即是下一个数据寄存器的地址
for i in [0,1,2,3]:wiringpi.wiringPiI2CWrite(i2cfd,reg_addr)reg_data[i]=wiringpi.wiringPiI2CReadReg8(i2cfd,reg_addr)reg_addr+=1
然后将高八位数据左移8位与低八位数据相加,即可得到该探测器的实际数据
并将得到的实际数据存到列表中,最后返回列表
ch_a[0]=256*reg_data[1]+reg_data[0]ch_a[1]=256*reg_data[3]+reg_data[2]return ch_a
接着定义一个函数cal_Lux()用以处理上一个函数采集的数据,再将处理后的光强的值返回
def cal_Lux(ch):bizhi=ch[1]/ch[0]if(bizhi<=0):return -1elif bizhi<=0.52:Lux=(0.0315*ch[0]-0.0593*ch[0]*((ch[1]/ch[0])**1.4))elif bizhi<=0.65:Lux=(0.0229*ch[0]-0.0291*ch[1])elif bizhi<=0.80:Lux=(0.0157*ch[0]-0.0180*ch[1])elif bizhi<=1.3:Lux=(0.00338*ch[0]-0.0026*ch[1])else:Lux=0return Lux
定义一个空列表用以数据中转,再调用两个函数,将光强的真实值打印出来
CH = [0,0,0,0]
Lux = cal_Lux(sum_Lux(CH))
print("光感应强度为:",Lux)
代码拆分解释到此结束
下面是完整的python源代码
#!/usr/lib/python3.5import wiringpi
import timedef cal_Lux(ch):bizhi=ch[1]/ch[0]if(bizhi<=0):return -1elif bizhi<=0.52:Lux=(0.0315*ch[0]-0.0593*ch[0]*((ch[1]/ch[0])**1.4))elif bizhi<=0.65:Lux=(0.0229*ch[0]-0.0291*ch[1])elif bizhi<=0.80:Lux=(0.0157*ch[0]-0.0180*ch[1])elif bizhi<=1.3:Lux=(0.00338*ch[0]-0.0026*ch[1])else:Lux=0return Luxdef sum_Lux(ch_a):reg_addr=0x8Creg_data=[0,0,0,0]i2cfd=wiringpi.wiringPiI2CSetup(0x39)wiringpi.wiringPiI2CWriteReg8(i2cfd,0x80,0x03)time.sleep(0.5)for i in [0,1,2,3]:wiringpi.wiringPiI2CWrite(i2cfd,reg_addr)reg_data[i]=wiringpi.wiringPiI2CReadReg8(i2cfd,reg_addr)reg_addr+=1ch_a[0]=256*reg_data[1]+reg_data[0]ch_a[1]=256*reg_data[3]+reg_data[2]return ch_aCH=[0,0,0,0]
Lux=cal_Lux(sum_Lux(CH))
print("光感应强度为:",Lux)
在命令行执行
pi@raspberrypi:~ $ python light.py
即可显示光强数值
由于此Python代码完全是由C语言逐句改写,下面也贴一下用C语言实现的源代码
#include<wiringPiI2C.h>
#include<stdio.h>
#include<unistd.h>
#include<math.h>//编译的时候要链接-lm库和-lwiringPi库,lm库用以运行pow函数
//int main(int argc , char **argv[])
{double Lux ; //光强的值double* sum_Lux(double* CH_L) ; //采集光强的原始值,返回数组首地址double cal_Lux(double* ch); //将光强原始值进行处理,得到光强实际值double CH[4] ; //存储光强原始值, Lux = cal_Lux(sum_Lux(CH));printf("%f\n",Lux);return 0 ;
}double cal_Lux(double* ch)
{double bizhi ; //两个传感器原始值的比值 double Lux ; //光强实际值 bizhi = ch[1]/ch[0] ; //根据计算公式处理光强原始值if(bizhi <= 0 )return -1 ; else if(bizhi <= 0.52)Lux = (0.0315*ch[0] - 0.0593*ch[0]*pow(ch[1]/ch[0],1.4));else if(bizhi <= 0.65)Lux = (0.0229*ch[0] - 0.0291*ch[1]);else if(bizhi <= 0.80) Lux = (0.0157*ch[0] - 0.0180*ch[1]);else if(bizhi <= 1.3)Lux = (0.00338*ch[0] - 0.0026*ch[1]);elseLux = 0 ; return Lux ;
}double* sum_Lux(double* CH_L)
{int reg_addr = 0x8C ; //数据寄存器初始地址0x8Cint i = 0 ; int i2cfd ;int reg_data[4];i2cfd = wiringPiI2CSetup(0x39); //开启光传感器,将文件流赋值给i2c变量wiringPiI2CWriteReg8(i2cfd,0x80,0x03); //给控制器寄存器发送指令0x03,命令传感器开始采集光强sleep(1) ; //采集光强数据后延迟1秒,再对寄存器进行读取数据 for(i ; i < 4 ; i++){wiringPiI2CWrite(i2cfd, reg_addr); //给寄存器发送指令,以便读取寄存器的数值reg_data[i] = wiringPiI2CReadReg8(i2cfd,reg_addr); //开始读取寄存器数据,寄存器地址依次递增,采用八位函数读取,一次读取两个字节reg_addr++ ; }CH_L[0] = 256 * reg_data[1] + reg_data[0]; //高八位数据左移8位,与低八位相加CH_L[1] = 256 * reg_data[3] + reg_data[2]; return CH_L ; //返回数组首地址
}
树莓派3B上用Python编程获取TSL2561光传感器数据相关推荐
- OpenHarmony3.0在树莓派3B上的烧录与通讯
OpenHarmony3.0已于2021年9月30号正式发布,本篇文章详细给出OpenHarmony3.0在树莓派3B上的烧录与通讯步骤,对其中使用的指令进行详细解释,同时附有烧录与通讯过程中使用的各 ...
- 树莓派python开发教程_树莓派教程(基于python编程)--入门篇
原标题:树莓派教程(基于python编程)--入门篇 一:格式化SD卡 SD卡插入读卡器连接电脑,使用SDFormatter对SD卡进行格式化 (重装烧录也要进行着SD卡格式化操作) 二:下载官方镜像 ...
- 在树莓派3B+ 上使用YOLO v3 Tiny进行实时对象检测
主要参考文章:http://funofdiy.blogspot.com/2018/08/deep-learning-with-raspberry-pi-real.html(需要vpn) https:/ ...
- python编程获取续蜀山剑侠传:目录名称、网址、内容,保存到文件
昨天已经用Python编程完成了 从<续蜀山剑侠传>连载网站页面上获取目录信息,包括目录名称和网址,进而读取每个网址对应的网页中连载内容,详见: python编程获取续蜀山剑侠传:从目录名 ...
- 如何python编程获取,分析可转债,让大家实现财富的小目标?
概要: 本文从可转债解释开始,对可转债的特点,不亏钱的特点,如何python编程获取,分析可转债,然后从实际例子出发给大家对目前市面上的可转债进行实战分析,让大家实现财富的小目标. 可转债是什么? & ...
- 树莓派教程(基于python编程)--初级篇
一.远程连接和远程桌面设置: 终端下执行命令: ifconfig,查看树莓派的IP 终端下执行命令:sudo apt-get install xrdp ,安装远程桌面支持. 在windows电脑上点开 ...
- 树莓派python编程优点_树莓派为什么会使用python编程?为什么有时python运行效率不高?...
在许多编程语言中,Python的语法也有很大不同.Python使用空格或缩进来分隔不同的代码块.C语言和其他语言使用花括号来区分不同的代码块,例如if语句,Python使用冒号和缩进来定义代码块.这也 ...
- 树莓派安装win10arm linux,在树莓派3B 上安装 Windows 10 ARM 版的方法
早先关注我们的朋友可能对<国外开发者尝试在树莓派3上运行Windows 10桌面版>有印象.本文转自 amatfan.com,文末视频来自 daveb778(感谢柠栀和刺分享),给出了如何 ...
- 如何在树莓派上进行python编程_设置并使用树莓派进行Python和C语言编程 (下)
Python部落(www.freelycode.com)组织翻译, 禁止转载 关键字 条件关键字 下表列出了和条件语句有关的关键字和它们的简要描述 if用来决定将要执行哪条语句 else 可选,条件为 ...
最新文章
- 10个C#编程和Visual Studio使用技巧
- LVDS收发传输实例
- Go单元测试从入门到放弃—0.单元测试基础
- python多进程间通信_Python 多进程编程之 进程间的通信(Queue)
- Git 提交错了不用慌,这三招帮你修改记录
- Active Directory的安装
- 【clion】自定义优美的代码配色(主题)
- 桌游跑团用roll点器,可以自己设置色字的数量和种类
- 历史上的今天:乔布斯辞去苹果CEO一职;Windows 95 发布
- javascript手册安卓版_javascript手册
- coreldraw矫正两张图_CorelDRAW矫正图像方法-CDR中如何矫正图像_好特教程
- windows11安装微软商店的ubuntu报错,已解决
- k8s 超详细总结,面试必问
- 房屋出租系统(第二版)
- swift转场动画_Swift游乐场的演变
- python3读文件中文_详解Python3解决读取中文文件txt编码的问题
- 模型可视化工具Netron手把手教学
- Redis如何实现多可用区?
- 已声明“ ”,但从未读取其值。ts(6133) 原因及解决方法
- Java基础案例:折纸高于珠穆朗玛峰(while循环)详解