1.项目需求
设计一个环境监测系统,利用热敏电阻和光传感器监测温度和光强的变化。结合输入、输出拓展版,使用彩色LCD显示实时数据,并结合LED和RGB LED以不同颜色表示不同的环境条件。通过按键选择监测模式,电位计调整LED亮度和颜色变化速率。
2.功能展示
2.1温度光强自动监测模式
彩色LCD实时显示当前环境的温度和光强,以及LED的亮度和变化速度;拓展板红绿蓝三色LED显示当前温度光强变化(代码设定温度光强阈值,高于最大值时显示红色,低于最小值时显示蓝色,介于中间时显示率色);通过按下电位计可以实现亮度和速度参数的选择,通过两个按键可以调节LED亮度和速度的大小。图1图2演示不同温度光强下的显示图样。
图1.自动模式下LCD显示
图2.温度高于最大值且光强低于最小值(LED红蓝混合),LED亮度为160时
图3.LED亮度值为360时
2.2温度光强手动监测模式
显示方式同自动模式。手动模式下,温度光强不会实时变化,只有当电位计旋钮向右旋转时,才会显示当前时刻的温度和光强。
图4.手动模式显示
2.3温度自动监测模式
该模式下LCD只显示当前温度,LED也只根据温度变化而变化。
图5.温度自动监测模式下显示
2.4光强自动监测模式
该模式下LCD只显示当前光强值,LED也只根据光强变化而变化。
图6.光强自动监测模式下显示
3.实现思路
- 拓展板LED亮度和变化速度通过MSPM0L输出PWM波控制
- 温度通过板卡上自带的热敏电阻电路输出电压,经过ADC转换带入公式计算得到
- 光强通过光传感器电路连接OPA电路,输出的电压经过ADC转换得到
- LCD通过I2C协议点亮并显示数据
- 拓展板按键通过板卡ADC采样获取不同状态
4.实现过程
4.1程序流程图
4.2电路图
MSPM0L通过杜邦线与输入输出拓展板的MSP430接口连接
4.3初始化
初始化包括板卡的初始化和LCD的初始化。本次实验需要两个PWM控制RGB三个LED灯;一个定时器0作为事件触发ADC转换;ADC采取序列重复转换,存储温度、光照和按键数字信号;LCD库函数根据提供外设的LCD型号获得,更改相关引脚参数即可。
4.4ADC采样记录结果
通过中断记录温度传感器、拓展板按键和光传感电路输出电压。
void ADC_INST_IRQHandler(void)
{
switch (DL_ADC12_getPendingInterrupt(ADC_INST)) {
case DL_ADC12_IIDX_MEM2_RESULT_LOADED:
gThermistorADCResult1 =
DL_ADC12_getMemResult(ADC_INST, DL_ADC12_MEM_IDX_0);
temperature=internal_temperature_sensor_calc(gThermistorADCResult1);
gCheckThermistor = true;
gThermistorADCResult2=DL_ADC12_getMemResult(ADC_INST, DL_ADC12_MEM_IDX_1);
External_ADC=gThermistorADCResult2;
gLightsensorADCResult=DL_ADC12_getMemResult(ADC_INST, DL_ADC12_MEM_IDX_2);
illumination=gLightsensorADCResult;
gCheckLightsensor=true;
NVIC_DisableIRQ(ADC_INST_INT_IRQN);
break;
default:
break;
}
}
由于板卡没有提供工厂校准温度传感器电压VTRIM,因此需要自己标定,这里采用的是该帖子(TI MSPM0L1306 LaunchPad体验08:内部温度传感器出厂校准误差有200多摄氏度? - MSPM0 MCU - 电子工程世界-论坛 (eeworld.com.cn))提供的标定电压值。
其中温度计算函数如下:
float internal_temperature_sensor_calc(uint16_t adc_code) {
float TSc = -1.75e-3;
float TStrim = 30;
float Vref = 1.4;
uint16_t TEMP_SENSE0=1867;
float Vsample = (Vref / 4096) * (adc_code - 0.5);
float Vtrim = (Vref / 4096) * (TEMP_SENSE0 - 0.5);
float Tsample = (1 / TSc) * (Vsample - Vtrim) + TStrim;
return Tsample;
}
4.5按键识别
拓展板不同按键按下会产生不同的电压输出,电压输出经过ADC转换变成数字信号,根据数字信号判断此时按键状态。因此需要对按键电压进行标定。
if ((External_ADC > 1700)&&(External_ADC<1900)){
key2=1;
check=0;
}
else if((External_ADC>2600)&&(External_ADC<2900)){
key1=1;
check=0;
}
else if((External_ADC>3100)&&(External_ADC<3300)){
press=1;
check=0;
}
else if((External_ADC>=3500)&&(External_ADC<3600)){
spin_left=1;
check=0;
}
else if((External_ADC>=3600)&&(External_ADC<3700)){
spin_right=1;
check=0;
}
else if(External_ADC>3700){
check=0;
}
4.6模式菜单与切换
按下电位计改变光标位置,进而通过按键实现亮度或速度的增减;通过左旋电位计实现切换菜单功能。
if(press==1){
cursor=!cursor;
}
if(cursor==0){
//调节pwm//
LCD_ShowChar(80,60,'>',RED,WHITE,12,0);
LCD_ShowChar(80,80,' ',RED,WHITE,12,0);
if(key1){
pwm+=10;
}
if(key2){
pwm-=10;
}
if(pwm>500){
pwm=500;
}
if(pwm<-10){
pwm=-10;
}
}
if(cursor==1){
//调节速度//
LCD_ShowChar(80,80,'>',RED,WHITE,12,0);
LCD_ShowChar(80,60,' ',RED,WHITE,12,0);
if(key1){
speed+=1;
}
if(key2){
speed-=1;
}
if(speed>10){
speed=10;
}
if(speed<0){
speed=0;
}
}
这里实现按下一次key1(上键)pwm加10,LED变亮或速度加1;按下一次key2(下键)pwm减10,LED变暗或速度减1。
5.难点
本次项目主要难点
- 温度传感器初始参数的标定,由于系统未提供具体数值,只能通过手动标定计算获得。
- LCD的驱动库函数大部分都是适配stm32等单片机,需要稍作修改以适配MSPM0L系列的MCU。
- 初次接触单片机,对I2C等并不清楚,MSPM0L系列单片机的资料较少,学习时需要自己搜集并研读相关资料。
- 多次使用到ADC转换,对ADC的内部工作逻辑需要掌握清楚。
- 第一次使用CCS软件并自学C语言,学习量较大。
- CCS内置的图形配置工具需要从头学习,将其与理论知识结合起来。
- 首次实现利用按键控制菜单功能,相关代码编写难度较大。
- 单片机的时钟种类繁杂,不同外设需要配置不同时钟。
6.改进
本项目最大问题在于按键功能的实现,经多次实验发现电位计旋转时,MCU读取ADC转换并不灵敏,经常发生旋转电位器但无事发生的情况,这也致使自己放弃使用电位计改变LED亮度和变化速度,转而使用按键控制,电位计则是左旋改变模式,右旋在手动模式下用来更新数值。此外,在控制LED变化速度部分的代码还有改进空间,或许可以利用定时器中断等方式实现,但由于对定时器掌握不精,未能实现,这也致使在代码中被迫采用循环的方式进行延时。