基于NRF24L01的校园智能路灯初步粗略设计方案.docx
- 文档编号:7382980
- 上传时间:2023-01-23
- 格式:DOCX
- 页数:21
- 大小:906.18KB
基于NRF24L01的校园智能路灯初步粗略设计方案.docx
《基于NRF24L01的校园智能路灯初步粗略设计方案.docx》由会员分享,可在线阅读,更多相关《基于NRF24L01的校园智能路灯初步粗略设计方案.docx(21页珍藏版)》请在冰豆网上搜索。
基于NRF24L01的校园智能路灯初步粗略设计方案
传感器与检测应用设计报告
实验名称:
基于NRF24L01的校园智能路灯课程设计
一.设计名称
基于NRF24L01的校园智能路灯初步粗略设计方案
二.摘要
近年来,低碳生活,节能减排越来越受到国家的大力支持,在校园生活中平均一盏路灯的功率在200W-300W之间,每晚大概需要点亮时长为18:
00--5:
00,粗略的计算会发现每盏路灯的功耗大概在2.2--3.3kW·h,学校大多用电平局一度电在0.55元左右,因此,每晚一盏路灯所产生的电费大概在1.2--1.8元左右,大学校园犹如一个小城市,每个学校的路灯至少上百盏,路灯的数量有的会达到上千盏甚至更多。
这给学校每天的开销带来了一部分没必要的浪费。
节约校园照明用电消耗成为响应国家对于节能号召的重要措施之一。
一般的校园照明系统只是运用普通的声控及光控传感器组成开环的控制系统,其灵活性差,功耗大,不可人为干预。
而市场上闭环控制的照明系统投入资金大,稳定性差,无法在校园中得到推广。
三.设计目的
1.了解NRF24L01的基本通信原理
2.掌握stm32f103芯片的AD转换原理
3.熟练掌握光敏电阻的应用
4.将本学年所学知识进行一次综合汇总
四.设计原理
系统的设计主要有以下四个模块部分:
微控制器STM32,光敏电阻模块,LED照明电路.无线射频模块。
其中光敏电阻模块与LED照明电路组成检测照明部分,主要负责检测外界光的强度,人流高峰期会默认开启普通照明模式,夜间会默认开启节能模式。
微控制器STM32负责收集采集数据,以及AD转换,通过串口向PC机发送消息。
无线射频模块负责向主机传递信息,当从机照明电路出现错误时会触发射频模块发射数据,不同从机对应不同数据。
发送完成结束传输。
1.本设计的设计要求
(1).综合考虑选择是一主多从还是一从多主。
(2).硬件设计上应该考虑到滤波的重要性,结构尽量简单实用,易于实现,使系统电路尽量简单。
(3).软件设计必须要有完善的思路,要充分考虑到各种传感器和无线收发器的时序,做到程序简单,调试方便。
(4).通过软件设计尽量降低无线数据传输的误码率
2.主要硬件介绍
(1).NRF24L01无线模块简介
各管脚如下定义:
8.IRQ7.MISO
6.MOSI5.SCK
4.CSN3.CE
2.VCC1.GND
具体说明:
3.CE芯片的模式控制线。
在CSN为低的情况下,CE协同NRF24L01的CONFIG寄存器共同决定NRF24L01的状态(参照NRF24L01的状态机)。
4.CSN为芯片的片选线CSN为低电平芯片工作
5.SCK为芯片控制的时钟线(SPI时钟)
6.MOSI为芯片控制数据线(Masteroutputslaveinput)主输出从输入
7.MISO芯片控制数据线(Masterinputslaveoutput)主输入从输出
8.IRQ中断信号引脚。
中断时变为低电平,即NRF24L01内部发生中断时IRQ引脚从高电平变为低电平。
引脚会在以下三种情况变低:
TxFIFO发完并且收到ACK(使能ACK情况下)、RxFIFO收到数据、达到最大重发次数。
中断:
nRF24L01的中断引脚(IRQ)为低电平触发,当状态寄存器中TX_DS(数据发送完成中断位)、RX_DR(接收数据中断位)或MAX_RT(达到最多次重发中断位)为高时触发中断。
当MCU给中断源写‘1’时,中断引脚被禁止。
可屏蔽中断可以被IRQ中断屏蔽。
通过设置可屏蔽中断位为高,则中断响应被禁止。
默认状态下所有的中断源是被禁止的。
系统结构框图如下所示
五.设计原理
NRF24L01工作原理
发射数据时,首先将nRF24L01配置为发射模式:
接着把接收节点地址TX_ADDR和有效数据TX_PLD按照时序由SPI口写入nRF24L01缓存区,TX_PLD必须在CSN为低时连续写入,而TX_ADDR在发射时写入一次即可,然后CE置为高电平并保持至少10μs,延迟130μs后发射数据;若自动应答开启,那么nRF24L01在发射数据后立即进入接收模式,接收应答信号(自动应答接收地址应该与接收节点地址TX_ADDR一致)。
如果收到应答,则认为此次通信成功,TX_DS置高,同时TX_PLD从TX FIFO中清除;若未收到应答,则自动重新发射该数据(自动重发已开启),若重发次数(ARC)达到上限,MAX_RT置高,TX FIFO中数据保留以便在次重发;MAX_RT或TX_DS置高时,使IRQ变低,产生中断,通知MCU。
最后发射成功时,若CE为低则nRF24L01进入空闲模式1;若发送堆栈中有数据且CE为高,则进入下一次发射;若发送堆栈中无数据且CE为高,则进入空闲模式2。
接收数据时,首先将nRF24L01配置为接收模式,接着延迟130μs进入接收状态等待数据的到来。
当接收方检测到有效的地址和CRC时,就将数据包存储在RX FIFO中,同时中断标志位RX_DR置高,IRQ变低,产生中断,通知MCU去取数据。
若此时自动应答开启,接收方则同时进入发射状态回传应答信号。
最后接收成功时,若CE变低,则nRF24L01进入空闲模式1。
在写寄存器之前一定要进入待机模式或掉电模式。
如下图,给出SPI操作及时序图:
图2.4SPI读操作
SPI口为同步串行通信接口,最大传输速率为10Mb/s,传输时先传送低位字节,再传送高位字节。
但针对单个字节而言,要先送高位再送低位。
与SPI相关的指令共有8个,使用时这些控制指令由nRF24L01的MOSI输入。
相应的状态和数据信息是从MISO输出给MCU。
nRF24L0l所有的配置字都由配置寄存器定义,这些配置寄存器可通过SPI口访问。
nRF24L01的配置寄存器共有25个,常用的配置寄存器如表2所示。
表2:
常用配置寄存器
地址(H)
寄存器名称
功能
00
CONFIG
设置24L01工作模式
01
EN_AA
设置接收通道及自动应答
02
EN_RXADDR
使能接收通道地址
03
SETUP_AW
设置地址宽度
04
SETUP_RETR
设置自动重发数据时间和次数
07
STATUS
状态寄存器,用来判定工作状态
0A~0F
RX_ADDR_P0~P5
设置接收通道地址
10
TX_ADDR
设置接收接点地址
11~16
RX_PW_P0~P5
设置接收通道的有效数据宽度
六.硬件电路图
(1).NRF24L01原理图
(2).光敏电阻模块原理图
(3).硬件电路连接图
七.程序源码及分析
(1).主机程序
主机程序主要实现
当三个从机中在时间触发的情况下进行AD采集带电压并且返回给主机,主机进行错误判断
一号路灯出现问题时候,主机会通过串口向PC段发送数据,主机端监视助手会进行判断,对应的相应的灯会出现亮灭以及闪烁状态。
以达到提醒维修人员及时检查维修路灯。
程序部分如下所示
//错误检测
NRF_RX_Mode();
printf("Receivemode\r\n");
if(NRF_Rx_Dat(rxbuf)==RX_DR)
;
else
{
printf("接收失败\r\n");
}
//第一个路灯出现问题
if(rxbuf[0]==JC1[0]&&rxbuf[1]==JC1[1]&&rxbuf[2]==JC1[2])
{
bz1=1;
USART_SendData(USART1,0x01);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
printf("出错请检查路灯\r\n");
memcpy(rxbuf,"",12);
printf("%d\r\n",rxbuf[0]);
printf("%d\r\n",rxbuf[1]);
printf("%d\r\n",rxbuf[2]);
}
//第二个路灯出现问题
elseif(rxbuf[0]==JC2[0]&&rxbuf[1]==JC2[1]&&rxbuf[2]==JC2[2])
{
bz2=1;
USART_SendData(USART1,0x02);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
printf("出错请检查路灯\r\n");
memcpy(rxbuf,"",12);
printf("%d\r\n",rxbuf[0]);
printf("%d\r\n",rxbuf[1]);
printf("%d\r\n",rxbuf[2]);
}
//第三个路灯出现问题
elseif(rxbuf[0]==JC3[0]&&rxbuf[1]==JC3[1]&&rxbuf[2]==JC3[2])
{
bz3=1;
USART_SendData(USART1,0x03);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
printf("出错请检查路灯\r\n");
memcpy(rxbuf,"",12);
printf("%d\r\n",rxbuf[0]);
printf("%d\r\n",rxbuf[1]);
printf("%d\r\n",rxbuf[2]);
}
//路灯一和路灯二出现问题
elseif(bz1&&bz2==1)
{
USART_SendData(USART1,0x04);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
bz1=0;
bz2=0;
}
//路灯二和路灯三出现问题
elseif(bz2&&bz3==1)
{
USART_SendData(USART1,0x05);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
bz2=0;
bz3=0;
}
//路灯一和路灯三出现问题
elseif(bz1&&bz3==1)
{
USART_SendData(USART1,0x06);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
bz1=0;
bz3=0;
}
//路灯一.路灯二.路灯三出现问题
elseif(bz1&&bz2&&bz3==1)
{
USART_SendData(USART1,0x07);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
bz1=0;
bz2=0;
bz3=0;
}
else
;
if(rxbuf[0]==JN1[0]&&rxbuf[1]==JN1[1]&&rxbuf[2]==JN1[2])
{
key1=1;
}
if(rxbuf[0]==JN2[0]&&rxbuf[1]==JN2[1]&&rxbuf[2]==JN2[2])
{
key2=1;
}
if(rxbuf[0]==JN3[0]&&rxbuf[1]==JN3[1]&&rxbuf[2]==JN3[2])
{
key3=1;
}
if(key1&&key2&&key3==1)
{
USART_SendData(USART1,0x08);
while(USART_GetFlagStatus(USART1,USART_FLAG_TXE)==RESET);
delay_ms(10);
key1=0;
key2=0;
key3=0;
}
GPIO_SetBits(GPIOB,GPIO_Pin_5);
delay_ms(1000);
/*
*函数名:
SPI_NRF_Init
*描述:
SPI的I/O配置
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidSPI_NRF_Init(void)
{
SPI_InitTypeDefSPI_InitStructure;
GPIO_InitTypeDefGPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOG,ENABLE);//使能PB,G端口时钟
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB,ENABLE);//PORTB时钟使能
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2,ENABLE);//SPI2时钟使能
/*配置SPI_NRF_SPI的SCK,MISO,MOSI引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_AF_PP;//复用功能
GPIO_Init(GPIOB,&GPIO_InitStructure);
/*配置SPI_NRF_SPI的CE引脚和SPI_NRF_SPI的CSN引脚:
NSS*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_6;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP;
GPIO_Init(GPIOG,&GPIO_InitStructure);
/*配置SPI_NRF_SPI的IRQ引脚*/
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_8;
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPU;//上拉输入
GPIO_Init(GPIOG,&GPIO_InitStructure);
/*这是自定义的宏,用于拉高csn引脚,NRF进入空闲状态*/
NRF_CSN_HIGH();
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;//双线全双工
SPI_InitStructure.SPI_Mode=SPI_Mode_Master;//主模式
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b;//数据大小8位
SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low;//时钟极性,空闲时为低
SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge;//第1个边沿有效,上升沿为采样时刻
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft;//NSS信号由软件产生
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_8;//8分频,9MHz
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB;//高位在前
SPI_InitStructure.SPI_CRCPolynomial=7;
SPI_Init(SPI2,&SPI_InitStructure);
/*EnableSPI1*/
SPI_Cmd(SPI2,ENABLE);
}
/*
*函数名:
NRF_RX_Mode
*描述:
配置并进入接收模式
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidNRF_RX_Mode(void)
{
NRF_CE_LOW();
SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自动应答
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);//设置RF通信频率
SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
/*CE拉高,进入接收模式*/
NRF_CE_HIGH();
}
/*
*函数名:
NRF_TX_Mode
*描述:
配置发送模式
*输入:
无
*输出:
无
*调用:
外部调用
*/
voidNRF_TX_Mode(void)
{
NRF_CE_LOW();SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);//写TX节点地址SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//设置TX节点地址,主要为了使能ACK
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自动应答
SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:
500us+86us;最大自动重发次数:
10次
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);//设置RF通道为CHANAL
SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断
/*CE拉高,进入发送模式*/
NRF_CE_HIGH();
delay_ms(20);//CE要拉高一段时间才进入发送模式
}
此处主要设置ADC的初始化,负责电压采集初始
voidADC_Configuration(void)
{
ADC_InitTypeDefADC_InitStructure;
ADC_InitStructure.ADC_Mode=ADC_Mode_Independent;
ADC_InitStructure.ADC_ScanConvMode=DISABLE;
ADC_InitStructure.ADC_ContinuousConvMode=DISABLE;
ADC_InitStructure.ADC_ExternalTrigConv=ADC_ExternalTrigConv_None;
ADC_InitStructure.ADC_DataAlign=ADC_DataAlign_Right;
ADC_InitStructure.ADC_NbrOfChannel=1;
ADC_Init(ADC1,&ADC_InitStructure);
ADC_RegularChannelConfig(ADC1,ADC_Channel_10,1,ADC_SampleTime_239Cycles5);
ADC_Cmd(ADC1,ENABLE);
ADC_ResetCalibration(ADC1);
while(ADC_GetResetCalibrationStatus(ADC1));
ADC_StartCalibration(ADC1);
while(ADC_GetCalibrationStatus(ADC1));
ADC_SoftwareStartConvCmd(ADC1,ENABLE);
}
(2).从机一程序源码
从机一程序即为路灯一控制程序
主要实现功能是:
通过RTC时钟的触发和光敏电阻模块同时触发来触发不同时间的路灯的工作状态。
当通过AD电压检测,检测到路灯处于断路状态时,会触发射频模块向主机发送错误报警数据,及时在主机PC端显示‘
程序如下所示
adcx=Lsens_Get_Val();
printf("%d\r\n",adcx);
//持续轮询自动检测控制通过光敏电阻
//高峰期开启普通模式
//并且向主机返回数据4,5,6
if(adcx<56&&calendar.hour==18&&calendar.min==0&&calendar.sec==0)
{
//普通模式
GPIO_ResetBits(GPIOF,GPIO_Pin_11);
GPIO_ResetBits(GPIOF,GPIO_Pin_12);
GPIO_ResetBits(GPIOF,GPIO_Pin_13);
ad=JC11_Get_Val();
ad12=JC12_Get_Val();
ad13=JC13_Get_Val();
mix11=3.3/4095*ad;
mix12=3.3/4095*ad12;
mix13=3.3/4095*ad13;
delay_ms(600);
printf("ad=%f\r\n",3.3/4095*ad);//实际电压值
printf("ad=%f\r\n",3.3/4095*ad12);//实际电压值
printf("ad=%f\r\n",3.3/4095*ad13);//实际电压值
/
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 基于 NRF24L01 校园 智能 路灯 初步 粗略 设计方案