GREEN HAND(2)--温度报警器

来源:互联网 发布:elsevier旗下数据库 编辑:程序博客网 时间:2024/04/29 17:16

Arduino学习第二篇

——————通过网络解决实际题目来学习arduino

1、题目要求

·改变一个温度传感器的温度,温度与LED灯的亮度成正比例关系;
·温度过高蜂鸣器报警,且红灯亮;温度过低绿灯亮;
·按下复位键后,停止报警,⑤s后温度过高,仍需报警;
·温度恢复正常后,停止报警;
·报警时,报警灯和蜂鸣器按①赫兹闪烁报警;
温度测量范围需要在10~50摄氏度每 80 毫秒测量一次,并刷新显示
报警温度可以自己设定。

器件
温敏电阻&DS18B20芯片

2、任务划分思路

改变一个温度传感器的温度,温度要在四位八段数码管上显示,精确到小数点后②位
1、了解DS18B20芯片和温敏电阻;
2、了解蜂鸣器;
3、分析题目逻辑,将其分为数个小任务;

3、初步构思(温度传感器始终有问题)

#include <DallasTemperature.h>#include <OneWire.h>#include "SevSeg.h"SevSeg sevseg; //Instantiate a seven segment controller object/////////////////////////////////////////////////////////////////////////////////////////////const int High=27;                 //设置上限温度const int Low=1;                  //设置下限温度const int a=3;                    //蜂鸣器的数字引脚const int b=A0;                   //低温绿灯数字引脚const int c=2;                    //开关监测引脚 //const int d=4;                    //温度传感器引脚int temparture=0;                 //蜂鸣器监测温度int tem=0;                        //实时变化温度int now;                          //存储实时时间int past=0;int tem_past=0;int val;                          //存储开关键值#define ONE_WIRE_BUS 4            //定义DS18B20数据口连接arduino的2号IO上///////////////////////////////////////////////////////////////////////////////////////////////初始连接在单总线上的单总线设备OneWire oneWire(ONE_WIRE_BUS);DallasTemperature sensors(&oneWire);/////////////////////////////////////////////////////////////////////////////////////////////int HIGHring(){  if(now-past>=1000)    {      for(int i=0;i<18000;i++)      {        digitalWrite(a, HIGH);        sevseg.refreshDisplay();      }      past=now;      }    else      digitalWrite(a,LOW);}int LOWring(){   if(now-past>=1000)   {      for(int i=0;i<18000;i++)      {        digitalWrite(b, HIGH);        sevseg.refreshDisplay();      }      past=now;    }    else      digitalWrite(b,LOW);}int Res(){  past=now;  while(now-past<=5000)  {     digitalWrite(a, LOW);     digitalWrite(b, LOW);     sevseg.refreshDisplay();     now=millis()/1000;   }}//ucos;//ucos;//ucos;//ucos;一个可以多线程的库;void setup() {  byte numDigits = 2;  byte digitPins[] = {12,13};  byte segmentPins[] = {11,9,6,7,8,10,5,A5};  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins  byte hardwareConfig = COMMON_ANODE; // See README.md for options  bool updateWithDelays = false; // Default. Recommended  bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros    sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments, updateWithDelays, leadingZeros);  sevseg.setBrightness(90);  /////////////////////////////////////////////////////////////////////////////////////////////////////////  pinMode(a, OUTPUT);  pinMode(b, OUTPUT);  //pinMode(d, OUTPUT);  pinMode(c, INPUT);  /////////////////////////////////////////////////////////////////////////////////////////////////////////  sensors.begin();  Serial.begin(57600);}void loop() {/////////////////////  now=millis();  ///////////////////////  tem=millis()/10000;//温度这里是别的队员在做,暂时用这个函数来代表温度的输入    if(now-tem_past>=80)    {        sensors.requestTemperatures(); // 发送命令获取温度        tem=sensors.getTempCByIndex(0);        temparture=tem;        for(int i=1;i<8000;i++)        {          sevseg.setNumber(tem,-1);          sevseg.refreshDisplay();                   }    } ////////////////////  if(temparture>High)     HIGHring();  if(temparture<Low)     LOWring();  val=digitalRead(c);  if(val==HIGH)  {    Res();  }  sevseg.setNumber(tem,-1);  sevseg.refreshDisplay();}/// END ///

//温度显示方案有待解决;使用ONEMIRE以下函数

~sensors.requestTemperatures(); // 发送命令获取温度

~sensors.getTempCByIndex(0)

会无法做到80ms刷新一次并在数码管上显示。

通过http://playground.arduino.cc/Learning/OneWire了解到
Program timing for other functionsArguably the biggest problem with using the above methodology is that unless threading measures are undertaken, the device must sit (hang) and wait for the conversion to take place if a hardcoded wait time is included. This presents a serious problem if other timed processes exist, and even if they don't -- many programs wait for user input, process data, and perform many other functions that cannot be put on hold for the time necessary for a temperature conversion process. As noted above and below, a 12-bit conversion process for a DS18B20 can take as long as 750ms. There is no reason to use the wait method, unless it is desired that the controller do nothing (at all) until the measurement conversion is complete. It is far more efficient to issue a conversion command and return later to pick up the measurement with a Read Scratchpad command once the conversion is complete.Scaling for Poll Speed with multiple devicesAnother major problem with the "Convert, Wait, Read" method is that it scales very poorly, and for no good reason. All conversion commands can be issued in series (or simultaneously, by issuing a Skip ROM and then Convert command), and the result can then be read back in succession. See discussion here: http://interfaceinnovations.org/onewireoptimization.htmlAdjustment of wait time to required conversion timeThe most efficient and expeditious read of 1Wire devices explicitly takes into account the conversion time of the device being read, which is typically a function of read resolution. In the example below, for example, 1000ms is given, while the datasheet lists 750ms as the maximum conversion time, and typical conversion takes place in 625ms or less. Most important, the value should be adjusted for the resolution that is currently being polled. A 9-bit conversion, for example, will take 94ms or less, and waiting for 1000ms simply doesn't make sense. As noted above, the most efficient way to poll is the use a read time slot to poll the device. In this fashion one can know exactly when the result is ready and pick it up immediately.
于是只能从ONEMIRE库的例程DS18x20_temperature部分代码入手
  ds.reset();  ds.select(addr);  ds.write(0x44,1);         // start conversion, with parasite power on at the end    delay(1000);     // maybe 750ms is enough, maybe not  // we might do a ds.depower() here, but the reset will take care of it.    present = ds.reset();  ds.select(addr);      ds.write(0xBE);         // Read Scratchpad  Serial.print("  Data = ");  Serial.print(present,HEX);  Serial.print(" ");  for ( i = 0; i < 9; i++) {           // we need 9 bytes    data[i] = ds.read();

然而问题依旧不知具体如何解决。

4、第一种方案(对LED与温度成正比的解决)

这个想法,是自己用已有的知识,自己写的。可以说,中间波折很多。
#include <DallasTemperature.h>#include <OneWire.h>OneWire  ds(4);  // on pin 10/////////////////////////////////////////////////////////////////////////////////////////////const int High=27;                 //设置上限温度const int Low=27;                  //设置下限温度const int a=3;                    //蜂鸣器的数字引脚const int b=A0;                   //低温绿灯数字引脚const int c=2;                    //开关监测引脚 const int e=11;                   //LED灯呼吸引脚//const int d=4;                    //温度传感器引脚int temparture=0;                 //蜂鸣器监测温度int tem=0;                        //实时变化温度int now;                          //存储实时时间int past=0;int tem_past=0;int ledshine;int val;                          //存储开关键值#define ONE_WIRE_BUS 4            //定义DS18B20数据口连接arduino的2号IO上/////////////////////////////////////////////////////////////////////////////////////////////int GetTem(){  byte i;  byte present = 0;  byte type_s;  byte data[12];  byte addr[8];  float celsius, fahrenheit;  now=millis();  if ( !ds.search(addr)) {    Serial.println("No more addresses.");    Serial.println();      ds.reset_search();    //delay(250);    return;  }  // the first ROM byte indicates which chip      type_s = 0;  ds.reset();  ds.select(addr);  ds.write(0x44,1);         // start conversion, with parasite power on at the end////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  // maybe 750ms is enough, maybe not  // we might do a ds.depower() here, but the reset will take care of it.   present = ds.reset();  ds.select(addr);      ds.write(0xBE);         // Read Scratchpad  for ( i = 0; i < 9; i++) {           // we need 9 bytes    data[i] = ds.read();  }  // convert the data to actual temperature  unsigned int raw = (data[1] << 8) | data[0];    byte cfg = (data[4] & 0x60);    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms    // default is 12 bit resolution, 750 ms conversion time//  }  celsius = (float)raw / 16.0;  tem=(int)celsius;  //Serial.print("  Temperature = ");  //Serial.print(celsius);  //Serial.print(" Celsius, ");;}int HIGHring(){  if(now-past>=1000)    {      for(int i=0;i<18000;i++)      {        digitalWrite(a, HIGH);        ledshine=15+(tem-25)*70;        analogWrite(e,ledshine);      }      past=now;      }    else      digitalWrite(a,LOW);}int LOWring(){   if(now-past>=1000)   {      for(int i=0;i<18000;i++)      {        digitalWrite(b, HIGH);        ledshine=15+(tem-25)*70;        analogWrite(e,ledshine);      }      past=now;    }    else      digitalWrite(b,LOW);}int Res(){  int Res_now=0;  int Res_past=0;  Res_now=millis();  Res_past=Res_now;  Serial.println("循环前");  Serial.println(Res_now);  Serial.println(Res_past);  while(Res_now-Res_past<=5000)  {     digitalWrite(a, LOW);     digitalWrite(b, LOW);     ledshine=15+(tem-25)*70;     analogWrite(e,ledshine);     Res_now=millis();     Serial.println("!!!!!!!!!");      Serial.println(Res_now);     Serial.println(Res_past);  }}   //ucos;void setup() {  // put your setup code here, to run once:    Serial.begin(9600);////////////////////////////////////////////////////////////////////////////////////////////////////////  pinMode(a, OUTPUT);  pinMode(b, OUTPUT);  pinMode(e, OUTPUT);  pinMode(c, INPUT);/////////////////////////////////////////////////////////////////////////////////////////////////////////}void loop() {  // put your main code here, to run repeatedly:  GetTem();  ledshine=15+(tem-25)*70;  analogWrite(e,ledshine);  Serial.println(ledshine);  Serial.println(tem);  if(tem>High)     HIGHring();  if(tem<Low)     LOWring();  val=digitalRead(c);  if(val==HIGH)  {    Res();  }}


第二种方法(调用Timer-Master库,对LED亮度与温度成正比的解决方案)

这种方案,在逻辑上,看起来更加简单。避免了第一种方法中,由于时间差异,一个函数中还要运行比这个函数单位时间小的内容,有很多东西会交叉;、
以下的方法,更简单。
#include <DallasTemperature.h>#include <OneWire.h>#include <Event.h>#include <Timer.h>OneWire  ds(4);  // on pin 10Timer t;/////////////////////////////////////////////////////////////////////////////////////////////const int High=26;                 //设置上限温度const int Low=25;                  //设置下限温度const int a=3;                    //蜂鸣器的数字引脚const int b=A0;                   //低温绿灯数字引脚const int c=2;                    //开关监测引脚 const int e=11;                   //LED灯呼吸引脚int val;                          //存储开关键值int pass_val=0;int tem=0;                        //实时变化温度int ledshine;/////////////////////////////////////////////////////////////////////////////////////////////int Breath(){  Serial.println("Breath here");  ledshine=15+(tem-25)*70;  analogWrite(e,ledshine);}int HighRing(){    Serial.println("High here");    if(pass_val==0)    {      if(tem>High)        {      for(int i=1;i<2000;i++) digitalWrite(a, HIGH);            }    }    digitalWrite(a, LOW);}int LowRing(){      Serial.println("Low here");    if(tem<Low)    {      for(int i=1;i<2000;i++) digitalWrite(b, HIGH);    }    digitalWrite(b,LOW);}int Res(){  Serial.println("Res here");  val=digitalRead(c);  if(val==HIGH)  {    Serial.println("Res true");    digitalWrite(a, LOW);    digitalWrite(b, LOW);    pass_val=1;    t.after(5000,turn);  }}int turn(){  pass_val=0;  Serial.println("!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!");}int GetTem(){byte i;  byte present = 0;  byte type_s;  byte data[12];  byte addr[8];  float celsius, fahrenheit;  if ( !ds.search(addr)) {    Serial.println("No more addresses.");    Serial.println();      ds.reset_search();    //delay(250);    return;  }  // the first ROM byte indicates which chip      type_s = 0;  ds.reset();  ds.select(addr);  ds.write(0x44,1);         // start conversion, with parasite power on at the end////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////  // maybe 750ms is enough, maybe not  // we might do a ds.depower() here, but the reset will take care of it.   present = ds.reset();  ds.select(addr);      ds.write(0xBE);         // Read Scratchpad  for ( i = 0; i < 9; i++) {           // we need 9 bytes    data[i] = ds.read();  }  // convert the data to actual temperature  unsigned int raw = (data[1] << 8) | data[0];    byte cfg = (data[4] & 0x60);    if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms    else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms    else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms    // default is 12 bit resolution, 750 ms conversion time//  }  celsius = (float)raw / 16.0;  tem=(int)celsius;  //Serial.print("  Temperature = ");  Serial.print("                                   ");  Serial.println(tem);  //Serial.print(" Celsius, ");;}void setup() {  // put your setup code here, to run once:  Serial.begin(9600);////////////////////////////////////////////////////////////////////////////////////////////////////////  t.every(800,GetTem);  t.every(50,Breath);  t.every(1000,HighRing);  t.every(1000,LowRing);  t.every(50,Res);////////////////////////////////////////////////////////////////////////////////////////////////////////  pinMode(a, OUTPUT);  pinMode(b, OUTPUT);  pinMode(e, OUTPUT);  pinMode(c, INPUT);/////////////////////////////////////////////////////////////////////////////////////////////////////////}void loop() {  // put your main code here, to run repeatedly:  t.update();}

第二种方法(调用TaskScheduler库,对LED亮度与温度成正比的解决方案)



#include <TaskScheduler.h>#include <DallasTemperature.h>#include <OneWire.h>OneWire  ds(12);  //温度传感器数字引脚/////////////////////////////////////////////////////////////////////////////////////////////  const int High=27;                //设置上限温度  const int Low=26;                 //设置下限温度 const int buzzer=4;               //蜂鸣器的数字引脚 const int a=3;                    //高温红灯的数字引脚  const int b=5;                    //低温绿灯数字引脚  const int c=13;                   //开关监测引脚   const int e=6;                    //LED灯呼吸引脚  int val;                          //存储开关键值  int pass_val=0;                   //控制5s关闭蜂鸣器int tem=30;                       //实时变化温度  int ledshine;                     //与温度成正比的LED亮度int t=0;                          //t++=200则达到5s/////////////////////////////////////////////////////////////////////////////////////////////  void GetTemCallback();           //得到温度void HIGHringCallback();         //高温警报void LOWringCallback();          //低温警报void ResCallback();              //按钮响应及5s关闭蜂鸣器void LEDCallback();              //与温度成正比的LED亮度//TasksTask GetTem(800, TASK_FOREVER, &GetTemCallback);Task HIGHring(1000, TASK_FOREVER, &HIGHringCallback);Task LOWring(1000, TASK_FOREVER, &LOWringCallback);Task LED(400, TASK_FOREVER, &LEDCallback);Task Res(50, TASK_FOREVER, &ResCallback);Scheduler runner;void GetTemCallback()  {    byte i;    byte present = 0;    byte type_s;    byte data[12];    byte addr[8];    float celsius, fahrenheit;      if ( !ds.search(addr)) {        ds.reset_search();       return;    }      // the first ROM byte indicates which chip        type_s = 0;    ds.reset();    ds.select(addr);    ds.write(0x44,1);         // start conversion, with parasite power on at the end                /////////////////////////////////            /////////////////////////////////  // maybe 750ms is enough, maybe not    // we might do a ds.depower() here, but the reset will take care of it.     present = ds.reset();    ds.select(addr);        ds.write(0xBE);         // Read Scratchpad      for ( i = 0; i < 9; i++) {           // we need 9 bytes      data[i] = ds.read();      }      // convert the data to actual temperature      unsigned int raw = (data[1] << 8) | data[0];        byte cfg = (data[4] & 0x60);      if (cfg == 0x00) raw = raw << 3;  // 9 bit resolution, 93.75 ms      else if (cfg == 0x20) raw = raw << 2; // 10 bit res, 187.5 ms      else if (cfg == 0x40) raw = raw << 1; // 11 bit res, 375 ms      // default is 12 bit resolution, 750 ms conversion time  //  }    celsius = (float)raw / 16.0;    tem=(int)celsius;  }  void HIGHringCallback()  {       if(tem>High)        {        for(int i=1;i<500;i++)       {        digitalWrite(a, HIGH);         if(pass_val==0) digitalWrite(buzzer, HIGH);             }    }        digitalWrite(a, LOW);    digitalWrite(buzzer,LOW);        }  void LOWringCallback()  {       if(tem<Low)      {        for(int i=1;i<500;i++) digitalWrite(b, HIGH);      }      digitalWrite(b,LOW);  } void LEDCallback()  {     ledshine=15+(tem-25)*70;    analogWrite(e,ledshine);} void ResCallback()  {     val=digitalRead(c);    if(val==HIGH)    {        digitalWrite(a, LOW);      digitalWrite(b, LOW);      pass_val=1;        }    if(pass_val==1)  {    t++;    if(t==99)    {      t=0;       pass_val=0;          }  }}  void setup() {  Serial.begin(9600);//////////////////////////////////////  runner.addTask(GetTem);;    runner.addTask(HIGHring);  runner.addTask(LOWring);    runner.addTask(Res);   runner.addTask(LED);    GetTem.enable();  HIGHring.enable();  LOWring.enable();  Res.enable();  LED.enable();//////////////////////////////////////  pinMode(a, OUTPUT);    pinMode(b, OUTPUT);    pinMode(e, OUTPUT);  pinMode(buzzer,OUTPUT);  pinMode(c, INPUT);  }void loop() {  // put your main code here, to run repeatedly:  runner.execute();}

完成!
1 0
原创粉丝点击