1.引言
1.1课题背景
随着经济的高度发展,人们对所处的生活环境的要求也越来越高。我国的申
奥主题就有“绿色奥运”之说。本项目的研究就是基于人们生存的光环境的“绿色”所开展的。紧扣能源节约与健康的主题。
能源与健康是当代社会的几大热门话题之一。节约能源,已经迫在眉睫。环顾我们的周围,能源浪费现象十分严重。就拿我们十分熟悉的校园来说,大家肯定都留心到了这些现象:教室时常是不分白昼黑夜的亮着灯;宿舍断电时,我们常常忘了关掉电源。等到再次来电时,我们又常常不在宿舍,此时灯却依旧亮着,而当时的光线常常不需要开灯。这样不仅浪费电,而且也会缩短灯泡的寿命;另外,我们有时会因光线不好而开灯,可过了一会儿,当光线好起来时,我们又因手头的事不能停下而无法去关灯,这样也导致了能源的浪费。
不良的光源会在不知不觉中对眼睛造成伤害。太强或太弱的光对眼睛都是有害的。大量研究表明学生的近视和长期应用不科学照明光源有直接关系。所以一个好的光环境尤为重要。
鉴于以上的分析,我们设计了这个便携式的灯光控制调节系统,它与灯泡相连便构成光控电灯。它的意义在于:使用者可通过自己设置的光强通过本系统使室内达到恒定的光强。即达到了节能的目的,又有保护视力的效果。
1.2课题研究的意义
在家居、工作、学习的各个环境中,我们所使用的光源均为固定瓦数的,提供固定光强的电灯。我们计划研制的灯光调节器,能够为人们提供“绿色光源”。我们查阅了大量的资料,结果发现目前市面上还没有此种灯。有些人也研制了一些调节灯,如http://eae.seu.edu.cn/vote1/htm/A13.asp(东南大学电工电子试验中心)网页上所介绍的调节灯仅能人为手动调节亮度,再附上几个比较器组成的光感报警系统,来提醒人们室内光强超出允许范围,我们研制的调节器能真正意义上的达到自动调节光强的目的。此灯通过传感器采集的光强来控制灯泡的亮度,使室内达到了稳定的光强,此恒定光强也可通过外设键盘自主设定,既减少了经常开关灯的不便,又解决了浪费电能与影响视力的问题。此灯成本不高,可在办公室图书馆等公共场合使用。使人们生活的光环境的质量有了大大的提高,使人们生
84
活在由自己随心所欲控制的光环境下,满足了工作、 学习及家居对光的要求。
1.3课题研究的目的
(1) 通过动手实践巩固所学的知识体系,将理论与实践相结合,更好的理 解书本上的知识。
(2) 通过查询相关的课外资料,掌握更加系统的知识体系,开拓视野。 (3) 在相互协作制作的同时,增强了我们的团队精神。知道怎样分工协作 才能达到最高效率。
2.课题方案的设计
本课题研究的主要内容是如何采光与如何控光。
2.1光检方案:
方案一:图1所示为英文资料上推荐的光检电路,我们对该电路进行了测试,测试结果如下:
图1
实验条件:Rf=470K,V+=3.33V,采用60W的可调台灯照明,台灯亮度从最暗调整到最亮。
实验数据:光检电路的输出电压变动范围-0.03------250mV,电路电流为520uA。
实验结论:输出电压不稳定,而且电压太小,无法实现控制。经过计算,将电路参数Rf调整为5M左右,电路输出电压将近3V,但输出电压稳定度下降。
方案二:图2为经过改进的电路
85
图2
测试条件与方案一相同。
测量结果:电路输出电压范围为0.04V---3.52V,达到设计要求,电压稳定性也比第一种方案好。
通过以上两个试验的测试,决定采用第二种方案。
2.2灯控方案:
方案一:图3所示方案为采用可控硅调节灯泡的电压,从而调节了灯的亮度。
图3
方案二:图4所示方案采用CMOS管和光耦来调节灯泡的电压。
86
图4
通过对上述两种方案的具体测试,我们发现用可控硅的光控电路控制灯泡时出现闪烁现象。第二种方案在同等控制输入信号频率下,电路工作稳定,灯泡无闪烁现象。分析原因在于第一种方案中可控硅的开关速度达不到设计要求,因而出现闪烁现象。
2.3单片机的选择 方案一:采用C51单片机
采用C51单片机,容易编程,但外围硬件接口电路的设计较复杂。 方案二:采用美国TI公司MSP430系列单片机
美国TI公司的MSP430系列单片机,内置模块功能较强,接口电路简易,可通过编程直接产生PWM信号,方便地控制灯的亮度。
MSP430系列单片机简介:
TI公司的MSP430系列是一个特别强调超低功耗的单片机品种。在这个系列中有多个型号,他们是由一些基本功能模块按不同的应用目标组合而成的。
特性功能:
1.定时器中断可用于事件计数、时序发生、PWM等
2.A/D转换器(10位或更高精度)有8个输入端,可作为恒流源 3.具有LCD驱动电路 4.已开发了c-编译器
87
5.系统内置模块:LCD驱动、A/D转换、I/O端口、UART、看门狗、定时器、EPROM等
6.64KB公共空间中,有可能实现任意的ROM/RAM混合分配 八位脉宽调制定时器PWM介绍:
用8位定时器计数器,PWM外围模块产生一个占空比可以是0%~100%的方波输出。占空比由8位占空比控制寄存器PWMDT来确定。 PWM定时器模块具有以下特性:
1.可选择8个时钟源;
2.占空比为0%~100%,分辨率为1/254; 3.可以用正或负逻辑输出。
基于课题的设计要求,我们所选用的单片机是MSP430系列的448型号。
3.硬件电路设计
3.1系统原理框图
电源蜂鸣器亮度检测MSP430F44X单片机图5
PWM亮度控制LCD显示 按键输入
系统原理框图如图5所示,主要包含六个部分: (1)电源部分
88
图6
(2)光检电路
图7
(3)光控电路
图8
89
(4)单片机电路
图9
(5)按键电路
图10
90
(6)蜂鸣器电路
4.1初始化流程图
图11
4.软件流程图开始初始化IO口初始化系统时钟初始化LCD显示初始化PWM周期初始化AD转换器结束图12
91
4.2系统流程图
开始A初始化比设定值大 增加PWM占空比读取亮度等级减小PWM占空比读取显示标志键盘程序AD采样LCD显示A结束 图13
4.3键盘处理子程序框图
开始按键处理存储状态值结束 图14
92
5.课题研究成果介绍
5.1作品面板展示
图15
5.2作品操作方法介绍
本作品将光强分为了十个级别,1#、2#、3#键为快捷键。 1#键为亮,相当于第十级。 2#键为次亮,相当于第五级。 3#键为暗,相当于第三级。 4#键为级别上升控制键。
5#键为级别下降控制键。按动4#键、5#键,光亮便可以一级一级的变动。 6#键为显示切换键。按动此键可使液晶的显示值分别显示PWM占空比、光亮等级和采集电压值。
93
5.3本作品的使用环境
本品是220V电压供电。可采用一个箱体控制灯的光强,也可将多个箱体分散放置于室内以获得较均衡的光强。
6.前景展望
本作品净成本为300——400元,若产品化批量生产,成本可降为100元以内,如果将所使用的单片机换成同系列的较低级的亦可实现本功能,虽然功能扩展难以实现,但成本可降到更低。这样如果将其商品化,既可以用于公共场所,亦可用于家居。它的价值不仅在于节省的电能,而且可以保护人们的视力,这一点是用价钱无法衡量的。
由于本系统所使用的单片机性能好,可扩展许多功能,所以本作品有继续开发的价值,最终可将其作为一个智能家电控制系统使用。
7.心得体会
经过近一年的长时间努力,我们小组终于完成了这个课题,回想这一过程,真是感受颇多。
自从2003年9月份组队申报项目开始,到现在完成课题,我们小组的三个人邵慧敏、贾妍妍、刘明宇都为之付出了艰辛的努力。从方案论证,硬件电路设计到软件设计,工作量都非常大,而且我们只有业余时间可以利用。如果我们不能很好的分工合作,是不可能完成这项课题的。
我们的小组是由两名大二学生和一名经验丰富的大三学生组成,由于知识上的欠缺,我们在刚刚开始研究课题的时候,由大三的同学刘明宇指导我们在图书馆以及网上查阅下载了相当多的有关资料和一些必备的基本知识。经过了一段时间的学习积累,我们对这个课题有了更为深入地了解。于是我们共同进入了方案的研制测试阶段。我们集中在一起讨论,商定最终的方案,确定硬件电路,软件编程。在这个课题中我们所使用单片机MSP430*448是比较新的产品,我们从来都没有使用过,而且有关的资料很多都是英文,但是这并没有阻碍我们前进的步伐,我们克服重重困难,在实践中积累经验,掌握了这种单片机的基本应用方法,并且成功的将它应用到我们的课题之中。
通过本次活动,我们拓宽了思路,开阔了视野,从中学到了许多课本上没有的知识,为以后进入实验室进行更深入的研究奠定了基础。与此同时,我们还学会了许多解决实际问题的方法,巩固了我们所学的基础知识,将课本上的知识与
94
实践结合起来,加强了我们的动手能力。
团队合作的精神在这一过程中也得到了充分的展示。我们相互讨论,分工明确,互相帮助,有条不紊的对方案进行修进和调试。一年的时间,我们一起经历风雨,在讨论中互相学习,在失意中相互鼓励,在协作中增强友谊。这种经历无疑将成为我们在今后走向社会时的一种宝贵的财富。可以毫不愧言的说:我们的团队是一个团结,高效,友爱的团队。
8.参考文献及单片机源程序
8.1参考文献:
《MSP430系列16位单片机原理与应用》 胡大可主编 北京航空航天大学出版社 2000.6
《MSP430 Family User’s Guide》 美国TI公司资料 8.2单片机源程序:
#include //*********************************************************************** void delay(unsigned long i) { while(i--); } //*********************************************************************** unsigned char input3(unsigned char bit) { } 95 unsigned char temp1; temp1=P3DIR; //读取A口原来的方向属性 //设置要设置的位为输入 P3DIR=temp1&(0xff-(1< void output2(unsigned char bit,unsigned char value) { unsigned char temp1,temp2/*,temp3*/; temp1=P2DIR; temp2=P2IN; //save the value before //读取A口原来的方向属性 //读取A口原来的数据 P2DIR=temp1|(1< default:break; }//end switch }// end output2 //*********************************************************************** float Vchange(unsigned int in_res) { float i; i=(float)((3.3*in_res)/4095.0); return(i); } //*********************************************************************** void pwminit() { TACTL = ID1+ID0+TASSEL1 + TACLR; // SMCLK, Clear Tar CCR0 = 4096; // PWM Period CCTL2 = OUTMOD_7; // CCR2 reset/set CCR2 = 18; // CCR2 PWM duty cycle P2DIR |= 0x01; // P2.0 output P2SEL |= 0x01; // P2.0 TA2 otion TACTL |= MC0; // Start Timer_A in up mode } 96 //*********************************************************************** void usext2(void) { SCFQCTL=0x00; // mudulation enable, and muliplier=0 // if DCOPLUS=0:fDCOCLK=(N+1)*fCRYSTAL else *D SCFI0=0x04; // DCO Range 1.4-12M FLL_CTL0=0x80; // not divided FLL_CTL1=0x14; // use xt2,MCLK=xt2,SMCLK=xt2 } //*********************************************************************** char *LCD = LCDMEM; char dig_dp[4]={0x00,0x00,0x00,0x10}; char dig[10][4]={{0x11,0x11,0x11,0x00}, // 0 {0x10,0x01,0x00,0x00}, // 1 {0x11,0x10,0x01,0x01}, // 2 {0x11,0x11,0x00,0x01}, // 3 {0x10,0x01,0x10,0x01}, // 4 {0x01,0x11,0x10,0x01}, // 5 {0x01,0x11,0x11,0x01}, // 6 {0x11,0x01,0x00,0x00}, // 7 {0x11,0x11,0x11,0x01}, // 8 {0x11,0x11,0x10,0x01} // 9 }; //*********************************************************** void LCDsegmentON(unsigned char control) { switch(control) { case 0:LCDCTL&=0xff-LCDSON;break; case 1:LCDCTL|=LCDSON;break; default:break; 97 } } //*********************************************************** void selectLCDfre(unsigned char level) { switch(level) { case 1: BTCTL&=0xff-(BTFRFQ1+BTFRFQ0);break; case 2: BTCTL&=0xff-(BTFRFQ1);BTCTL|=(BTFRFQ0);break; case 3: BTCTL&=0xff-(BTFRFQ0);BTCTL|=(BTFRFQ1);break; case 4: BTCTL|=(BTFRFQ1+BTFRFQ0);break; default:break; } } //*********************************************************************** #pragma vector=BASICTIMER_VECTOR __interrupt void basic_timer(void) { //P5OUT ^= 0x02; // Toggle P5.1 using exclusive-OR unsigned char i; for(i=0;i<4;i++) { LCD[i+15]=dig[4][i]; } i=i; } #pragma vector=PORT1_VECTOR __interrupt void port1(void) { //P5OUT ^= 0x02; // Toggle P5.1 using exclusive-OR 98 unsigned char i; for(i=0;i<4;i++) { LCD[i+15]=dig[3][i]; } i=i; } static unsigned int results[4]; //*********************************************************************** void write_flash_init(void) { WDTCTL = WDTPW + WDTHOLD; // Stop watchdog timer FCTL2 = FWKEY + FSSEL0 + FN0; // MCLK/2 for Flash Timing Generator } unsigned char read_SegA_byte(unsigned char address) { char *Flash_ptr; // Flash pointer Flash_ptr = (char *) 0x1080; // Initialize Flash pointer write_flash_init(); return(*(Flash_ptr+address)); // Write value to flash } void write_SegA_byte(unsigned char address,unsigned char value) { char *Flash_ptr; // Flash pointer write_flash_init(); Flash_ptr = (char *) 0x1080; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *Flash_ptr = 0; // Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; // Set WRT bit for write operation *(Flash_ptr+address) = value; // Write value to flash 99 FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Reset LOCK bit } void write_SegA (char value) { char *Flash_ptr; // Flash pointer unsigned int i; write_flash_init(); Flash_ptr = (char *) 0x1080; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *Flash_ptr = 0; // Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; // Set WRT bit for write operation for (i=0; i<128; i++) { *Flash_ptr++ = value; } FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Reset LOCK bit } // segB unsigned char read_SegB_byte(unsigned char address) { char *Flash_ptr; // Flash pointer Flash_ptr = (char *) 0x1000; // Initialize Flash pointer write_flash_init(); return(*(Flash_ptr+address)); // Write value to flash } void readsegBtobuffer(void) { char *Flash_ptr; unsigned char i; Flash_ptr=(char *) 0x1000; write_flash_init(); for(i=0;i<128;i++) 100 { flashbuffer[i]=*(Flash_ptr+i); } } void write_SegB_byte(unsigned char address,unsigned char value) { unsigned char i; char *Flash_ptr; // Flash pointer write_flash_init(); readsegBtobuffer(); Flash_ptr = (char *) 0x1000; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *Flash_ptr = 0; // Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; // Set WRT bit for write operation flashbuffer[address]=value; for (i=0; i<128; i++) { *(Flash_ptr+i) = flashbuffer[i]; // Write value to flash } FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Reset LOCK bit } void write_SegB (char value) { char *Flash_ptr; // Flash pointer unsigned int i; write_flash_init(); Flash_ptr = (char *) 0x1000; // Initialize Flash pointer FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *Flash_ptr = 0; // Dummy write to erase Flash segment FCTL1 = FWKEY + WRT; // Set WRT bit for write operation for (i=0; i<128; i++) 101 { *Flash_ptr++ = value; // Write value to flash } FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Reset LOCK bit } //*********************************************************************** void main(void) { float set=0.6; float step=0.08; int j; float a; unsigned char i=0,k; unsigned char displaymode; set=read_SegB_byte(0x05)/10.0; displaymode=read_SegB_byte(0x06); WDTCTL = WDTPW+WDTHOLD; // Stop watchdog timer P6SEL = 0xff; // Enable A/D channel inputs set sampling time ADC12CTL0 = ADC12ON+MSC+SHT0_2; // Turn on ADC12, set sampling time ADC12CTL1 = SHP+CONSEQ_1; // Use sampling timer, single sequence ADC12MCTL0 = INCH_3; // ref+=AVcc, channel = A0 ADC12MCTL1 = INCH_4; // ref+=AVcc, channel = A1 ADC12MCTL2 = INCH_5; // ref+=AVcc, channel = A2 ADC12MCTL3 = INCH_6+EOS; // ref+=AVcc, channel = A3, end seq. ADC12IE = 0x08; // Enable ADC12IFG.3 ADC12CTL0 |= ENC; // Enable conversions ADC12CTL0 |= ADC12SC; // Start conversion LCDCTL = 0xe5; //static LCD, segments = 0 - 23 BTCTL = BTFRFQ1+BTFRFQ0; // BTCTL ;set fLCD = ACLK / 256 BTFRFQ1 for (i=0; i<20; i++) { LCD[i] = 0; } 102 usext2(); pwminit(); CCR2=1000; while(1) { if((ADC12IFG&0x08)!=0) { results[0] = ADC12MEM0; results[1] = ADC12MEM1; results[2] = ADC12MEM2; results[3] = ADC12MEM3; a=Vchange(results[0])+Vchange(results[1])+Vchange(results[2])+Vchange(results[3])/4.0; //bright #define delayvalue 50000 #define max 5.0 if(!input3(0)) { output2(7,1); while(!input3(0)); output2(7,0); delay(delayvalue); set=max; write_SegB_byte(0x05,(unsigned char)(set*10)); } // mid if(!input3(1)) { output2(7,1); while(!input3(1)); output2(7,0); delay(delayvalue); set=max/2.0; //write_flash_init(); write_SegB_byte(0x05,(unsigned char)(set*10)); } 103 // dark if(!input3(2)) { output2(7,1); while(!input3(2)); output2(7,0); delay(delayvalue); set=max/3.0; //write_flash_init(); write_SegB_byte(0x05,(unsigned char)(set*10)); } // up if(!input3(3)) { output2(7,1); while(!input3(3)); output2(7,0); delay(delayvalue); set+=max/10; if(set>max) { set=max; } write_SegB_byte(0x05,(unsigned char)(set*10)); } // down if(!input3(4)) { output2(7,1); while(!input3(4)); output2(7,0); delay(delayvalue); set-=max/10; if(set<=max/10) { set=max/10; } write_SegB_byte(0x05,(unsigned char)(set*10)); 104 } // dis if(!input3(5)) { output2(7,1); while(!input3(5)); output2(7,0); delay(delayvalue); displaymode++; if(displaymode>3) { displaymode=1; } write_SegB_byte(0x06,displaymode); } if(a>=set+step) { CCR2--; if(CCR2<=1) { CCR2=1; } } if(a<=set-step) { CCR2++; if(CCR2>=4096) { CCR2=4096; } } switch(displaymode) { case 1: // CCR2 { for(i=0;i<4;i++) { LCD[i+7]=dig[CCR2/1000%10][i]; for(i=0;i<4;i++) { LCD[i+11]=dig[CCR2/100%10][i]; for(i=0;i<4;i++) 105 } } { LCD[i+15]=dig[CCR2/10%10][i]; } } break; case 2: // voltage { for(i=0;i<4;i++) { LCD[i+7]=dig[(int)a%10][i]+dig_dp[i]; } for(i=0;i<4;i++) { LCD[i+11]=dig[(int)(a*10)%10][i]; } for(i=0;i<4;i++) { LCD[i+15]=dig[(int)(a*100)%10][i]; } break; case 3: // class { if(set==max) // if not '0' dispaly { for(i=0;i<4;i++) { LCD[i+7]=dig[(unsigned char) ((set*10/max)/10)][i]; } } else // else do not display { for(i=0;i<4;i++) { LCD[i+7]=0; } } for(i=0;i<4;i++) { LCD[i+11]=dig[(((unsigned char)((set*10)/max))%10)][i]; } for(i=0;i<4;i++) { LCD[i+15]=0; } } break; default:break; ; 106 } }// end of switch delay(1000); ADC12CTL0 |= ADC12SC; } } WDTCTL = WDTPW + WDTHOLD; // stop watchdog timer LCDCTL = 0xe5; // static LCD, segments = 0 - 23 BTCTL = BTFRFQ1+BTFRFQ0; // BTCTL ;set fLCD = ACLK / 256 BTFRFQ1 // set up ports // P1DIR = 0xFF; // set port to outputs P2DIR = 0xFF; // set port to outputs P3DIR = 0xFF; // set port to outputs P4DIR = 0xFF; // set port to outputs P5DIR = 0xFF; // set port to outputs P6DIR = 0xFF; // set port to outputs P1DIR = 0x22; // P1.1 & P1.5 to output direction P1SEL = 0x22; // P1.1 & P1.5 to output MCLK & ACLK for (i=0; i<20; i++) { LCD[i] = 0; } WDTCTL = WDTPW +WDTHOLD; // Stop WDT usext2(); pwminit(); j=11; while(1) { if(j==11) { CCR2++; if(CCR2>=1024) { j=22; } } if(j==22) { CCR2--; 107 if(CCR2<=0) { j=11; } } for(i=0;i<4;i++) { LCD[i+15]=dig[CCR2/100][i]; } delay(2000); } while(1) { for(k=1;k<=4;k++) { selectLCDfre(k); for(j=0;j<=9;j++) { for(i=0;i<4;i++) { LCD[i+15]=dig[j][i]; CCR2=100*j; delay(100000); }// light up for(j=9;j>=0;j--) { for(i=0;i<4;i++) { LCD[i+15]=dig[j][i]; CCR2=100*j; delay(100000); }// light down } } } } 108 } 因篇幅问题不能全部显示,请点此查看更多更全内容