基于Robei:环境光传感器实验设计(及L298N模块控制LED灯板)

摘要:最近在做FPGA视觉机器人,考虑到晚上机器人视线不好,萌发了给机器人做一个小型灯补光的想法。咱是机器人肯定要整点智能的对不对,思来想去觉得环境光传感器是个不错的选择。

嘿嘿,行动派往往都是说做就做,从不拖拉。

首先查阅资料:
AP3216C是一个能够测量环境光强度和距离的整合型光感测距传感器。因其功耗低、控制简单、封装小而广泛应用于智能手机、电容式触摸屏、数码相机等领域。例如应用于智能手机上面检测环境光强度,用来实现自动背光控制,以及接近开关控制(听筒靠近耳朵,手机自动灭屏功能)。

:因为它是一种整合型多功能传感器,这种类型的传感器一般都会多种有不同的工作模式(AP3216C内部有一些寄存器,这些寄存器可以控制AP3216C的工作模式、中断方式以及采集数据等。):
在这里插入图片描述
这么多模式,我们选择ALS+PS+IR模式,在该模式下AP3216C连续采集环境光照强度和距离值。上表中,地址0X00对应的是一个系统模式控制寄存器,我们在初始化的时候将它配置为011,这样就能开启ALS+PS+IR模式。其他6个寄存器我们用来存储采集到的数据(红外光强度、环境光强度、以及距离值)。AP3216C采用I2C总线协议与控制器(FPGA)进行通信,因此我们通过I2C协议实现对AP3216C
相关寄存器的配置和采集数据的读取。

接下来上某宝淘材料:

L298N驱动模块一个,LED灯若干,洞洞板一块,焊接成3*3的电灯板,建议焊接成并联电路,这样就不需要为电压不足而烦恼啦:
在这里插入图片描述
电路连接:将电灯板的正极接到驱动模块的OUT2,负极接到OUT1,驱动模块使能端口以及IN2接到开发板的两个排针(想用哪个排针在程序定义就好),通过改变这两个端口的逻辑,我们可以实现对LED进行亮灭。在这里有个点要提一下,驱动模块只有与开发板共地才能使用,很多初学的朋友会问,怎么共地,一般的驱动模块都是会有一个模块用电输入,和一个开发板供电的(5v的正负极,你只要把这个端口的GND接到开发板的GND就行了)。但是也有特殊情况,就是一些比较小的驱动模块是没有一个独立的开发板供电端口的,像我这个模块,比较小,所以他的用电输入与开发板供电是在一起的(3个口,+5V,GND,+12V),像我图片中圈中这样,这个时候你就要从GND这个口中多分出一条线,接到开发板上,另一条接电源的GND:

在这里插入图片描述
AP3216C环境光传感器:因为我的开发板自带了一个环境光传感器,所以无需另接。传感器里面集成了数字环境光传感器(Ambilent Light Sensor,ALS)、距离传感器(Proximity Sensor,PS)和一个红外LED(Infrared Radiation LED,IR LED)。
在这里插入图片描述

接下来就是程序设计
FPGA通过IIC总线读取AP3216C采集的环境光,通过判断环境光光照强度值(als_data)控制LED灯亮灭。从而实现白天夜晚LED灯自动开关的功能。(另外通过ps_data的值可以测试感光器与物体距离远近) 注:(想看Robei程序代码的点这个链接,我已经将整个Robei生成的工程上传!!!)
在这里插入图片描述
在上面的工程中,我并没有设计测距效果模块,如果需要想要看看测距效果如何的朋友,new一个模块就好了。代码如下:

//led灯亮灭个数(4个)显示数据大小(距离的远近),这里的led灯不是焊接板的灯,而是开发板上的灯,可自调
always @(posedge clk or negedge rst_n) begin
    if(rst_n == 1'b0) begin
        led <=  4'd0;
    end
    else if(data < 10'd16)   //这里的data例化的时候连接ap3216c模块的PS_data端口就行
        led <= 4'b0001;
    else if(data < 10'd128)
        led <= 4'b0011;
    else if(data < 10'd512)
        led <= 4'b0111;
    else     
        led <= 4'b1111;
end

考虑到下载文件不方便,我将核心模块ap3216c模块Verilog代码放在这里:

module ap3216c(    
	clk,         //ap3216c模块主要用来测量环境光照强度和距离值
	rst_n,
	i2c_data_r,
	i2c_done,
	i2c_rh_wl,
	i2c_exec,
	i2c_addr,
	i2c_data_w,
	als_data,
	ps_data);

	//---Ports declearation: generated by Robei---
	input clk;
	input rst_n;
	input [7:0] i2c_data_r;
	input i2c_done;
	output i2c_rh_wl;
	output i2c_exec;
	output [15:0] i2c_addr;
	output [7:0] i2c_data_w;
	output [15:0] als_data;
	output [9:0] ps_data;

	wire clk;
	wire rst_n;
	wire [7:0] i2c_data_r;
	wire i2c_done;
	reg i2c_rh_wl;
	reg i2c_exec;
	reg [15:0] i2c_addr;
	reg [7:0] i2c_data_w;
	reg [15:0] als_data;
	reg [9:0] ps_data;

	//----Code starts here: integrated by Robei-----
	parameter      TIME_PS   = 14'd12_500  ;  // PS转换时间为12.5ms(clk = 1MHz)
	parameter      TIME_ALS  = 17'd100_000 ;  // ALS转换时间为100ms(clk = 1MHz)
	parameter      TIME_REST =  8'd2       ;  // 停止后重新开始的时间间隔控制
	
	//reg define
	reg   [ 3:0]   flow_cnt   ;               // 状态流控制
	reg   [18:0]   wait_cnt   ;               // 计数等待
	reg   [15:0]   als_data_t ;               // ALS的临时数据
	reg            als_done   ;               // 环境光照强度值采集完成信号
	reg   [ 9:0]   ps_data_t  ;               // PS的临时数据
	reg            ir_of      ;               // 溢出标志(判断ps_data是否有效)
	reg            obj        ;               // 物体状态标志(0远离1靠近)
	
	
	
	//配置AP3216C并读取数据
	always @(posedge clk or negedge rst_n) begin
	    if(!rst_n) begin
	        i2c_exec   <=  1'b0;
	        i2c_addr   <=  8'd0;
	        i2c_rh_wl  <=  1'b0;
	        i2c_data_w <=  8'h0;
	        flow_cnt   <=  4'd0;
	        wait_cnt   <= 18'd0;
	        ps_data    <= 10'd0;
	        ps_data_t  <= 10'd0;
	        ir_of      <=  1'b0;
	        obj        <=  1'b0;
	        als_done   <=  1'b0;
	        als_data_t <= 16'd0;
	    end
	    else begin
	        i2c_exec <= 1'b0;
	        case(flow_cnt)
	            //初始化AP3216C
	            4'd0: begin
	                if(wait_cnt == 18'd100) begin
	                    wait_cnt <= 18'd0;
	                    flow_cnt <= flow_cnt + 1'b1;
	                end
	                else
	                    wait_cnt <= wait_cnt +1'b1;
	            end
	            //配置AP3216C的功能模式
	            4'd1: begin
	                i2c_exec   <= 1'b1 ;
	                i2c_rh_wl  <= 1'b0 ;
	                i2c_addr   <= 8'h00;               // 配置系统寄存器
	                i2c_data_w <= 8'h03;               // 激活ALS+PS+IR 功能
	                flow_cnt   <= flow_cnt + 1'b1;
	            end
	            //配置完成
	            4'd2: begin
	                if(i2c_done)
	                    flow_cnt <= flow_cnt + 1'b1;
	            end
	            //等待PS转换完成(12.5ms)
	            4'd3: begin
	                if(wait_cnt  == TIME_PS) begin
	                    wait_cnt <= 18'd0;
	                    flow_cnt <= flow_cnt + 1'd1;
	                end
	                else
	                    wait_cnt <= wait_cnt + 1'b1;
	            end
	            //预读PS Data Register(0x0E)
	            4'd4: begin
	                i2c_exec <= 1'b1;
	                i2c_rh_wl<= 1'b1;
	                i2c_addr <= 8'h0E;
	                flow_cnt <= flow_cnt + 1'b1;
	            end
	            //读PS Data Register(0x0E)
	            4'd5: begin
	                if(i2c_done) begin
	                    flow_cnt     <= flow_cnt + 1'b1;
	                    ps_data_t[3:0] <= i2c_data_r[3:0];
	                    ir_of        <= i2c_data_r[6]  ;
	                    obj          <= i2c_data_r[7]  ;
	                end
	            end
	            //等待一段时间以进行下一次读写
	            4'd6: begin
	                if(wait_cnt == TIME_REST) begin//TIME_REST
	                    wait_cnt <= 18'd0;
	                    flow_cnt <= flow_cnt + 1'b1;
	                end
	                else
	                    wait_cnt <= wait_cnt +1'b1;
	            end
	            //预读PS Data Register(0x0F)
	            4'd7: begin
	                i2c_exec <= 1'b1;
	                i2c_rh_wl<= 1'b1;
	                i2c_addr <= 8'h0F;
	                flow_cnt <= flow_cnt + 1'b1;
	            end
	            //读PS Data Register(0x0F)
	            4'd8: begin
	                if(i2c_done) begin
	                    flow_cnt     <= flow_cnt + 1'b1;
	                    ps_data_t[9:4] <= i2c_data_r[5:0];
	                    ir_of        <= i2c_data_r[6]  ;
	                    obj          <= i2c_data_r[7]  ;
	                end
	            end
	            //等待ALS转换完成(100ms)
	            4'd9: begin
	                if(wait_cnt  ==  TIME_ALS) begin
	                    wait_cnt <= 18'd0;
	                    flow_cnt <= flow_cnt + 1'd1;
	                          ps_data  <= ps_data_t;
	                end
	                else
	                    wait_cnt <= wait_cnt + 1'b1;
	            end
	            //预读ALS Data Register(0x0C)
	            4'd10: begin
	                i2c_exec <= 1'b1;
	                i2c_rh_wl<= 1'b1;
	                i2c_addr <= 8'h0C;
	                flow_cnt <= flow_cnt + 1'b1;
	            end
	            //读ALS Data Register(0x0C)
	            4'd11: begin
	                if(i2c_done) begin
	                    als_done        <= 1'b0;
	                    als_data_t[7:0] <= i2c_data_r;
	                    flow_cnt        <= flow_cnt + 1'b1;
	                end
	            end
	            //等待一段时间以进行下一次读写
	            4'd12: begin
	                if(wait_cnt == TIME_REST) begin
	                    wait_cnt <= 18'd0;
	                    flow_cnt <= flow_cnt + 1'b1;
	                end
	                else
	                    wait_cnt <= wait_cnt +1'b1;
	            end
	            //预读ALS Data Register(0x0D)
	            4'd13: begin
	                i2c_exec <= 1'b1;
	                i2c_rh_wl<= 1'b1;
	                i2c_addr <= 8'h0D;
	                flow_cnt <= flow_cnt + 1'b1;
	            end
	            //读ALS Data Register(0x0D)
	            4'd14: begin
	                if(i2c_done) begin
	                    als_done         <= 1'b1;
	                    als_data_t[15:8] <= i2c_data_r;
	                    flow_cnt         <= 4'd3;             //跳转到状态3重新读取数据
	                end
	            end
	        endcase
	    end
	end
	
	//当采集的环境光转换成光照强度(单位:lux)
	always @ (*) begin
	    if(als_done)
		 als_data = als_data_t * 6'd35 / 7'd100;
	end
endmodule    //ap3216c

接下来将程序下载到开发板上来看一下实验效果:
注:因为我是在白天做这个实验,没有黑暗环境做实验条件,所以将开发板放抽屉里面,用手遮住传感器上方,这样模拟一下夜晚环境。

FPGA环境光传感器实验

扫描二维码关注公众号,回复: 11881708 查看本文章

猜你喜欢

转载自blog.csdn.net/weixin_46423500/article/details/107289091