智能灯控(基于ZigBee)

背景:《单片机原理与应用》课程设计

名称:智能灯控

摘要

本系统实现了多方式控灯功能,有按键控灯、串口指令控灯、点对点无线射频控灯、AI模式控灯。其中AI模式控灯是通过红外模块感应外界是否有人靠近来控制灯的亮灭及通过光敏传感器模块感应外界光照强度进而动态调整PWM占空比的输出来控制灯的亮度。

物联网是新一代信息技术的重要组成部分,也是“信息化”时代的重要发展阶段。互联网是物联网个过渡,物联网将成为新时代的发展灵魂。

处于AI时代来临前的我深感可庆,传统的灯控需要大量的布线,若要实现双控、三控及多控更是需要加大用线量,且开关还需要特别定制,及其麻烦,对于远程控制更是不敢想象。

我们将要设计并打造出一款基于ZigBee模块,多传感器,多方式开关,远程智能控制的灯控系统,达到智能照明的节能、环保、舒适、方便的功能。

 

关键词  物联网;智能;控制;LED灯

前言

1.1 系统研究背景

传统的灯控需要大量的布线,若要实现双控、三控及多控更是需要加大用线量,且开关还需要特别定制,及其麻烦,对于远程控制更是不敢想象。

1.2 系统研究的意义和目的

设计并打造出一款基于ZigBee模块,多传感器,多方式开关,远程智能控制的灯控系统,达到智能照明的节能、环保、舒适、方便的功能。

系统概述

2.1 系统的结构

本系统有软件和硬件两部分组成。

软件部分:串口调试助手,控制灯的亮灭、打开和关闭AI模式和实时监测灯的变化情况和日志

硬件部分:两个ZigBee模块,其中控制模块可以控制灯的亮灭和打开和关闭AI模式,被控制模块有人体红外感应模块、光敏传感器和LED发光二极管,其本身按键S1可以控制灯的亮灭,S2按键可以控制AI模式的开和关。AI模式是通过红外感应模块和光敏传感器智能控灯。

                                                            图2.1  系统结构图

2.2  系统的功能

1)按键控灯:开发板按键S1可以控制灯的亮和灭;

2)串口控灯:串口调试助手可发1开灯,和0关灯,控制灯的亮和灭;

3)无线控灯:一对一无线控制灯的开关,安全,可靠,无线发送模块的按键S1为灯控按键;

4)AI模式控灯:智能灯控的核心,AI模式可以感应周围是否有人经过来控制灯的开和关,并且可以根据外界的光照强度来调节自身灯的亮度,达到了节能、环保、舒适的绝佳效果;

5)多方式AI模式开关:本系统提供多方式控制AI模式的开启和关闭,其方式有:按键S2、串口、无线发送模块按键S2;

6)实时信息:串口助手实时上报灯的亮灭情况和当前受到哪方面的控制,如无线开灯时,串口将会显示“----无线开灯成功-----”和“/////AI模式关闭/////”信息,以达到最佳安全级别。

2.3  开发环境

IAR Embedded Workbench微型处理器开发环境

 硬件系统设计

3.1  Zigbee芯片 CC2530

ZigBee是基于IEEE802.15.4标准的低功耗局域网协议。根据国际标准规定,ZigBee技术是一种短距离、低功耗的无线通信技术。这一名称(又称紫蜂协议)来源于蜜蜂的八字舞,由于蜜蜂(bee)是靠飞翔和“嗡嗡”(zig)地抖动翅膀的“舞蹈”来与同伴传递花粉所在方位信息,也就是说蜜蜂依靠这样的方式构成了群体中的通信网络。其特点是近距离、低复杂度、自组织、低功耗、低数据速率。主要适合用于自动控制和远程控制领域,可以嵌入各种设备。简而言之,ZigBee就是一种便宜的,低功耗的近距离无线组网通讯技术。ZigBee是一种低速短距离传输的无线网络协议。ZigBee协议从下到上分别为物理层(PHY)、媒体访问控制层(MAC)、传输层(TL)、网络层(NWK)、应用层(APL)等。其中物理层和媒体访问控制层遵循IEEE 802.15.4标准的规定。

3.2  LED发光二极管

LED发光二极管采用的是2*5*7MM雾状白蓝色发光二极管,二极管的阳极接在ZigBee模块的P1_0引脚,阴极接ZigBee模块的GND引脚。

 

                        图3.1  LED发光二极管实物图

3.3 人体红外感应模块

人体红外感应模块采用的是完整版的HC-SR501人体模块,自动感应,红外感应模块的VCC接在ZigBee模块的5.0vVCC引脚,GND接在ZigBee模块的GND 引脚,out接在ZigBee模块的P1_3引脚。

            

图3.2      人体红外感应模块原理图             图3.3     人体红外感应模块实物图

 3.4 光敏电阻传感器

光敏电阻传感器采用的是4线光敏电阻传感器模块,光敏电阻型号为:5516,本产品使用的是AO模拟量输出,光敏电阻传感器的VCC脚接在ZigBee模块的3.3vVCC引脚,GND接在ZigBee模块的GND引脚,AO接在ZigBee模块的P0_5引脚。

             

图3.4   光敏传感器模块原理图                    图 3.5  光敏传感器模块实物图

软件系统设计

4.1系统整体功能设计

ADC环境光照强度魔术转换;PWM多级调光;多中断智能处理;人体红外感应;无线远距离控制。

                                          图4.1  程序流程图

4.2  AI模式

AI模式可以感应周围是否有人经过来控制灯的开和关,并且可以根据外界的光照强度来调节自身灯的亮度,达到了节能、环保、舒适的绝佳效果。

主函数while(1)循环里,if((boozd==1)&&(P1_3==1))(boozd为AI模式是否允许标志位,P1_3==1表示当前有人经过)成立则会不断获取当前ADC环境光照强度魔术转换后的值,然后用if(){}else if(){}方法与标准区间进行比较,若比较成功将会以当前区间所对应的LED亮度动态调整PWM占空比输出,然后将进行新判断、获取、比较。

 

                                      图 4.2-1

如图 4.2-1,串口调试助手发送 2,收到 CC2530 串口发送的的信息,此时红外人体感应模块和光敏传感器模块两者协调工作,共同控制 LED 灯,也可以通过接收 CC2530 单片机的按键模块的 S2 按键来打开和关闭 AI 模式,也可通过发送CC2530 单片机的按键 S2 来控制 AI 模式的启动与关闭; 

                                      图 4.2-2 

 如图 4.2-2,系统处于 AI 模式时用手握紧光敏传感器模块,让光敏传感器模块处于黑暗的环境下,可见 LED 灯的亮度 

 

                                    图 4.2-3

 如图 4.2-3,系统处于 AI 模式时,打开手机闪光灯靠近光敏传感器模块,可见LED 灯的亮度明显降低,当闪光灯更加接近光敏传感器模块时,LED 灯会熄灭 

4.3 多中断智能处理

本系统包含3大中断处理函数:

1》》串口接收中断处理函数:

#pragma vector=URX0_VECTOR 

__interrupt void urx0(){}

可判断串口接收到的数据,然后进行智能处理,当接收到‘1’时,会以最大亮开灯和关闭AI模式,并且向串口调试助手发送“---串口开灯成功-----”和“----AI模式关闭-----”日志,当收到‘0’时,将向串口发送“/////串口关灯成功////”日志;当收到‘2’时,模块将会利用标志位判断AI模式是否打开,若打开则进行关闭操作,并向串口发送“----AI模式打开-----”日志;当收到其他数据时,模块将向串口将会发送“!!!无该指令!!!”日志。

 

                                          图 4.3-1
如图 4.3-1,串口调试助手发送‘1’,LED 灯会以全亮的形式打开,并关闭AI模式

                                        图 4.3-2

如图 4.3-2,串口调试助手发送‘0’,LED 灯熄灭 (2 按键中断处理函数: 

#pragma vector=P0INT_VECTOR
__interrupt void p0int(){}
模块按键有 S1 和 S2,分别对应的是 ZigBee 模块的 P0_0 和 P0_1 引脚,S1可以控制灯的亮灭,当按键按下且 if(P0IFG&0x01)成立则表示可进入 S1 中断处理函数,函数里将根据标志位状态进行下一步操作,若标志位显示此时灯是灭的,则将会进行开灯功能,并向串口发送相应日志;S2 可以控制 AI 模式的开和关,当按按下且 if(P0IFG&0x02)成立将进入 S2 中断处理函数,函数里将根据标志位状态进行下一步操作,若标志位显示此时 AI 模式已开启,则会进行关闭 AI 模式操作,并先串口发送相应日志。 

 

                                         图 4.3-3
如图 4.3-3,当按下接收 CC2530 单片机的按键模块的 S2 按键,串口调
试助手收到单片机发来的 AI 模式打开的信息,此时 AI 模式正在运行中。

                                      图 4.3-4
如图 4.3-4,当再次按下接收 CC2530 单片机的按键模块的 S2 按键,串口调试助手收到单片机发来的 AI 模式关闭信息,此时 LED 灯熄灭

                                        图 4.3-5
如图 4.3-5,当按下接收 CC2530 单片机的按键模块的 S1 按键,串口调试
助手收到单片机发来的按键开灯成功和 AI 模式关闭信息,此时 LED 最亮显示

                                         图 4.3-6
如图 4.3-6,当再次按下接收 CC2530 单片机的按键模块的 S1 按键,串口调试助手收到单片机发来的 LED 关闭信息,此时 LED 灯熄灭
3》》RF 中断处理函数

#pragma vector=RF_VECTOR __interrupt void x1(){}

 当 ZigBee 模式收到发送模块数据时且 if(RFIRQF0 & 0x40)成立将进入 RF接收处理函数,读取数据包的倒数第 4 和第 3 个有效字节,倒数第 3 位数据对应串口发送‘2’的功能,倒数第 4 位数据对应的是串口发送‘1’的功能 

 

                                          图 4.3-7

如图 4.3-7,当发送 CC2530 单片机模块按下 S1 按键时 ,接受 CC2530 将会进入 RF 中断,并收到“0x0D,0x51,0x88,0x00, 0x07,0x20,0xEF,0xBE,0x20, 0x50,'1','0'” 数据包,经过解析可知是控制灯的亮灭指令,接受单片机模块执行开灯和关闭 AI 模式 

 

                                            图 4.3-8

如图 4.3-8,当发送 CC2530 单片机模块再次按下 S1 按键时 ,接受CC2530 将会再次进入 RF 中断,并再次接收到“0x0D,0x51,0x88,0x00, 0x07,0x20,0xEF,0xBE,0x20, 0x50,'1','0'” 数据包,经过解析可知是控制灯的亮灭指令,接受单片机模块执行关灯操作 

 

                                       图 4.3-9

如图 4.3-9,当发送 CC2530 单片机模块按下 S2 按键时 ,接受 CC2530 将会进入RF 中断,并收到“0x0D,0x51,0x88,0x00,0x07,0x20,0xEF,0xBE,0x20, 0x50,'0','2'” 数据包,经过解析可知是控制 AI 模式的启动与停止指令,接受单片机判断此时 AI 模式是否开启然后继续相反操作。

 

                                     图 4.3-10

 如图 4.3-10,当发送 CC2530 单片机模块再次按下 S2 按键时 ,接受 CC2530将会再次进入 RF 中断,并收到“0x0D,0x51,0x88,0x00,0x07,0x20,0xEF, 0xBE,0x20,0x50,'0','2'” 数据包,经过解析可知是控制 AI 模式的启动与停止指令,接受单片机判断此时 AI 模式是否开启然后进行相反操作。

系统调试

5.1. 系统硬件调试
单个功能一一测试完成后,发现 ZigBee 模块仅有一个 GND 引脚,所以把全
部传感器、二极管等的 GND 引脚一起用 1 根杜邦线引入 ZigBee 模块的 GND 引脚。

 

                              5.1 硬件总体实物图

5.2. 系统软件调试
如何更加准确的知道当前环境的光照情况,明暗变化的光照强度 ADC 变化,可以通过:

char str[30];
sprintf(str,"adc 数值为:%d",adc);
uartTX_Send(str);
在主函数实时发送 ADC 的值到串口调试助手里,获取每个光照阶段里 ADC转换的值,计算 PWM 占空比以达到最佳的调光效果。

相关部分代码

RF收

  1 #include<iocc2530.h>
  2 #include<stdio.h>
  3 #include<string.h>
  4 #include<stdbool.h>
  5 #define LED P1_1
  6 #define uint unsigned int
  7 bool boozd=1;
  8 bool boog=1;
  9 uint pwmx[11]={0x00,0xF7,0xE1,0xC8,0xAF,0x96,0x7D,0x64,0x4B,0x32,0x01};
 10 uint adc;
 11 float adcResu;
 12 void InitLED(){//*****************初始化LED灯
 13 P1SEL &=0xFD;
 14 P1DIR |=0x02;
 15 LED=0;
 16 }
 17 void InitADC(){//********************初始化ADC
 18 P0DIR &=0xDF;//P0_5为输入
 19 APCFG |=0x20;//设置为模拟口
 20 ADCCON3 =0x75;//0011 0101,端口电压,512抽取率,P0_5
 21 adc=0;
 22 ADCH=0;
 23 ADCL=0;//清除ADC数据
 24 ADCCON1=0x30;//停止ADC转换
 25 ADCCON1 |=0x40;//启动ADC转换
 26 }
 27 void Initclock()//*************************************时钟初始化
 28 {//32MHz
 29  SLEEPCMD &=0xFB;//开启全部RC振荡器,避免16MHZRC振荡器被关闭
 30  while((SLEEPSTA&0x40)==0);//等待32MHZ上电稳定
 31  CLKCONCMD &=0xBF;//设置32MHZ为系统时钟源
 32  while(CLKCONSTA&0x40);//等待32MHZ成功成为系统时钟源
 33  CLKCONCMD |=0x38;
 34  CLKCONCMD &=0xF8;//系统时钟不分频输出,定时器为250KHZ
 35  SLEEPCMD |=0x04;//关闭不用的RC振荡器
 36 }
 37 
 38 void InitUart(){//*******************************串口初始化
 39   PERCFG &=0xFE;//将串口0的位置选在P0口
 40   P2DIR &=0x3F; //P0口的外设优先级控制设为串口0优先
 41   P0SEL |=0x0C;//P0口的2、3管脚设为外设工作方式
 42   U0CSR |=0xC0;//USART0工作的UART模式,接收使能
 43   U0UCR=0x02;//据格式为8位数据位、1位停止位、没有校验位
 44   U0GCR |=11;//波特率为115200
 45   U0BAUD |=216;
 46   EA=1;
 47   URX0IE=1;//接收中断打开
 48   UTX0IF=0;
 49   URX0IF=0;
 50  }
 51  void delay(uint i){//*********************延时函数
 52 for(uint j=0;j<i;j++)
 53 for(uint x=0;x<1000;x++);
 54 }
 55 void uartTX_Send(char *strx){//********************串口发送
 56  while(*strx!='\0'){
 57   U0DBUF=*strx;
 58   while((U0CSR&0x02)==0);//等待发送完成
 59    *strx++;
 60    U0CSR &=0xFD;
 61   }
 62 }
 63 void InitTime(){//**********************pwm
 64   //输出比较,P1_0
 65  P1SEL |=0x01;
 66  P1DIR &=0xEE;
 67  PERCFG |=0x40;
 68  P2DIR |=0xC0;//定时器通道2-3最高优先级
 69  T1CTL=0x02;//模模式,0x00-T1CC0!!!!!!!!!!!!!!!!
 70  T1CCTL2=0x1C;
 71  T1CC0H=0x00;
 72  T1CC0L=0xFA;//周期为1ms,频率为1KHZ 必须设置!!!!
 73  T1CC2H=0x00;
 74  T1CC2L=pwmx[0];
 75 //0x00 0xF7 0xE1 0xC8 0xAF 0x96 0x7D 0x64 0x4B 0x32 0x19 
 76 }
 77 void InitButton(){//*******************按键中断初始化
 78 P0SEL &=0xFC;
 79 P0DIR &=0xFC;
 80 P0INP &=0xFC;
 81 P2INP &=0xFC;
 82 PICTL |=0x01;
 83 P0IE=1;
 84 P0IEN |=0x03;
 85 P0IF=0;
 86 P0IFG &=0xFC;
 87 }
 88 void Initho(){//******************************红外感应初始化
 89 //P1_3
 90 P1SEL &=0xF7;
 91 P1DIR &=0xF7;
 92 P1INP &=0xF7;
 93 P2INP |=0x40;
 94 }
 95 void InitWX()//***********************************射频的初始化
 96 {
 97 FRMCTRL0 |=0x60;
 98 TXFILTCFG =0x09;
 99 AGCCTRL1 =0x15;
100 FSCAL1=0x00;
101 
102 RFIRQM0 |=0x40;//打开接收中断
103 IEN2 |=0x01;
104 FREQCTRL=(11+(25-11)*5);// 25号信道可改设置载波为2475M
105 
106 PAN_ID0=0x07;
107 PAN_ID1=0x20;//PAMID
108 
109 RFST=0xEC;//清除接收缓冲器
110 RFST=0xE3;//开启接收使能
111 
112 SHORT_ADDR0=0xEF;
113 SHORT_ADDR1=0xBE;//设置模块网络地址
114 }
115 void main(){
116   InitLED();
117   Initclock();
118   InitUart();
119   InitADC();
120   InitTime();
121   InitButton();
122   Initho();
123   InitWX();
124   boozd=1;
125   boog=1;
126   while(1){
127     if(ADCCON1&0x80){
128     adc |=(ADCL>>2);
129     adc |=(ADCH<<6);
130     if((boozd==1)&&(P1_3==1)){
131         LED=1;
132        if(adc>6191){T1CC2H=0x00;T1CC2L=pwmx[10];}
133        else if(adc>5191){T1CC2H=0x00;T1CC2L=pwmx[8];}
134        else if(adc>4191){T1CC2H=0x00;T1CC2L=pwmx[6];}
135        else if(adc>3191){T1CC2H=0x00;T1CC2L=pwmx[4];}
136        else if(adc>2191){T1CC2H=0x00;T1CC2L=pwmx[2];}
137        if(adc<2191){T1CC2H=0x00;T1CC2L=pwmx[0];}
138     /*  char str[30];
139     sprintf(str,"adc数值为:%d",adc);
140     uartTX_Send(str);*/
141     }else if(boog){
142     LED=0;
143     T1CC2H=0x00;
144     T1CC2L=pwmx[0];
145     }
146     InitADC();//再次启动
147     delay(1000);
148     
149     }
150   }
151 }
152 #pragma vector=URX0_VECTOR
153 __interrupt void urx0(){  //*******************串口中断处理函数
154   
155   char bufch1;
156   bufch1=U0DBUF;
157  if(bufch1=='1')
158  {boog=0;
159   T1CC2H=0x00;
160   T1CC2L=pwmx[10];
161   boozd=0;
162   LED=1;
163   uartTX_Send("\r\n   ----串口开灯成功-----  \r\n");
164    uartTX_Send("\r\n   ----AI模式关闭-----  \r\n");
165 }
166  else if(bufch1=='0')
167 {boog=0;
168 boozd=0;
169   LED=0;
170  T1CC2H=0x00;
171  T1CC2L=pwmx[0];
172  uartTX_Send("\r\n   /////串口关灯成功////  \r\n");
173 }
174  else if(bufch1=='2'){
175    boog=1;
176     LED=1;
177    boozd=1;
178   uartTX_Send("\r\n   ----AI模式打开-----  \r\n");
179  }
180  else 
181 uartTX_Send("\r\n   !!!无该指令!!!  \r\n");
182 
183 
184 }
185 #pragma vector=P0INT_VECTOR//**************按键中断处理函数
186 __interrupt void p0int(){
187   if(P0IFG&0x01){
188    delay(150);
189   if(P0_0==0){
190     boog=0;
191     if(LED==1){
192       LED=0;
193      boozd=0;
194      T1CC2H=0x00;
195      T1CC2L=pwmx[0];
196      uartTX_Send("\r\n   /////按键关灯成功////  \r\n");
197      
198     }else{
199       LED=1;
200       boozd=0;
201   uartTX_Send("\r\n   ----按键开灯成功-----  \r\n");
202   uartTX_Send("\r\n   /////AI模式关闭///// \r\n");
203   T1CC2H=0x00;
204   T1CC2L=pwmx[10];
205     }
206   }
207   }
208   if(P0IFG&0x02){
209    delay(150);
210   if(P0_1==0){
211     boog=1;
212     if(boozd==0){
213       boozd=1;
214       LED=1;
215     uartTX_Send("\r\n   ----AI模式打开-----  \r\n");
216     }else{
217      boozd=0;
218      LED=0;
219     uartTX_Send("\r\n   /////AI模式关闭///// \r\n");
220     }
221     }
222   }
223 P0IF=0;
224 P0IFG &=0xFC;
225 }
226 #pragma vector=RF_VECTOR//******************RF中断处理函数
227 __interrupt void x1()
228 {
229 if(RFIRQF0 & 0x40){
.........

RF发

 1 #include<iocc2530.h>
 2 void Initwx()//********************************射频的初始化
 3 {
 4 EA=0;
 5 FRMCTRL0 |=0x60;
 6 TXFILTCFG =0x09;
 7 AGCCTRL1 =0x15;
 8 FSCAL1=0x00;
 9 
10 RFIRQM0 |=0x40;//打开射频接收中断,应该在下面写接收中断函数
11 IEN2 |=0x01;//RFIE中断开
12 FREQCTRL=(11+(25-11)*5);//设置信道为25则载波为2475M
13 
14 PAN_ID0=0x07;//////PANID
15 PAN_ID1=0x20;//0x2007
16 
17 RFST=0xEC;//清除接收缓冲器
18 RFST=0xE3;//开启接收使能
19 EA=1;
20 }
21 void fa( char *fsj,int len){//************************发送函数
22 RFST=0xEC;//确保接收是空
23 RFST=0xE3;//清接收标志位
24 while(FSMSTAT1 & 0x22);//等待射频发送准备好
25 RFST =0xEE;//确保发送队列为空 
26 RFIRQF1 &=~0x02;//清空发送标志位
27 for(int i=0;i<len;i++){
28   RFD=fsj[i];}
29 RFST=0xE9;//发送缓冲区的数据
30 
31 while(!(RFIRQF1 & 0x02));//等待发送完成
32 RFIRQF1=~0x02;//清发送完成标志
33 }
34 
35 void delay(){//*****************延时函数
36 for(int i=0;i<30;i++)
37 for(int j=0;j<1000;j++);
38 }
39 void go32m()//*************************时钟频率初始化
40 {
41  SLEEPCMD &=0xFB;//开启全部RC振荡器,避免16MHZRC振荡器被关闭
42  while((SLEEPSTA&0x40)==0);//等待32MHZ上电稳定
43  CLKCONCMD &=0xBF;//设置32MHZ为系统时钟源
44  while(CLKCONSTA&0x40);//等待32MHZ成功成为系统时钟源
45  CLKCONCMD |=0x38;
46  CLKCONCMD &=0xF8;//系统时钟不分频输出,定时器为250KHZ
47  SLEEPCMD |=0x04;//关闭不用的RC振荡器
48 }
49 void InitButton()//**************************
50 {
51 P0SEL &=0xFC;
52 P0DIR &=0xFC;
53 P0INP &=0xFC;
54 P2INP &=0xFC;
55 PICTL |=0x01;
56 P0IE=1;
57 P0IEN |=0x03;
58 P0IF=0;
59 P0IFG &=0xFC;
60 }
61 void InitLED(){//***************************************
62 P1SEL &=0xFC;
63 P1DIR |=0x03;
64 P1_0=1;
65 P1_1=1;
66 
67 }
68 void main(){
69 InitLED();
70 go32m();
71 InitButton();
72 Initwx();
73 SHORT_ADDR0=0x50;
74 SHORT_ADDR1=0x20;//设置模块网络地址为0x2050;
.....
posted @ 2019-05-12 00:22  东小东  阅读(10024)  评论(5编辑  收藏  举报