您的位置:首页 > 产品设计 > UI/UE

arduino中断和一些问题

2015-12-28 14:09 573 查看
上次做的arduino小项目在测试过程中发现了一些小问题,至此又引出了一系列问题。大概是这样的,之前检测烟雾传感器使用电位器分压替代的,今天找到了打火机和小木棍就点火实测了一把(好久没玩火了)。测试过程中发现这个MQ135传感器并不是很灵敏,把火苗放在下面传感器测试值升高的很有限(50升到100的样子),而且火灭掉后或者有风吹过测量值很快就下来了,我估计这是和这个传感器所主要测量的气体相关,这个传感器主要是测氨气,一些有机气体和烟雾,可能小木棍燃烧过程中这类气体相对较少。

因此就出现了一个问题,我之前的程序里面采用的并非实时监测,而是在每一秒求100次采集平均值(而且是写死的),这样做主要为了减少虚警,但是如果要提高监测灵敏度的话还是需要增加一个虚警时间阈值的参数,将求平均的时间缩短,实际实现还是增加一个队列存储一段时间的采样数据(虚警时间阈值窗口),然后每次采样的时候求一次平均值。这样的话相当于实时在对烟雾进行检测并且实时检测是否超过阈值需要报警,而且可以通过调整虚警时间阈值这个参数来改变报警的灵敏度。为了实现这个功能就需要用到arduino的中断。幸好arduino是有内部中断的,即便是UNO这个最低的型号,它里面有3个定时器,每一个都可以作为中断,也就是说最多可以同时又三个定时中断,我找到了一篇文章详细的介绍了中断的设置方式,http://www.instructables.com/id/Arduino-Timer-Interrupts/?ALLSTEPS具体就不详细说明了,看代码即可。具体就不详细说明了,看代码即可。

int i = 0;

void setup() {
// initialize serial communications at 9600 bps:
Serial.begin(9600);
cli();//stop interrupts
//set timer1 interrupt at 1Hz
TCCR1A = 0;// set entire TCCR1A register to 0
TCCR1B = 0;// same for TCCR1B
TCNT1  = 0;//initialize counter value to 0
// set compare match register for 1hz increments
OCR1A = 15624;// = (16*10^6) / (1*1024) - 1 (must be <65536)
// turn on CTC mode
TCCR1B |= (1 << WGM12);
// Set CS12 and CS10 bits for 1024 prescaler
TCCR1B |= (1 << CS12) | (1 << CS10);
// enable timer compare interrupt
TIMSK1 |= (1 << OCIE1A);
sei();//allow interrupts
delay(100000);
}

ISR(TIMER1_COMPA_vect){//timer1 interrupt 1Hz toggles pin 13 (LED)
//generates pulse wave of frequency 1Hz/2 = 0.5kHz (takes two cycles for full wave- toggle high then toggle low)
i++;
Serial.println(i);
}

void loop() {
// put your main code here, to run repeatedly:

}


在这个100Hz中断中进行MQ135采集,10ms采样间隔,然后在中断中进行平均值计算,并给出报警标志。在使用中断过程中又发现了一个问题,就是蜂鸣器报警失效了,这个我之前单独给蜂鸣器写了一个库,最终发现问题应该是arduino函数堆栈问题,这里主函数loop里面调用蜂鸣器库函数,蜂鸣器库函数里面又有delay函数,估计是在这个delay里面再进中断的时候挂掉的,解决的方法也很简单,把这个蜂鸣器库函数去掉封装,直接放到loop函数里面即可。这也进一步说明问题应该是由于arduino函数堆栈大小不够导致的函数入栈或者出栈时出了问题。

这进一步又让我怀疑arduino的中断系统,它是如何处理多个中断的,是否支持中断嵌套,是否有中断队列等等,这个如果写实时性高复杂的代码就需要注意这些问题,后面有时间对现在一些有名的处理器的中断机制做一个总结。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: