发 帖  
[创意DIY] 基于Arduino 一个完整的DIY气象站 包含代码
2018-5-10 20:56:35  1441 Arduino
分享

这个项目在我把好友放入搜索空间后不久就开始了。现在,在您开始吓唬并呼吁执法之前,我的“Crawlspace Buddy”在室外有4个温度传感器--1个关键位置的爬网空间。当温度变得太低时,用这些读数来控制辅助加热器,以防止我110岁的房子里冻住管子。还有一个安装在托梁上的超声波距离传感器,用于测量发生淹水时的水位。那个项目重新点燃了建立我自己的气象站的长期梦想。现在它已经变得相当复杂的系统,有3个独立的微控制器进行通信,并最终将数据发送到互联网。

我开始使用我现有的DHT22温度/湿度传感器和Arduino Nano(我记录中,我并不是DHT传感器的忠实粉丝,并且最终会升级)。然后我制作了一个“Tipping斗“雨量计,紧接着一个风速计。风速计和雨量计都使用霍尔效应传感器和磁铁进行检测。我还增加了气压模块和实时时钟。接下来,我制作了一个通风箱,以容纳DHT和气象站电路,并将其全部安装在离我家大约100英尺的围栏上。所有数据仅在此阶段通过蓝牙发送到我的手机,所以我还添加了一个RF发射器(433Mhz)。





气象站传感器









气象站电路 - 纳米,RTC模块,气压模块安装在原板上。









“倾翻斗”雨量计机制




然后我建立了数据接收器。我使用了超外差射频接收器模块,为它建了一个抛物面天线,并将它连接到我桌上已有的Arduino MEGA类型的板上,监控我的“Crawlspace Buddy”,并解析/处理数据。我在那时决定,MEGA将成为我计划的几个家庭监测项目的数据/控制中心。MEGA在下面的照片中,埋在MEGA原始屏蔽下,以及安装在UNO屏蔽上的LCD。





显示Crawlspace Buddy Temps-室外,炉子,杂物间和厨房的MEGA









所示的抛物面天线板不是我目前使用的超外差射频接收器




最后,我需要实施项目链中的最后一环 - 将其连接到互联网,这样我就可以在世界任何地方监视我家的天气,因为......好的,谁不需要这种能力?在用ESP8266模块和分线板几个无用的时间后,我咨询了Arduino论坛,并决定寻找一个单独的基于ESP8266的开发板。根据我读过的几篇文章,我决定NodeMCU制作的一块电路板听起来就像是我的最佳选择,并且在亚马逊的搜索中发现了一个包含NodeMCU ESP8266电路板,DHT11温度/湿度传感器以及a.96的“气象站工具包” “OLED显示屏,它将从”Weather Underground“中检索天气和预报数据,从时间服务器获取正确时间,然后将温度和湿度读数从DHT发送到” 并将必要的代码添加到NodeMCU程序中。每10分钟一次,它从MEGA收到一份数据摘要,并将其提交到“Thingspeak”网站。这里是我的公共频道与我的实时天气数据的链接。 https://thingspeak.com/channels/463187





Weatherpeak上显示天气数据









NodeMCU ESP8266物联网天气设备/气象站网络接口




正如任何复杂项目的典型情况一样,在开发过程中必须解决一些问题。对于这个项目项目来说,室外电台的电源是一个主要问题。我正在使用3.7v 18650型电池(2)为监控站供电。我最终希望纳入太阳能充电,但那会晚一些。目前,我只是监测电压,并在需要时更换电池。我有几套,所以我总是保持一套收费。这些电池已被证明具有大致线性的工作范围,用于在满充电时施加8.4伏的电压,以7.4伏放电,电压以更快的速率开始下降。我使用降压转换器将其降至系统调节的5v,并且这5伏也通过OptoMOS继电器连接到升压调节器的输入端以输出9。6v到发射机。此供应仅在每分钟实际传输一次数据包期间打开。(每个数据包发送2次以防止数据丢失,因为这只是单向RF链路。)为了最大限度地延长电池寿命,我还实现了睡眠/节能,将电阻器与Nano上的LED断开连接并消除板上监管机构,因为我正在向董事会交付受监管的5。这使得我的功耗在节电模式下降至约11毫安,正常工作时降至16毫安,在射频传输期间降至约24毫安。由于风速和雨量读数都是由中断产生的,为了保持风速测量的准确性,Nano只有在风速计没有输入脉冲10秒的情况下才进入省电模式。有了这个当前的设置,在我必须更换它们之前,我会在充满电的电池组上使用约48-60小时。风对潜在的电池寿命有显着的影响,因此范围很广。

这个项目已经用了大约3个月的时间,并且可能还需要几个月才能完全实施。我想添加一个风向标来监测风向。时间允许时发布原理图和代码。哦,还有“Rube Goldberg”头衔的原因?我的儿子称这个气象站为“疯狂的装置”,它确实是一个电路/设备的大杂烩,所以这个名字似乎很适合。另一个“功能”,虽然我很少打开由于大量电流消耗,是一套紫外线LED。他们照在风速计上,一杯风速计涂上绿色荧光漆。晚上打开时,你会看到一个绿色的光球来回摆动。这样做的目的是为了给邻居和路人一些想法!











Arduino的数据接收器代码
#include  <AltSoftSerial.h>

#include  <Adafruit_Sensor.h>
#include  <VirtualWire.h>

#include  <OneWire.h>
#include  <Da​​llasTemperature.h>
#include  <LiquidCrystal.h>

#define TIMEOUT 5000
// SoftwareSerial dataSerial(39,38); // RX,TX const int rs = 2 ,en = 3 ,d4 = 4 ,d5 = 5 ,d6 = 6 ,d7 = 7 ; const String THINGSPEAK_API_WRITE_KEY = “PWLOULJXD5GO8RWP” ; LiquidCrystal lcd (rs ,en ,d4 ,d5 ,d6 ,d7 ); INT



                  
   
      
alarmLevel  =  7000 ;
int  devCount ;
int  swPin  =  11 ;
int  RlyPin  =  8 ;
const  int  receive_pin  =  9 ; //针对来自发射器在
天井中的
天气数据的RF接收器的引脚// bool OKtoPost;
bool  HeatControl ;    // ON状态表示温度控制处于活动状态
bool  SuspendData ;
浮动 t1 , t2 , t3 , t4 ;
/ ******************* ******************* /
//数据线插入到Arduino的引脚12
#define ONE_WIRE_BUS 12
/ ************* ************************************************** ***** / /
设置一个oneWire实例与任何OneWire设备进行通信
//(不仅仅是Maxim / Dallas温度IC)
OneWire  oneWire (ONE_WIRE_BUS );
/ ******************* ******************* /
//将我们的oneWire参考传递给Dallas Temperature。
DallasTemperature  传感器(&oneWire );
/ ******************* ******************* /
DeviceAddress Probe01 = { 0x28, 0xFF, 0x67, 0x18, 0x23, 0x17, 0x04, 0xBF }; //Outdoor Sensor
DeviceAddress Probe02 = { 0x28, 0xFF, 0xF5, 0x22, 0x23, 0x17, 0x04, 0xD8 }; //Under Stairs Sensor
DeviceAddress Probe03 = { 0x28, 0xFF, 0xA9, 0xE7, 0x22, 0x17, 0x04, 0x7F }; // Utility Room
DeviceAddress Probe04 = { 0x28, 0xFF, 0x7D, 0x18, 0x23, 0x17, 0x04, 0x7E };// Under Kitchen

long delayMS;
long OutdoorTrig = 25; // Trigger Relay if outdoor temp is below
long OutdoorCut = 26; // Cutoff Relay if outdoor temp is above
long SinkTrig = 35;
long SinkCut = 38;

struct package
{
  float temperature = 0;
  float humidity = 0;
  float barometer = 0;
  byte wind = 0;
  byte maxWind = 0;
  byte windPacketPeak = 0;
  float rain = 0;
  float rainRate = 0;
  float randDate = 0;
  float randTime = 0;
  float battery = 0;
  long packetID = 0;
  float CKSum = 1;
};


typedef struct package Package;
Package data;
Package lastData;

struct postingPackage{
  float temperature = 0;
  float barometer = 0;
  float humidity = 0;
  uint8_t avgWind = 0;
  uint8_t peakWindThisRead = 0;
  float rainThisRead = 0;
  float rainRate = 0;
  float battV = 0;
};

typedef struct postingPackage PostingPackage;

PostingPackage dataToPost;

bool wxMode;

void setup() {
  pinMode(13, OUTPUT);
  pinMode(RlyPin, OUTPUT);
  pinMode(swPin, INPUT);
  Serial.begin(115200);
  Serial1.begin(57600);
  HeatControl = false;
  SuspendData = false;
  //OKtoPost = false;// becomes true after first temperature readings
  
  //Serial.println("Dallas Temperature IC Control Library Demo");
  // Start up the library
  sensors.begin();
  lcd.begin(16, 2);
  // Print a message to the LCD.
  lcd.print("Pipe Protector 2");
  lcd.setCursor(0, 1);
  devCount = sensors.getDeviceCount();
  Serial.print("Device Count: ");
  Serial.println(devCount);
  delayMS = 60000;// WIll increase to 60000 ms when finished. One reading per minute is plenty
  randomSeed(analogRead(0));
  vw_set_rx_pin(receive_pin);
  vw_setup(2000);   // Bits per sec
  vw_rx_start();       // Start the receiver PLL running
  wxMode = true;// for now, we'll start in weather mode
  //lastData.

  //sensors.requestTemperatures();
}// End Setup

void stateSwitch(void) {
  /* if(delayMS >=50000){
     delayMS=10000;
    }
    else{
     delayMS=60000;
    }*/
}

bool SuspendToggle(void) {
  SuspendData = !SuspendData;
  return (SuspendData);

}

void sendStatus(void) {
  String myStr;// Variable to hold all values as text string for sending over serial port
  myStr = OutdoorTrig;
  myStr.concat(",");
  myStr.concat(OutdoorCut);
  myStr.concat(",");
  myStr.concat(SinkTrig);
  myStr.concat(",");
  myStr.concat(SinkCut);
  myStr.concat(",");
  myStr.concat(delayMS);
  myStr.concat(",");
  myStr.concat(HeatControl);
  myStr.concat(",");
  myStr.concat(SuspendData);
  Serial.println(myStr);
}




int HighestTemp() {
  int retVal;
  for (int cnt = 0; cnt < devCount; cnt++) {
    //int trVal = GetFTempDec(cnt);
    int trVal = sensors.getTempFByIndex(cnt);
    if (cnt == 0) {

      retVal = trVal;
    }
    //Serial.println(sensors.getTempFByIndex(cnt));

    if (retVal < trVal) {
      retVal = trVal;
    }
  }
  // checkRange(retVal);
  return (retVal);
}

float LowestTemp() {
  float retVal;
  for (int cnt = 0; cnt < devCount; cnt++) {
    //int trVal = GetFTempDec(cnt);
    int trVal = sensors.getTempFByIndex(cnt);
    if (cnt == 0) {

      retVal = trVal;
    }
    //Serial.println(sensors.getTempFByIndex(cnt));

    if (retVal > trVal) {
      retVal = trVal;
    }
  }
  //  checkRange(retVal);
  return (retVal);
}

float printTemperature(DeviceAddress deviceAddress)
{

  float retVal = sensors.getTempF(deviceAddress);

  if (retVal == -196.60)
  {
    Serial.print(F("<Error>"));
  }
  else
  {


    Serial.print(retVal);

    Serial.print(F(" F "));
    return (retVal);
    //Serial.print(DallasTemperature::toFahrenheit(tempC));
  }
}// End printTemperature

void serial1Check(){
String myCmd;

  if(Serial1.available() > 0){
   Serial.println("You are there");
       myCmd = Serial1.readString();
    Serial.println(myCmd);
      
  }
  Serial.println("You ARE LEAVING!!");
}

void serialCheck(){
  if (Serial.available() >> 0) {
    String NewVal = Serial.readString();
    lcd.clear();
    if (NewVal == "+") {
      //lcd.print("HEAT ON");
      // delay( 2000);
      HeatControl = true;

    }
    else if (NewVal == "-") {
      lcd.print(F("HEAT OFF"));
      HeatControl = false;
      //delay (2000);
    }
    else if (NewVal == "S") {
      sendStatus;
      //delay (2000);
    }
    else {
      long secs = NewVal.toInt();
      delayMS = secs * 1000;
      //lcd.clear();
      //lcd.print(delayMS);
      //delay (2000);
    }
    // digitalWrite(13,HeatControl);
  }
}


void pipeProtect(){
  sensors.requestTemperatures(); // Send the command to get temperature readings

    /********************************************************************/
    bool RelayOn;
    RelayOn = digitalRead(RlyPin);
    digitalWrite(13, HeatControl); // Board LED indicates Heat Control Status
    if (HeatControl == true) {

      //if (!(t1> OutdoorTrig && t4>SinkTrig)){

      //if (digitalRead(RlyPin)==false){// Heat status is OFF
      if (t1 > OutdoorCut) {
        RelayOn = false;
      }

      if (t4 > SinkCut) {
        RelayOn = false;
      }
      if (t1 < OutdoorTrig) {
        RelayOn = true;

      }

      if (t4 > 41) { //Absolute cutoff if temp at sink is above 41.  No need to heat more that?
        RelayOn = false;

      }

      if (t4 < SinkTrig) {
        RelayOn = true;

      }
      digitalWrite(RlyPin, RelayOn);
      // }
    }
    else {
      digitalWrite(RlyPin, false);
    }

    if (SuspendData == false) {

      Serial.println(F(" ** Temperatures Read **"));

      Serial.print(F("Outdoor temp. is:   "));
      t1 = printTemperature(Probe01);
      Serial.println();

      Serial.print(F("Near Furnace temp. is:   "));
      t2 = printTemperature(Probe02);

      Serial.println();

      Serial.print(F("Under Utility Room temp. is:   "));
      t3 = printTemperature(Probe03);
      Serial.println();

      Serial.print(F("Under Sink temp. is:   "));
      t4 = printTemperature(Probe04);
      String OutLogic;
      OutLogic = "*&*";
      if (digitalRead(RlyPin) == HIGH) {
        OutLogic.concat("+");
      }
      else {
        OutLogic.concat("-");
      }
      Serial.println();
      Serial.println();
      Serial.println(OutLogic);
      Serial.println();


    }

    lcd.clear();
    lcd.setCursor(0, 0);
    lcd.print(F("O="));
    lcd.print(t1);
    lcd.print(F(" F="));
    lcd.print(t2);
    lcd.setCursor(0, 1);
    lcd.print(F("U="));
    lcd.print(t3);
    lcd.print(F(" K="));
    lcd.print(t4);
}



void loop(void)
{
  static bool notFirstIteration;
  static long nextOneWireMillis;
  if (!notFirstIteration) {// Occurs on first run.  
    nextOneWireMillis = millis() + delayMS;
    pipeProtect();
    notFirstIteration = true;
  }

  if (wxMode == true) {// If monitoring weather station

    //Serial.println("WXMODE TRUE");
    rxSubLoop();
   
    delay(100);
    if(Serial1.available()>0){

        Serial.println("Something Returned I think");
        while(Serial1.available()){
          char c = Serial1.read();
          Serial.print(c);
        }
        Serial.println("\nDDDD\n");
  }

  }
  // call sensors.requestTemperatures() to issue a global temperature
  // request to all devices on the bus
  /********************************************************************/
  //Serial.print("**Requesting temperatures...");
  serialCheck();//检查传入命令的串行端口
// serial1Check(); //Serial.println("Out of Serial1Check“); if (nextOneWireMillis <= millis ()){ //这段是程序管道保护部分nextOneWireMillis = millis ()+ delayMS ; pipeProtect (); //你可以在同一条总线上有多个DS18B20。// 0表示线上的第一个IC // delay(delayMS + 200); } }


Arduino Mega的数据接收器代码


bool  CheckData () {
float CkVal = data 。湿度+ 数据。温度+ 数据。晴雨表+ 数据。风+ 数据。雨+ 数据。maxWind + 数据。rainRate + 数据。packetID + 数据。windPacketPeak + 数据。randDate + 数据。randTime +
                            数据。电池;
布尔CKB = ((CkVal == 数据。CKSUM )&& (数据。CKSUM > 30000 )); if (ckB == false ){ data 。温度= 0 ; 数据。湿度= 0 ; 数据。气压计= 0 ; 数据。风= 0 ; 数据

           
      
      
      
      
      
    。雨 =  0 ;
数据。CKSum = 1 ; } return (ckB ); } float rainFallRate (){ } // END rainFallRate()********************** float windChill (float mTempF ,float mMPH ){ //计算风寒如果温度<50,风力> 3 浮动Twc ; 如果((mTempF < 50.0 )&& (mMPH > 3.0 ))
      

  
   



  





     
   
          {
    Twc = 35.74 + 0.6215 * mTempF - 35.75 * pow(mMPH, 0.16) + 0.4275 * mTempF * pow(mMPH, 0.16);
  }
  else
  {
    Twc = mTempF;// return temp unchanged if no wind chill
  }

  return (Twc);
}// End windChill()---------------------------------------------


float RandianDate(byte dayOfMonth, byte month, byte year) { //  Date to integer format - 01-01-1980 becomes 111180
  String myStr;
  byte myDay = dayOfMonth + 10;// Adding 10 to values to make all 2 digit.  No need to do the years.
  byte myMonth = month + 10;
  byte myYear = year + 10;
  //month += 10;
  myStr.concat(myMonth);

  myStr.concat(myDay);

  myStr.concat(myYear);

  return (myStr.toFloat());
  //return(0);
}


float RandianTime(byte hours, byte minutes, byte seconds) { //  Time to integer format - 14:56:03 becomes 145603
  String myStr;
  hours += 10;   // Adding 10 to these values to ensure all are 2 digits.
  minutes += 10; //  Will subtract 10 again when decoded
  seconds += 10;
  myStr.concat(hours);

  myStr.concat(minutes);

  myStr.concat(seconds);

  return (myStr.toFloat());
  //return(0);
}

String RandianToDate(float RandDate) {
  String msg = "";
  msg.concat(RandDate);
  String token;
  String myDt;
  int trans;

  for ( int cnt = 0; cnt < 6 ; cnt++) {
    token.concat(msg.charAt(cnt));
    if ((cnt == 1) || (cnt == 3)) {
      trans = token.toInt() - 10;
      if (trans < 10) {
        myDt.concat("0");
      }
      myDt.concat(trans);
      myDt.concat("-");
      token = "";
    }

    else if (cnt == 5) {
      trans = token.toInt() - 10;
      myDt.concat("20");
      myDt.concat(trans);
    }

  }
  return (myDt);
}

String RandianToTime(float RandTime) {
  String msg = "";
  msg.concat(RandTime);
  String token;
  String myDt;
  int trans;

  for ( int cnt = 0; cnt < 6 ; cnt++) {
    token.concat(msg.charAt(cnt));
    if ((cnt == 1) || (cnt == 3) || (cnt == 5)) {
      trans = token.toInt() - 10;
      if (trans < 10) {
        myDt.concat("0");
      }
      myDt.concat(trans);
      if (cnt < 5) {
        myDt.concat(":");
      }

      token = "";
    }


  }
  return (myDt);
}

void showReport(void) {
  Serial.print(F("\nTemperature: "));
  Serial.print(data.temperature);
  Serial.print(F(" Degrees F\nHumidity: "));
  Serial.print(data.humidity);
  Serial.print(F("% \nBarometer: "));
  Serial.print(data.barometer);
  Serial.print(F(" Inches Hg \nWind (current): "));
  Serial.print(data.wind);
  Serial.print(F(" Mph\n   Feels like "));
  Serial.print(windChill(data.temperature, data.wind));

  Serial.print(F(" Wind Chill\nPeak Wind this Read: "));
  Serial.print(data.windPacketPeak);
  Serial.print(F(" Mph\nPeak Wind Today: "));
  Serial.print(data.maxWind);
  Serial.print(F(" Mph\nRainfall: "));
  Serial.print(data.rain);
  Serial.print(F(" Inches\nRain Rate: "));
  Serial.print(data.rainRate);
  Serial.print(F(" Inches per Hour\n\nPacket ID: "));

  Serial.print(data.packetID);
  //Serial.print("\nCheck Sum: ");
  //Serial.println(data.CKSum);
  Serial.print(F("\nDate: "));
  Serial.println(RandianToDate(data.randDate));
  Serial.print(F("Time: "));
  Serial.println(RandianToTime(data.randTime));
  Serial.println("");
  Serial.print(F("Battery: "));
  Serial.print(data.battery);
  Serial.println(F(" Volts\n\n****************************************\n"));



}

void dataPrep() { // Process incoming data, prepare dataToPost for transmission to network interface.  Average some values

  //static bool firstSeries;
  static int avgCounter;
  static float tempAvg;
  static int windAvg;
  static int windPeak;
  static int windRing[10];
  static float tempRing[10];// the "Ring arrays keep the last 10 readings for averaging, constatly rotating through
  static float rainVals[10];
  static float barVals[10];
  static float humVals[10];
  float tempTot;
  float batt;
  float rainfallRate;
  static int clearCount;

  if (avgCounter == 0) { //  Reset some vals for next post
    windPeak = 0;
    for (int ct; ct < 10 ; ct++) {
      rainVals[ct] = 0;
      tempRing[ct] = 0;
      tempTot = 0;
    }

  }
  windRing[avgCounter] = data.wind;
  if (data.windPacketPeak > windPeak) {
    windPeak = data.windPacketPeak;
  }
  tempRing[avgCounter] = data.temperature;
  humVals[avgCounter] = data.humidity;
  barVals[avgCounter] = data.barometer;
  rainVals[avgCounter] = data.rain;// - lastData.rain;// Rain measurement from station is a daily total-we need to calculate rain per package
  String trTime = RandianToTime(data.randTime);
  bool saveNOW = (trTime.charAt(4) == '0') && (avgCounter > 0);// will cause update at least every 10 packets, but should keep it at 00 minutes
  if ((avgCounter == 9)|| (saveNOW)) { //Last of data packets. Prepare values, insert into dataToPost, then send to Network Interface
    float rainTot;
    float windTot;
    float humTot;
    float barTot;
    // int tempTot;
    for (int ct = 0; ct < avgCounter+1 ; ct++) {
      rainTot = rainVals[ct];// for rain, just use last reading sent. No need to average, will send as total for day
      windTot += windRing[ct];
      tempTot += tempRing[ct];
      barTot += barVals[ct]-28.00;// Subtracting out lowest likely reading.  Averaging difference to increase accuracy in the event of errors
      humTot += humVals[ct];
      /*    Serial.println();
        Serial.print(tempRing[ct]);
        Serial.print("  ");
        Serial.println(tempTot);
        //Serial.println();
      */
    }
    avgCounter ++;// increment for calculating averages (due to zero based array counter)
    dataToPost.battV = data.battery;
    dataToPost.temperature = tempTot / float(avgCounter);
    dataToPost.barometer = (barTot /  float(avgCounter))+28.00;
    dataToPost.humidity = humTot /  float(avgCounter);
    dataToPost.avgWind = windTot / (avgCounter);
    dataToPost.peakWindThisRead = windPeak;
    dataToPost.rainThisRead = rainTot;
    dataToPost.rainRate = data.rainRate;
    Serial.println(F("\n~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"));
    Serial.print(F("\nData to Post:\n"));
    Serial.println(dataToPost.temperature);
    Serial.println(dataToPost.barometer);
    Serial.println(dataToPost.humidity);
    Serial.println(dataToPost.avgWind);
    Serial.println(dataToPost.peakWindThisRead);
    Serial.println(dataToPost.rainThisRead);
    Serial.println(F("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\n"));
    delay (2000);
    String url = "@";// add start character
    url += String(dataToPost.temperature);
    url += ",2=";
    url += String(dataToPost.humidity);
    url += ",3=";
    url += String(dataToPost.avgWind);
    url += ",4=";
    url += String(dataToPost.peakWindThisRead);
    url += ",5=";
    url += String(dataToPost.rainThisRead);
    url += ",6=";
    url += String(dataToPost.barometer);
    url += ",7=";
    url += String(dataToPost.rainRate);
    url += ",8=";
    url += String(dataToPost.battV);
    url += "~";// add end character

    String datStr;
    datStr.concat(dataToPost.temperature);
    datStr.concat(",");
    datStr.concat(dataToPost.humidity);
    datStr.concat(",");
    datStr.concat(dataToPost.avgWind);
    datStr.concat(",");
    datStr.concat(dataToPost.peakWindThisRead);
    datStr.concat(",");
    datStr.concat(dataToPost.rainThisRead);
    datStr.concat(",");
    datStr.concat(dataToPost.barometer);
    Serial.println (datStr);
    Serial1.print(url);// This line is where data is submitted to Network Interface (NodeMCU)   
    delay(10000);       // Lets wait a little while then   
    Serial1.print(url);// Send again to minimize data gaps due to errors in transmission   

    avgCounter = -1;
    //  Serial.print("IN the Test");
  }

  avgCounter ++;
  if (avgCounter > 9) {
    avgCounter = 0;
  }


}


void simulateData() {
  static long cnt;

  data.temperature = t1;
  data.humidity = t2;
  data.barometer = t3;
  data.wind = random(t4);
  data.maxWind = t4 + random(0, 21);
  data.windPacketPeak = t4 + random(0, 21);
  data.rain = t1;
  data.rainRate = t2;
  data.randDate = 101218;
  data.randTime = 131313;
  data.packetID = cnt;
  cnt ++;

}



void rxSubLoop(void) {

  // Serial.println("In the rxSubLoop");
  uint8_t buf[sizeof(data)];
  uint8_t buflen = sizeof(data);
  //Serial.println("in Loop");
  //vw_wait_message();
  if (vw_have_message())  // Is there a packet for us?
  {
    vw_get_message(buf, &buflen);
    memcpy(&data, &buf, buflen);
    // delay(500);
    bool myCkV = CheckData();// Check for  valid Packet-return true if valid
    if (myCkV == true) {

      if (data.packetID != lastData.packetID) {
        dataPrep();
        showReport();

        lastData = data;

      }


    }
    else {
      Serial.print(F("Bad Packet"));
      Serial.print(F("\n\n****************************************\n\n"));
    }

  }
  /*else{//A place to add a line for data simlation-for devel purposes
    // This ELSE clause will be commented out after new transmitter comes in

       simulateData();
       dataPrep();
       showReport();
      lastData = data;      延迟(30000); //希望每隔1分钟模拟一次数据包     //Serial.println("Exiting RX_Lib“);     } * / }



Arduino的气象站传感器/变送器代码
  1. #include  <VirtualWire.h>
  2. #include  <Time.h>
  3. #include  <TimeLib.h>
  4. #include  <dht.h>
  5. #include  <Adafruit_MPL3115A2.h>
  6. #include  <Wire.h>

  7. #include  <avr / power.h>
  8. #include  <avr / sleep.h>
  9. #include  <avr / wdt.h>


  10. #define DS3231_I2C_ADDRESS 0x68
  11. #define OFF false
  12. #define ON true
  13. #define TOGGLE 2 //如果您想切换一个值而不是ON / OFF / TRUE / FALSE,则使用此选项以获得无线电功能
  14. dht  myDHT ;  //创建DHT传感器实例
  15. Adafruit_MPL3115A2  baro  =  Adafruit_MPL3115A2 (); //创建气压传感器的实例
  16. time_t myTime ; //是系统时间对象time_t upTime ; //包含时间系统定时器被设置为const uint8_t ledPin = 13 ; const uint8_t transmit_pin =





  17.    
  18.     11;
  19. const uint8_t rainPin = 2;// Wind and rain readings handled by interrupts
  20. const uint8_t windPin = 3; // Wind and rain readings handled by interrupts
  21. const uint8_t dhtPin = 4;
  22. const uint8_t rfPower = 5;// control line for RF Power Relay

  23. const float rainPerTip = .0202;// Specific to dimensions of rain gauge built
  24. const int timeComp = -1516;// Value for periodic time compensation. After this many seconds,
  25. // 1 second adjustment is added or subtracted for on the fly Sys Clock a Correction
  26. // Value was computed after 24 hours running, to determine approximate adjustment value.
  27. // This may be further refined as I use unit for longer periods of time.
  28. float rainInches;
  29. volatile long rainLastMillis; // Millis of previous rain "tip"
  30. volatile long rainMillis;     // Millis of current rain tip
  31. float windAdj = 9.5;  //default value for wind speed (Anemometer) adjustment
  32. volatile long windLastMillis; // last millis reading from anemometer
  33. volatile long revTime; // time in millis of current anemometer revolution
  34. volatile int f_wdt = 1;
  35. volatile long nextSleepMillis;
  36. volatile long wokeUpMillis;

  37. long xmitRate = 60000; // xmitRate is how often packets will be transmitted, in milliseconds.
  38. int tipCount; // Rain gauge bucket "tips", .0202 inch per tip for my gauge.  Resets at midnight
  39. float tempDHT; // Temperature from DHT
  40. float humDHT;  // Humidity from DHT
  41. float curWindMPH;  // Calculated wind speed
  42. float topWind;
  43. bool needsReset;  // Set to true at 11:59 PM, to trigger reset at midnight
  44. bool baroSensorPresent; // Set to true if barometric pressure sensor is detected at startup
  45. long timeCompTrigger;// value of next time compensation in millis
  46. bool serialDump;
  47. bool testMode;
  48. byte testMinutes = 2;

  49. byte ckHour;// ckHour and ckMinute are used to see if time to reset (at midnight)
  50. byte ckMinute;
  51. byte ckSecond;
  52. volatile bool beenAsleep;

  53. struct package
  54. {
  55.   float temperature ;
  56.   float humidity ;
  57.   float barometer ;
  58.   byte wind ;
  59.   byte maxWind;
  60.   byte windPacketPeak;
  61.   float rain ;
  62.   float rainRate;
  63.   float randDate;
  64.   float randTime;
  65.   float battery;
  66.   long packetID;
  67.   float CKSum ;
  68. };


  69. typedef struct package Package;
  70. Package data;

  71. //DHT dht(DHTPIN, DHTTYPE);

  72. void setup()
  73. {
  74.   testMode = true;  // Will start in test mode, this will time out in 5 minutes.   Helps aim antenna
  75.   beenAsleep = false;
  76.   serialDump = testMode;
  77.   // Initialise the IO and ISR
  78.   vw_set_tx_pin(transmit_pin);
  79.   vw_set_ptt_inverted(true); // Required for DR3100
  80.   vw_setup(2000);       // Bits per sec
  81.   Serial.begin(9600);
  82.   Serial.println(F("Working to setup"));

  83.   Wire.begin();
  84.   //serialDump = false;
  85.   //serialDump = true;
  86.   baroSensorPresent = true;
  87.   if (! baro.begin()) {
  88.     Serial.println(F("Couldnt find sensor"));
  89.     baroSensorPresent = false;
  90.     //return;
  91.   }
  92.   else {

  93.     baro.write8(0x2D, 0x23);// calibration for altitude
  94.   }

  95.   pinMode (rainPin, INPUT_PULLUP);
  96.   pinMode (dhtPin, INPUT);
  97.   pinMode(ledPin, OUTPUT);
  98.   pinMode (windPin, INPUT_PULLUP);
  99.   pinMode(rfPower, OUTPUT);
  100.   attachInterrupt(0, rain_Count, FALLING);// Define interrupt pins and processes required
  101.   attachInterrupt(1, wind_Count, FALLING);

  102.   //needsReset = true;// used in testing only
  103.   tipCount = 0;// Initial value 0 "tips", 0 inches of rain
  104.   rainInches = 0;
  105.   revTime = 0;
  106.   readDHT();
  107.   /*** Setup the WDT ***/

  108.   /* Clear the reset flag. */
  109.   MCUSR &= ~(1 << WDRF);

  110.   /* In order to change WDE or the prescaler, we need to
  111.      set WDCE (This will allow updates for 4 clock cycles).
  112.   */
  113.   WDTCSR |= (1 << WDCE) | (1 << WDE);

  114.   /* set new watchdog timeout prescaler value */
  115.   WDTCSR = 1 << WDP0 | 1 << WDP3; /* 8.0 seconds */

  116.   /* Enable the WD interrupt (note no reset). */
  117.   WDTCSR |= _BV(WDIE);


  118.   delay(2000);// Delay to prevent re-read of DHT prematurely after startup
  119.   radio(OFF);

  120. } // END Setup() *******************

  121. //!!!!!!!!!!!!!!!!!! The following 3 functions are used by RTC.  DO NOT CHANGE !!!!!!!!!!!!!!!!!!!
  122. byte decToBcd(byte val)
  123. {
  124.   return ( (val / 10 * 16) + (val % 10) );
  125. }
  126. // Convert binary coded decimal to normal decimal numbers
  127. byte bcdToDec(byte val)
  128. {
  129.   return ( (val / 16 * 10) + (val % 16) );
  130. }


  131. void readRTCTime(byte *second,
  132.                  byte *minute,
  133.                  byte *hour,
  134.                  byte *dayOfWeek,
  135.                  byte *dayOfMonth,
  136.                  byte *month,
  137.                  byte *year)
  138. {
  139.   Wire.beginTransmission(DS3231_I2C_ADDRESS);
  140.   Wire.write(0); // set DS3231 register pointer to 00h
  141.   Wire.endTransmission();
  142.   Wire.requestFrom(DS3231_I2C_ADDRESS, 7);
  143.   // request seven bytes of data from DS3231 starting from register 00h
  144.   *second = bcdToDec(Wire.read() & 0x7f);
  145.   *minute = bcdToDec(Wire.read());
  146.   *hour = bcdToDec(Wire.read() & 0x3f);
  147.   *dayOfWeek = bcdToDec(Wire.read());
  148.   *dayOfMonth = bcdToDec(Wire.read());
  149.   *month = bcdToDec(Wire.read());
  150.   *year = bcdToDec(Wire.read());
  151. }


  152. // !!!!!!!!!!!!!!!!  END OF DO NOT CHANGE SECTION !!!!!!!!!!!!!!!!!!!!!!!!!!!

  153. // **  INTERRUPT PROCESSOR SECTION  **
  154. //*************************************************************

  155. void rain_Count() { // Interrupt Process for Rain Gauge Tip Counting
  156.   rainLastMillis = rainMillis;
  157.   rainMillis = millis();
  158.   tipCount ++; // All we aneed to do here is increment the tip counter
  159. }  // END of Interrupt Processor rain_Count --------------------

  160. // ************************************************************
  161. //*************************************************************

  162. void wind_Count() { // Interrupt Process for Wind measuring
  163.   if (beenAsleep) {
  164.     /*
  165.       nextSleepMillis = millis() + 10000;// wait 10 seconds to see if another wind pulse comes in before sleeping again.
  166.       windLastMillis = nextSleepMillis - 10000;
  167.     */
  168.     //long adj = 15;
  169.     long myVal = millis();
  170.     //long newRevTime = myVal - windLastMillis;
  171.     nextSleepMillis = myVal + 9000;// stay awake for a little while to wait for more wind pulses.
  172.     if (1) { //(((curWindMPH > 8) && (newRevTime < revTime/2)) || ((curWindMPH <8) && (newRevTime < revTime/3))) {// Probably Noise-ignore pulse

  173.     }

  174.     else {

  175.       revTime = myVal - windLastMillis;
  176.       windLastMillis = myVal;
  177.       nextSleepMillis = myVal + 12000;
  178.     }

  179.   }
  180.   else {
  181.     long myVal = millis();
  182.     long newRevTime = myVal - windLastMillis;
  183.     if (((curWindMPH > 8) && (newRevTime < revTime/2)) || ((curWindMPH <8) && (newRevTime < revTime/3))) {// Probably Noise-ignore pulse

  184.     }

  185.     else {

  186.       revTime = myVal - windLastMillis;
  187.       windLastMillis = myVal;
  188.     }

  189.   }

  190.   //Serial.println("TRIGGERED");
  191.   //}

  192. }  // END of Interrupt Processor wind_Count


  193. ISR(WDT_vect)// Watchdog timer interrupt routine
  194. {
  195.   if (f_wdt == 0)
  196.   {
  197.     f_wdt = 1;
  198.   }
  199.   else
  200.   {
  201.     //Serial.println("WDT Overrun!!!");
  202.   }
  203. }


  204. // ************************************************************

  205. void sleepNow()
  206. {
  207.   Serial.println(F("Going to sleep now"));
  208.   // Choose our preferred sleep mode:
  209.   set_sleep_mode(SLEEP_MODE_IDLE);

  210.   // Set sleep enable (SE) bit:
  211.   sleep_enable();
  212.   power_adc_disable();
  213.   power_spi_disable();
  214.   power_timer0_disable();
  215.   power_timer2_disable();
  216.   power_twi_disable();
  217.   // Put the device to sleep:
  218.   sleep_mode();

  219.   // Upon waking up, sketch continues from this point.
  220.   sleep_disable();
  221.   Serial.println(F("GOOD MORNING VIET NAM!"));
  222.   power_all_enable();
  223. }


  224. void radio(uint8_t action) {
  225.   int pwrOnDly = 500;
  226.   if (action < 2) {

  227.     digitalWrite(rfPower, action); // If action = ON or OFF, comply
  228.     if (action == ON) {
  229.       delay(pwrOnDly);// Give radio a moment to power up before using0
  230.     }

  231.   }
  232.   else {
  233.     digitalWrite(rfPower, !digitalRead(rfPower)); // Otherwise Toggle
  234.     delay(pwrOnDly);// see above
  235.   }
  236. }

  237. float readBattery(void) {
  238.   float chipVoltage = 5.096;// Set this value to the measured voltage on 5 v pin on Arduino, USING EXPECTED POWER SUPPLY!!
  239.   int sum = 0;                    // sum of samples taken
  240.   unsigned char sample_count = 0; // current sample number
  241.   // take a number of analog samples and add them up
  242.   while (sample_count < 10) {
  243.     sum += analogRead(A1);
  244.     sample_count++;

  245.     delay(10);
  246.   }
  247.   float voltage = ((float)sum / 10.0 * chipVoltage ) / 1024.0;
  248.   // Serial.println(voltage * 1.922);
  249.   return (voltage * 2);
  250. }

  251. void readDHT() {

  252.   static long nextReadMillis;
  253.   if (millis() >= nextReadMillis) {
  254.     int readData = myDHT.read22(dhtPin);
  255.     tempDHT = myDHT.temperature * 1.8 + 32;
  256.     humDHT = myDHT.humidity;
  257.     nextReadMillis = millis() + 2000;// DHT can only be read every 2 seconds.  This variable prevents premature readings
  258.   }

  259. }// END of readDHT()-------------------------------------------

  260. void rain_Set(float myVal) {// Set rain to a specific value, used if restarting during day with rain

  261.   rainInches = myVal;
  262.   tipCount = rainInches / rainPerTip;
  263.   rainLastMillis = 0;
  264.   Serial.println("");
  265.   Serial.print(F("Rainfall Measurement SET to "));
  266.   Serial.print(myVal);
  267.   Serial.println(F(" Imches\n"));
  268. }// END of rain_Set()-----------------------------------------

  269. void rain_Reset() {

  270.   tipCount = 0;
  271.   rainInches = 0;
  272.   rainLastMillis = 0;
  273.   Serial.println("");
  274.   Serial.println(F("Rainfall Measurement RESET!\n"));
  275.   Serial.println(F(""));


  276. }// END of rain_Reset()-----------------------------------------

  277. void wind_Reset() {

  278.   topWind = 0;
  279.   Serial.println();
  280.   Serial.println(F("Maximum Wind RESET!\n"));
  281.   Serial.println();


  282. }// END of wind_Reset()-----------------------------------------

  283. void all_Reset() {

  284.   wind_Reset();
  285.   rain_Reset();


  286. }// END of all()-----------------------------------------


  287. float RandianDate(byte dayOfMonth, byte month, byte year) { //  Date to integer format - 01-01-1980 becomes 111180
  288.   String myStr;
  289.   byte myDay = dayOfMonth + 10;// Adding 10 to values to make all 2 digit.  No need to do the years.
  290.   byte myMonth = month + 10;
  291.   byte myYear = year + 10;
  292.   //month += 10;
  293.   myStr.concat(myMonth);

  294.   myStr.concat(myDay);

  295.   myStr.concat(myYear);

  296.   return (myStr.toFloat());
  297.   //return(0);
  298. }


  299. float RandianTime(byte hours, byte minutes, byte seconds) { //  Time to integer format - 14:56:03 becomes 145603
  300.   String myStr;
  301.   hours += 10;   // Adding 10 to these values to ensure all are 2 digits.
  302.   minutes += 10; //  Will subtract 10 again when decoded
  303.   seconds += 10;
  304.   myStr.concat(hours);

  305.   myStr.concat(minutes);

  306.   myStr.concat(seconds);

  307.   return (myStr.toFloat());
  308.   //return(0);
  309. }

  310. String RandianToDate(float RandDate) {
  311.   String msg = "";
  312.   msg.concat(RandDate);
  313.   String token;
  314.   String myDt;
  315.   int trans;

  316.   for ( int cnt = 0; cnt < 6 ; cnt++) {
  317.     token.concat(msg.charAt(cnt));
  318.     if ((cnt == 1) || (cnt == 3)) {
  319.       trans = token.toInt() - 10;
  320.       if (trans < 10) {
  321.         myDt.concat("0");
  322.       }
  323.       myDt.concat(trans);
  324.       myDt.concat("-");
  325.       token = "";
  326.     }

  327.     else if (cnt == 5) {
  328.       trans = token.toInt() - 10;
  329.       myDt.concat("20");
  330.       myDt.concat(trans);
  331.     }

  332.   }
  333.   return (myDt);
  334. }

  335. String RandianToTime(float RandTime) {
  336.   String msg = "";
  337.   msg.concat(RandTime);
  338.   String token;
  339.   String myDt;
  340.   int trans;

  341.   for ( int cnt = 0; cnt < 6 ; cnt++) {
  342.     token.concat(msg.charAt(cnt));
  343.     if ((cnt == 1) || (cnt == 3) || (cnt == 5)) {
  344.       trans = token.toInt() - 10;
  345.       if (trans < 10) {
  346.         myDt.concat("0");
  347.       }
  348.       myDt.concat(trans);
  349.       if (cnt < 5) {
  350.         myDt.concat(":");
  351.       }

  352.       token = "";
  353.     }


  354.   }
  355.   return (myDt);
  356. }

  357. void stampTime(void) {
  358.   String dateStr;
  359.   String timeStr;
  360.   byte second;
  361.   byte minute;
  362.   byte hour;

  363.   byte dayOfWeek;
  364.   byte dayOfMonth;
  365.   byte month;
  366.   byte year;
  367.   readRTCTime(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month,
  368.               &year);
  369.   ckMinute = minute;
  370.   ckHour = hour;
  371.   ckSecond = second;
  372.   data.randDate = RandianDate(dayOfMonth, month, year);
  373.   data.randTime = RandianTime(hour, minute, second);
  374.   /*
  375.     Serial.print("Hour: ");
  376.     Serial.print(hour);
  377.     Serial.print(" Minute: ");
  378.     Serial.print(minute);
  379.     Serial.print(" Second ");
  380.     Serial.print(second);
  381.     Serial.print("\n\n");
  382.     Serial.println(data.randTime);

  383.     //Serial.println(data.randTime);
  384.     Serial.println(data.randDate);

  385.   */


  386. }

  387. void serialReport(void) {
  388.   Serial.print("\Temperature: ");
  389.   Serial.print(data.temperature);
  390.   Serial.print(F(" Degrees F\nHumidity: "));
  391.   Serial.print(data.humidity);
  392.   Serial.print(F("% \nBarometer: "));
  393.   Serial.print(data.barometer);
  394.   Serial.print(F(" Inches Hg \nWind (current): "));
  395.   Serial.print(data.wind);
  396.   Serial.print(F(" Mph\nPeak Wind this Read: "));
  397.   Serial.print(data.windPacketPeak);
  398.   Serial.print(F(" Mph\nPeak Wind Today: "));
  399.   Serial.print(data.maxWind);
  400.   Serial.print(F(" Mph\nRainfall: "));
  401.   Serial.print(data.rain);
  402.   Serial.print(F(" Inches\nRain Rate: "));
  403.   Serial.print(data.rainRate);
  404.   Serial.print(F(" Inches per Hour\nPacket ID: "));
  405.   Serial.print(data.packetID);
  406.   Serial.print(F("\nCheck Sum: "));
  407.   Serial.println(data.CKSum);
  408.   Serial.print(F("Date: "));
  409.   Serial.print(RandianToDate(data.randDate));
  410.   Serial.print(F("\nTime: "));
  411.   Serial.println(RandianToTime(data.randTime));
  412.   Serial.print(F("Battery Voltage: "));
  413.   Serial.print(data.battery);
  414.   Serial.print(F(" Vdc\n\n"));

  415.   if (testMode == true) {


  416.     Serial.print(F("**  TEST MODE **  TEST MODE **\n\n"));
  417.   }
  418. }

  419. float CheckSum() { // A Check to ensure valid packet received.  Basic Check Sum (Sum of all fields-all are numeric)
  420.   return (data.temperature + data.humidity + data.barometer + data.wind + data.rain + data.rainRate + data.maxWind + data.packetID + data.windPacketPeak + data.randDate + data.randTime + data.battery);
  421. } // END CheckSum **************************


  422. void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte
  423.                    dayOfMonth, byte month, byte year)
  424. {
  425.   // sets time and date data to DS3231
  426.   Wire.beginTransmission(DS3231_I2C_ADDRESS);
  427.   Wire.write(0); // set next input to start at the seconds register
  428.   Wire.write(decToBcd(second)); // set seconds
  429.   Wire.write(decToBcd(minute)); // set minutes
  430.   Wire.write(decToBcd(hour)); // set hours
  431.   Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday)
  432.   Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31)
  433.   Wire.write(decToBcd(month)); // set month
  434.   Wire.write(decToBcd(year)); // set year (0 to 99)
  435.   Wire.endTransmission();
  436. }

  437. void sendData() { // Send data packet by RF transmitter
  438.   radio(ON);
  439.   digitalWrite(ledPin, HIGH); // Flash a light to show transmitting
  440.   //readSensors(); now doing in loop, not here - prevents differences in "same" packet sends
  441.   vw_send((uint8_t *)&data, sizeof(data));
  442.   vw_wait_tx(); // Wait until the whole message is gone
  443.   digitalWrite(ledPin, LOW);
  444.   // delay(2000);
  445.   radio(OFF);
  446. }// END sendData *******************


  447. void readSensors()// Read all sensors and build data package
  448. {

  449.   readDHT();
  450.   data.humidity = humDHT;
  451.   data.temperature = tempDHT;
  452.   data.barometer = baroReading();
  453.   data.wind = Wind_Speed();
  454.   
  455.   data.maxWind = topWind;

  456.   data.rainRate = rainFallRate();
  457.   data.rain = rainInches;
  458.   data.battery = readBattery();
  459.   data.CKSum = CheckSum();
  460. } // END readSensors() ******************************


  461. float rainFallRate() {
  462.   if (tipCount > 0) {

  463.     float tipDuration = rainMillis - rainLastMillis;
  464.     if (millis() > rainMillis + 600000) {// no new tips in last 10 minutes
  465.       tipDuration = millis() - rainLastMillis;
  466.     }

  467.     if (tipDuration > 120 * 60000) { // tip takes over 2 hour2, effective rate 0 for our purposes
  468.       return (0);
  469.     }
  470.     else {
  471.       float tipSeconds = tipDuration / 1000.00;
  472.       float tipsPerHour = 3600.00 / tipSeconds;

  473.       return ( rainPerTip * tipsPerHour);
  474.     }

  475.   }
  476.   else {
  477.     return (0);
  478.   }


  479. }

  480. float baroReading() {
  481.   if (baroSensorPresent == true) {
  482.     float pascals = baro.getPressure();
  483.     // Our weather page presents pressure in Inches (Hg)
  484.     // Use http://www.onlineconversion.com/pressure.htm for other units
  485.     // Serial.print(pascals/3377); Serial.println(" Inches (Hg)");
  486.     return ((pascals / 3377.00) + 0.87); // 0.87 is barometric adjustment

  487.   }
  488.   else {
  489.     return (99.99); // bogus reading if sensor not detected.

  490.   }


  491. }// End baroReading() ----------------------------------------------

  492. /*
  493.   float rainfallRate() {
  494.   float tipDuration = rainMillis - rainLastMillis;
  495.   float tipSeconds = tipDuration / 1000;
  496.   float tipsPerHour = 3600 / tipSeconds;
  497.   float myRainRate = rainPerTip * tipsPerHour;
  498.   return (myRainRate);
  499.   }// END of RainfallRate() ************************
  500. */
  501. int Wind_Speed() {

  502.   float retValF = 717.00 * windAdj / (revTime);

  503.   if (millis() >= windLastMillis + 10000) { // No wind pulses in 10 seconds, wind is effectively 0
  504.     retValF = 0.00;
  505.   }
  506.   curWindMPH = retValF;
  507.   if (data.windPacketPeak < retValF){
  508.       data.windPacketPeak = retValF;
  509.     }
  510.   if (topWind<data.wind){
  511.   topWind = data.wind;

  512.   }
  513.   return retValF;

  514. }// END of Wind_Speed() ---------------------------------------------


  515. float baroTempReading() {

  516.   float tempF = baro.getTemperature() * 1.8 + 32;
  517.   //Serial.println(tempF);
  518.   //Serial.println(tempF);
  519.   return (tempF);
  520.   // Serial.print(tempC); Serial.println("*C");

  521. }// End baroTempReading() -----------------------------------------

  522. void showHelp() {

  523.   Serial.println(F("- Valid Serial Commands -"));
  524.   Serial.println(F("W ## - Sets Max Wind to ##"));
  525.   Serial.println(F("I ## - Interval in seconds - Sets Packet Interval"));
  526.   Serial.println(F("R ## - Sets Rainfall"));
  527.   Serial.println(F("+  Wind Adj up 1"));
  528.   Serial.println(F("-  Wind Adj down 1"));
  529.   Serial.println(F("XW - Max Wind Reset"));
  530.   Serial.println(F("XR - Rainfall Reset"));
  531.   Serial.println(F("XX - ALL Reset"));
  532.   Serial.println(F("S - Toggle Serial Dump Mode"));
  533.   Serial.println(F("\n** ? - Shows This Help Screen **"));
  534. }// END showHelp()------------------------------------------------


  535. void checkSerial(void) {
  536.   if (Serial.available() > 0) { // Check for and Begin Processing of incoming Serial commands
  537.     String myCmd = Serial.readString();
  538.     char myChr = myCmd.charAt(0);

  539.     if ((myChr == 'W') || (myChr == 'w')) { // "w" should be followed by a number to set max wind to

  540.       myCmd.replace("w", "");
  541.       myCmd.replace("W", "");
  542.       myCmd.replace(",", "");
  543.       myCmd.replace(" ", "");
  544.       float newWind = myCmd.toFloat();
  545.       data.maxWind = newWind;
  546.       topWind = newWind;

  547.     }
  548.     if ((myChr == 'I') || (myChr == 'i')) { // "I" should be followed by a number to set data transmission interval

  549.       myCmd.replace("i", "");
  550.       myCmd.replace("I", "");
  551.       myCmd.replace(",", "");
  552.       myCmd.replace(" ", "");
  553.       float newInterval = myCmd.toFloat();
  554.       xmitRate = newInterval * 1000;// entry will be  in seconds, converting to millis()

  555.     }
  556.     if ((myChr == 'R') || (myChr == 'r')) { // "R" should be followed by a number to set rainfall
  557.       myCmd.replace("r", "");
  558.       myCmd.replace("R", "");
  559.       myCmd.replace(",", "");
  560.       myCmd.replace(" ", "");
  561.       float rcmd = myCmd.toFloat();
  562.       if (rcmd > 0) { // If number is entered, set rainfall to that, else add 1 tip
  563.         rain_Set(rcmd);
  564.       }
  565.       else {
  566.         rain_Count();

  567.       }

  568.     }
  569.     if ((myChr == 'S') || (myChr == 's')) { // toggles Serial Dump mode

  570.       serialDump = !serialDump;
  571.     }

  572.     if (myChr == '+') {

  573.       windAdj ++;
  574.       Serial.print(F("Wind Adj = "));
  575.       Serial.println(windAdj);
  576.     }
  577.     if (myChr == '-') {
  578.       windAdj --;
  579.       Serial.print(F("Wind Adj = "));
  580.       Serial.println(windAdj);
  581.     }
  582.     if (myChr == '!') { //  Toggle Test Mode

  583.       testMode = !testMode;
  584.       serialDump = testMode;
  585.       Serial.print(F("Toggling Test Mode  - Mode="));
  586.       Serial.println(testMode);
  587.     }
  588.     if (myChr == '?') {
  589.       showHelp();
  590.     }
  591.   }

  592. }// END checkSerial() *****************************************


  593. void enterSleep(void)
  594. {
  595.   set_sleep_mode(SLEEP_MODE_PWR_SAVE);
  596.   wdt_reset();
  597.   sleep_enable();


  598.   /* Disable all of the unused peripherals. This will reduce power
  599.      consumption further and, more importantly, some of these
  600.      peripherals may generate interrupts that will wake our Arduino from
  601.      sleep!
  602.   */
  603.   power_adc_disable();
  604.   power_spi_disable();
  605.   power_timer0_disable();
  606.   power_timer2_disable();
  607.   power_twi_disable();
  608.   beenAsleep = true;
  609.   /* Now enter sleep mode. */
  610.   sleep_mode();

  611.   /* The program will continue from here after the timer timeout*/
  612.   sleep_disable(); /* First thing to do is disable sleep. */
  613.   power_all_enable();
  614.   //wokeUpMillis = millis()-10;
  615.   /* Re-enable the peripherals. */

  616. }


  617. void loop()
  618. {


  619.   static int oldTipCount;//Use to check if a Rain "Tip" has generated an Interrupt response
  620.   static long nextSendMillis;
  621.   static byte nextSendSecond;
  622.   static byte nextSendMinute;
  623.   static long packetCount;
  624.   static float maxWindThisPkt;
  625.   long initTestEnd = long(60000 * testMinutes);
  626.   static bool doneFirstLoop;

  627.   // Serial.println("SofarSOgood");
  628.   //initTestEnd = 0;// Testing line-to be removfed
  629.   stampTime();// called here to check time for reset at midnight. stampTime updates values in ckHour, ckMinute, ckSecond
  630.   if (!doneFirstLoop) { // first iteration. Set up a few things for future iterations
  631.     if (xmitRate >= 60000) {
  632.       nextSendMinute = ckMinute + (xmitRate / 60000);
  633.       nextSendSecond = 00;//ckSecond;

  634.     }
  635.     else if (xmitRate < 60000) {
  636.       nextSendMinute = ckMinute;
  637.       nextSendSecond = ckSecond + xmitRate / 1000;
  638.     }

  639.     doneFirstLoop = true;

  640.   }

  641.   if ((millis() >= initTestEnd)  && (millis() <= initTestEnd + 60000)) {
  642.     testMode = false;

  643.   }

  644.   if ((needsReset == false) && (ckHour == 23) && (ckMinute == 59)) {
  645.     needsReset = true;
  646.     //rain_Reset();
  647.   }

  648.   if ((needsReset == true) && (ckMinute < 5)) {
  649.     all_Reset();// Resets Rain, wind Counter, stores todays values as yesterday at midnight, ready for a brand new day!
  650.     needsReset = false;

  651.     //  *********************************************************************************
  652.   }

  653.   checkSerial();
  654.   //serialReport;
  655.   if (xmitRate < 5000) { // Don't allow less than 5 second interval.
  656.     xmitRate = 5000;
  657.   }

  658.   rainInches = tipCount *  rainPerTip;
  659.   readSensors();
  660.   if (maxWindThisPkt <= data.wind) {
  661.     maxWindThisPkt = data.wind;
  662.     if ((data.maxWind < maxWindThisPkt) && (maxWindThisPkt < 120)) { // if maxWindThisPkt >120, either data is corrupted, *OR*
  663.       data.maxWind = maxWindThisPkt;// Weather Station is being destroyed by tornado
  664.       topWind = data.maxWind;
  665.     }

  666.   }

  667.   /*
  668.     Serial.println("---");
  669.     Serial.println(ckMinute);
  670.     Serial.println(nextSendMinute);
  671.     Serial.println(ckSecond);
  672.     Serial.println(nextSendSecond);
  673.     Serial.println("---");
  674.   */

  675.   if (((ckMinute >= nextSendMinute) && (ckSecond >= nextSendSecond)) || (testMode == true)) { // Time to send data packet.
  676.     if ((ckMinute == 59) && (nextSendMinute == 0)) { //Problem condition-need to skip

  677.     }
  678.     else {


  679.       data.windPacketPeak = maxWindThisPkt;
  680.       maxWindThisPkt = 0;
  681.       packetCount ++;
  682.       nextSendMillis = millis() + xmitRate;
  683.       stampTime();
  684.       data.packetID = packetCount;
  685.       readSensors();
  686.       for (int cnt = 0; cnt < 2 ; cnt++) { // Send each packet 3 times, to hopefully eliminate/minimize lost packets.
  687.         sendData();
  688.         //d+elay(500);// NO longer needed, delays built into SendData for turning radio on.
  689.       }
  690.       if (serialDump == true) {
  691.         serialReport();
  692.       }

  693.       if (xmitRate >= 60000) {
  694.         nextSendMinute = (xmitRate / 60000) + ckMinute;
  695.         //nextSendSecond = ckSecond;
  696.         if (nextSendMinute > 59) {
  697.           nextSendMinute -= 60;
  698.         }

  699.       }
  700.       else if (xmitRate < 60000) {
  701.         //nextSendMinute = ckMinute;
  702.         nextSendSecond = ckSecond + xmitRate / 1000;
  703.         if (nextSendSecond > 59) {
  704.           nextSendSecond -= 60;
  705.         }
  706.       }

  707.     }

  708.   }//*******

  709.   if ((!testMode) && (millis() > nextSleepMillis)) {
  710. Serial 。println (“睡觉” ); 延迟(300 ); beenAsleep = true ; enterSleep (); beenAsleep = false ; 串行。println (“回到生活” ); } // * / // } ///结束循环!!!!

复制代码





1
2018-5-10 20:56:35   评论
1 个讨论
这个不错  资料分享的挺到位
2018-11-4 21:48:47 评论

举报

高级模式
您需要登录后才可以回帖 登录 | 注册

发表新帖
关闭

站长推荐 上一条 /7 下一条

快速回复 返回顶部 返回列表