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具体就不详细说明了,看代码即可。具体就不详细说明了,看代码即可。
在这个100Hz中断中进行MQ135采集,10ms采样间隔,然后在中断中进行平均值计算,并给出报警标志。在使用中断过程中又发现了一个问题,就是蜂鸣器报警失效了,这个我之前单独给蜂鸣器写了一个库,最终发现问题应该是arduino函数堆栈问题,这里主函数loop里面调用蜂鸣器库函数,蜂鸣器库函数里面又有delay函数,估计是在这个delay里面再进中断的时候挂掉的,解决的方法也很简单,把这个蜂鸣器库函数去掉封装,直接放到loop函数里面即可。这也进一步说明问题应该是由于arduino函数堆栈大小不够导致的函数入栈或者出栈时出了问题。
这进一步又让我怀疑arduino的中断系统,它是如何处理多个中断的,是否支持中断嵌套,是否有中断队列等等,这个如果写实时性高复杂的代码就需要注意这些问题,后面有时间对现在一些有名的处理器的中断机制做一个总结。
因此就出现了一个问题,我之前的程序里面采用的并非实时监测,而是在每一秒求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的中断系统,它是如何处理多个中断的,是否支持中断嵌套,是否有中断队列等等,这个如果写实时性高复杂的代码就需要注意这些问题,后面有时间对现在一些有名的处理器的中断机制做一个总结。
相关文章推荐
- NGUI使用教程(3) 使用外部图片制作Atlas(图集)
- request.getParameter(“参数名”) 中文乱码解决方法
- 提示框的使用->UIAlertController类的使用
- easyui整理资料
- 对easyui datagrid进行扩展,当滚动条拉直最下面就异步加载数据
- Android开发如何在getContentResolver().query()方法中实现结果去重
- easyui自定义扩展视图实现功能--------datagrid返回记录为0时显示“没有记录”
- iOS错误提示:-[UITextSelectionView chatTextViewTextChange]: unrecognized selector sent to instance 0x7f
- BZOJ 4302(Hdu 5301 Buildings-构造)
- Using platform encoding (GBK actually) to copy filtered resources, i.e. build is platform dependent!
- 【Codeforces】280D k-Maximum Subsequence Sum【区间内k段最大和——线段树模拟费用流】
- 数据库连接池Druid
- 简析Handler、MessageQueue、Looper
- UIViewController的生命周期及iOS程序执行顺序
- 如何更好地限制一个UITextField的输入长度
- UILabel添加中划线、下划线
- 调整UIButton上图片的位置和大小
- 在UITableView顶部制作简单的UISegmentControl实例方法
- dsquery域帐号管理
- iOS UI-(多)视图控制器的生命周期、加载方法和模态视图方法以及屌丝方法