项目描述:
这是funpack第二季第四期活动,我选择的题目是开放题目。
基于AVR64DD32 Curiosity Nano 设计了一套温度监测报警系统。使用TMP235对环境温度进行检测,当温度升高至31℃时,发出报警声。另外配备经典0.96寸显示屏可以显示当前环境温度,同时为了保护OLED屏幕(长时间点亮会老化),使用了一块手势识别模块APDS-9960,实现挥手息屏的效果。
硬件方案介绍:
AVR64DD32 Curiosity Nano 板载资源丰富
- AVR64DD32微控制器
- 一个黄色用户LED
- 一个机械式用户开关
- 一个32.768kHz晶体
- 一个24MHz晶体
- 板载调试器:
- 一个绿色电源及状态指示LED
- 编程和调试
- 虚拟串行端口 (CDC)
- 两个调试GPIO通道 (DGI GPIO)
- USB供电
- 可调目标电压:
- MIC5353 LDO稳压器,由板载调试器控制
- 输出电压范围:1.8V至5.1V(受USB输入电压限制)
- 最大输出电流:500mA(受环境温度和输出电压限制)
功能模块说明
完成以上任务需要用到ADC,IIC,SPI,DAC以及RTC资源。官方给出的核心板IO口定义图十分清晰,根据下图进行模块连接,事半功倍。
温度传感器
TMP235是一款低功耗高精度模拟输出温度传感器,输出电压与温度成正比,测温范围是-40℃-150℃,满足测温要求。需要注意的是参考电压为3.3V.
cli(); //禁止中断
sensorValue = analogRead(temp1);
sei(); //启用中断
temper = (sensorValue*3.3/1024-0.5)*100;
if(temper>=31) //判断温度是否超限
{
DAC_OUT_EN=0x41; //使能DAC报警音输出
}
else if((DAC_OUT_EN==0x41) && (temper<30)) //判断消警条件是否满足
{
DAC_OUT_EN=0x00;
}
OLED显示部分
oled显示屏我是用的是6PIN接口,通讯协议是SPI,驱动IC为SSD1306.
u8g2.clearBuffer(); //清除模组的缓存
u8g2.setFont(u8g2_font_ncenB14_tr); // 设置字体
u8g2.drawStr(0,20,"The temp is:"); // 设置坐标 x=0,y=20 输出内容,0表示最左端
u8g2.setCursor(0,36); // 设置光标位置;
u8g2.print(temper); // 打印温度
u8g2.setCursor(0,52);
u8g2.print(proximity); //距离数据
u8g2.setCursor(64,36);
u8g2.print(0xaa);
u8g2.setCursor(64,52);
u8g2.print(gesture); //手势类别 0-上,1-下,2-左,3-右
u8g2.sendBuffer();
手势识别
APDS-9960是一款环境光和距离手势三合一传感器,通过 I2C 进行数据交互.此处主要用到它的手势识别功能。另外手势识别也可以使用LTR-553-ALS。
if (APDS.proximityAvailable()) {
proximity = APDS.readProximity();
}
// Check if a gesture reading is available
if (APDS.gestureAvailable()) {
gesture = APDS.readGesture();
switch (gesture) {
case GESTURE_UP:
mySerial.println("Detected UP gesture");
break;
case GESTURE_DOWN:
mySerial.println("Detected DOWN gesture");
break;
case GESTURE_LEFT:
mySerial.println("Detected LEFT gesture");
u8g2.clear();
break;
case GESTURE_RIGHT:
mySerial.println("Detected RIGHT gesture");
break;
default:
// Ignore
break;
}
}
报警音输出
声音报警用到了单片机的dac和RTC功能。使用RTC设定一个8KHz的节拍器轮流读取内置正弦波表,输出到IO口,驱动音箱报警。
DAC输出需要配置以下寄存器:
DAC0.DATAH=(main_tone[tone_count])/(main_mask[main_mask_count]); //DAC高8位值写入
DAC0.CTRLA=DAC_OUT_EN; //使能DAC
RTC的初始化如下:
RTC.CLKSEL=0X00; //RTC时钟源选择
RTC.PITCTRLA=0X09; //RTC模式配置 此处配置8.192k
RTC.PITINTCTRL=0X01; //使能中断
RTC.CTRLA=0X01; //打开rtc
RTC中断函数处理
ISR(RTC_PIT_vect) //RTC_PIT_vect由数据手册给出
{
tone_count++; //波表累加器
//DAC0.DATAH=main_tone[tone_count%16]/((tone_count/16)+1);
DAC0.DATAH=(main_tone[tone_count])/(main_mask[main_mask_count]); //输出波表及音量
if(tone_count>=16) //没播出一个正弦波改变音量大小
{
tone_count=0; //波表累加器置零
main_mask_count++; //跳转下一个音量值
if(main_mask_count>=tone_long)
{
main_mask_count=0;
}
}
DAC0.CTRLA=DAC_OUT_EN;
RTC.PITINTFLAGS=0X01; //清除RTC中断标志位
}
报警音频文件的处理此处使用的是内置波表的方法,先使用excel生成一本基础正弦波,提取16个点,得到一列基础波,存入main_tone[16]。然后为了防止音箱出现爆破音,需要对音频做音量渐变处理,此处处理方案是将基础波除以一个系数表main_mask[600]。
存在的问题:
配置完RTC后温度传感器受到了干扰,信号波动较大,问题根源还未确认。
心得体会
官方ide用起来很卡,转而用arduino,但是部分开源的库不支持该芯片,遇到问题需要查datasheet。是有些麻烦,有些挑战性的。