Components and supplies
Arduino Nano R3
DHT22 Temperature Sensor
RTC Module
NodeMCU ESP8266 Weather Station Kit
Arduino Mega 2560
Pressure/Altitude/Temperature Sensor
Hall Effect Sensor
Apps and platforms
ThingSpeak API
Arduino IDE
Project description
Code
RX_Lib.ino
arduino
Data Receiver Code for Arduino Mega
1 2bool CheckData() { 3 float CkVal = data.humidity + data.temperature + data.barometer + data.wind + data.rain + data.maxWind + data.rainRate + data.packetID + data.windPacketPeak + data.randDate + data.randTime + data.battery; 4 5 bool ckB = ((CkVal == data.CKSum) && (data.CKSum > 30000)); 6 if (ckB == false) { 7 data.temperature = 0; 8 data.humidity = 0; 9 data.barometer = 0; 10 data.wind = 0; 11 data.rain = 0; 12 data.CKSum = 1; 13 14 } 15 return (ckB); 16 17} 18 19float rainFallRate() { 20 21 22}// END rainFallRate() ********************** 23 24 25float windChill(float mTempF, float mMPH) {// Calculate wind chill if temp <50, wind >3 26 float Twc; 27 if ((mTempF < 50.0) && (mMPH > 3.0)) { 28 Twc = 35.74 + 0.6215 * mTempF - 35.75 * pow(mMPH, 0.16) + 0.4275 * mTempF * pow(mMPH, 0.16); 29 } 30 else 31 { 32 Twc = mTempF;// return temp unchanged if no wind chill 33 } 34 35 return (Twc); 36}// End windChill()--------------------------------------------- 37 38 39float RandianDate(byte dayOfMonth, byte month, byte year) { // Date to integer format - 01-01-1980 becomes 111180 40 String myStr; 41 byte myDay = dayOfMonth + 10;// Adding 10 to values to make all 2 digit. No need to do the years. 42 byte myMonth = month + 10; 43 byte myYear = year + 10; 44 //month += 10; 45 myStr.concat(myMonth); 46 47 myStr.concat(myDay); 48 49 myStr.concat(myYear); 50 51 return (myStr.toFloat()); 52 //return(0); 53} 54 55 56float RandianTime(byte hours, byte minutes, byte seconds) { // Time to integer format - 14:56:03 becomes 145603 57 String myStr; 58 hours += 10; // Adding 10 to these values to ensure all are 2 digits. 59 minutes += 10; // Will subtract 10 again when decoded 60 seconds += 10; 61 myStr.concat(hours); 62 63 myStr.concat(minutes); 64 65 myStr.concat(seconds); 66 67 return (myStr.toFloat()); 68 //return(0); 69} 70 71String RandianToDate(float RandDate) { 72 String msg = ""; 73 msg.concat(RandDate); 74 String token; 75 String myDt; 76 int trans; 77 78 for ( int cnt = 0; cnt < 6 ; cnt++) { 79 token.concat(msg.charAt(cnt)); 80 if ((cnt == 1) || (cnt == 3)) { 81 trans = token.toInt() - 10; 82 if (trans < 10) { 83 myDt.concat("0"); 84 } 85 myDt.concat(trans); 86 myDt.concat("-"); 87 token = ""; 88 } 89 90 else if (cnt == 5) { 91 trans = token.toInt() - 10; 92 myDt.concat("20"); 93 myDt.concat(trans); 94 } 95 96 } 97 return (myDt); 98} 99 100String RandianToTime(float RandTime) { 101 String msg = ""; 102 msg.concat(RandTime); 103 String token; 104 String myDt; 105 int trans; 106 107 for ( int cnt = 0; cnt < 6 ; cnt++) { 108 token.concat(msg.charAt(cnt)); 109 if ((cnt == 1) || (cnt == 3) || (cnt == 5)) { 110 trans = token.toInt() - 10; 111 if (trans < 10) { 112 myDt.concat("0"); 113 } 114 myDt.concat(trans); 115 if (cnt < 5) { 116 myDt.concat(":"); 117 } 118 119 token = ""; 120 } 121 122 123 } 124 return (myDt); 125} 126 127void showReport(void) { 128 Serial.print(F("\ 129Temperature: ")); 130 Serial.print(data.temperature); 131 Serial.print(F(" Degrees F\ 132Humidity: ")); 133 Serial.print(data.humidity); 134 Serial.print(F("% \ 135Barometer: ")); 136 Serial.print(data.barometer); 137 Serial.print(F(" Inches Hg \ 138Wind (current): ")); 139 Serial.print(data.wind); 140 Serial.print(F(" Mph\ 141 Feels like ")); 142 Serial.print(windChill(data.temperature, data.wind)); 143 144 Serial.print(F(" Wind Chill\ 145Peak Wind this Read: ")); 146 Serial.print(data.windPacketPeak); 147 Serial.print(F(" Mph\ 148Peak Wind Today: ")); 149 Serial.print(data.maxWind); 150 Serial.print(F(" Mph\ 151Rainfall: ")); 152 Serial.print(data.rain); 153 Serial.print(F(" Inches\ 154Rain Rate: ")); 155 Serial.print(data.rainRate); 156 Serial.print(F(" Inches per Hour\ 157\ 158Packet ID: ")); 159 160 Serial.print(data.packetID); 161 //Serial.print("\ 162Check Sum: "); 163 //Serial.println(data.CKSum); 164 Serial.print(F("\ 165Date: ")); 166 Serial.println(RandianToDate(data.randDate)); 167 Serial.print(F("Time: ")); 168 Serial.println(RandianToTime(data.randTime)); 169 Serial.println(""); 170 Serial.print(F("Battery: ")); 171 Serial.print(data.battery); 172 Serial.println(F(" Volts\ 173\ 174****************************************\ 175")); 176 177 178 179} 180 181void dataPrep() { // Process incoming data, prepare dataToPost for transmission to network interface. Average some values 182 183 //static bool firstSeries; 184 static int avgCounter; 185 static float tempAvg; 186 static int windAvg; 187 static int windPeak; 188 static int windRing[10]; 189 static float tempRing[10];// the "Ring arrays keep the last 10 readings for averaging, constatly rotating through 190 static float rainVals[10]; 191 static float barVals[10]; 192 static float humVals[10]; 193 float tempTot; 194 float batt; 195 float rainfallRate; 196 static int clearCount; 197 198 if (avgCounter == 0) { // Reset some vals for next post 199 windPeak = 0; 200 for (int ct; ct < 10 ; ct++) { 201 rainVals[ct] = 0; 202 tempRing[ct] = 0; 203 tempTot = 0; 204 } 205 206 } 207 windRing[avgCounter] = data.wind; 208 if (data.windPacketPeak > windPeak) { 209 windPeak = data.windPacketPeak; 210 } 211 tempRing[avgCounter] = data.temperature; 212 humVals[avgCounter] = data.humidity; 213 barVals[avgCounter] = data.barometer; 214 rainVals[avgCounter] = data.rain;// - lastData.rain;// Rain measurement from station is a daily total-we need to calculate rain per package 215 String trTime = RandianToTime(data.randTime); 216 bool saveNOW = (trTime.charAt(4) == '0') && (avgCounter > 0);// will cause update at least every 10 packets, but should keep it at 00 minutes 217 if ((avgCounter == 9)|| (saveNOW)) { //Last of data packets. Prepare values, insert into dataToPost, then send to Network Interface 218 float rainTot; 219 float windTot; 220 float humTot; 221 float barTot; 222 // int tempTot; 223 for (int ct = 0; ct < avgCounter+1 ; ct++) { 224 rainTot = rainVals[ct];// for rain, just use last reading sent. No need to average, will send as total for day 225 windTot += windRing[ct]; 226 tempTot += tempRing[ct]; 227 barTot += barVals[ct]-28.00;// Subtracting out lowest likely reading. Averaging difference to increase accuracy in the event of errors 228 humTot += humVals[ct]; 229 /* Serial.println(); 230 Serial.print(tempRing[ct]); 231 Serial.print(" "); 232 Serial.println(tempTot); 233 //Serial.println(); 234 */ 235 } 236 avgCounter ++;// increment for calculating averages (due to zero based array counter) 237 dataToPost.battV = data.battery; 238 dataToPost.temperature = tempTot / float(avgCounter); 239 dataToPost.barometer = (barTot / float(avgCounter))+28.00; 240 dataToPost.humidity = humTot / float(avgCounter); 241 dataToPost.avgWind = windTot / (avgCounter); 242 dataToPost.peakWindThisRead = windPeak; 243 dataToPost.rainThisRead = rainTot; 244 dataToPost.rainRate = data.rainRate; 245 Serial.println(F("\ 246~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")); 247 Serial.print(F("\ 248Data to Post:\ 249")); 250 Serial.println(dataToPost.temperature); 251 Serial.println(dataToPost.barometer); 252 Serial.println(dataToPost.humidity); 253 Serial.println(dataToPost.avgWind); 254 Serial.println(dataToPost.peakWindThisRead); 255 Serial.println(dataToPost.rainThisRead); 256 Serial.println(F("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ 257")); 258 delay (2000); 259 String url = "@";// add start character 260 url += String(dataToPost.temperature); 261 url += ",2="; 262 url += String(dataToPost.humidity); 263 url += ",3="; 264 url += String(dataToPost.avgWind); 265 url += ",4="; 266 url += String(dataToPost.peakWindThisRead); 267 url += ",5="; 268 url += String(dataToPost.rainThisRead); 269 url += ",6="; 270 url += String(dataToPost.barometer); 271 url += ",7="; 272 url += String(dataToPost.rainRate); 273 url += ",8="; 274 url += String(dataToPost.battV); 275 url += "~";// add end character 276 277 String datStr; 278 datStr.concat(dataToPost.temperature); 279 datStr.concat(","); 280 datStr.concat(dataToPost.humidity); 281 datStr.concat(","); 282 datStr.concat(dataToPost.avgWind); 283 datStr.concat(","); 284 datStr.concat(dataToPost.peakWindThisRead); 285 datStr.concat(","); 286 datStr.concat(dataToPost.rainThisRead); 287 datStr.concat(","); 288 datStr.concat(dataToPost.barometer); 289 Serial.println (datStr); 290 Serial1.print(url);// This line is where data is submitted to Network Interface (NodeMCU) 291 delay(10000); // Lets wait a little while then 292 Serial1.print(url);// Send again to minimize data gaps due to errors in transmission 293 294 avgCounter = -1; 295 // Serial.print("IN the Test"); 296 } 297 298 avgCounter ++; 299 if (avgCounter > 9) { 300 avgCounter = 0; 301 } 302 303 304} 305 306 307void simulateData() { 308 static long cnt; 309 310 data.temperature = t1; 311 data.humidity = t2; 312 data.barometer = t3; 313 data.wind = random(t4); 314 data.maxWind = t4 + random(0, 21); 315 data.windPacketPeak = t4 + random(0, 21); 316 data.rain = t1; 317 data.rainRate = t2; 318 data.randDate = 101218; 319 data.randTime = 131313; 320 data.packetID = cnt; 321 cnt ++; 322 323} 324 325 326 327void rxSubLoop(void) { 328 329 // Serial.println("In the rxSubLoop"); 330 uint8_t buf[sizeof(data)]; 331 uint8_t buflen = sizeof(data); 332 //Serial.println("in Loop"); 333 //vw_wait_message(); 334 if (vw_have_message()) // Is there a packet for us? 335 { 336 vw_get_message(buf, &buflen); 337 memcpy(&data, &buf, buflen); 338 // delay(500); 339 bool myCkV = CheckData();// Check for valid Packet-return true if valid 340 if (myCkV == true) { 341 342 if (data.packetID != lastData.packetID) { 343 dataPrep(); 344 showReport(); 345 346 lastData = data; 347 348 } 349 350 351 } 352 else { 353 Serial.print(F("Bad Packet")); 354 Serial.print(F("\ 355\ 356****************************************\ 357\ 358")); 359 } 360 361 } 362 /*else{//A place to add a line for data simlation-for devel purposes 363 // This ELSE clause will be commented out after new transmitter comes in 364 365 simulateData(); 366 dataPrep(); 367 showReport(); 368 369 lastData = data; 370 371 delay(30000);// want data packets simulated every 1 minute 372 //Serial.println("Exiting RX_Lib"); 373 }*/ 374 375 376 377 378} 379
MegaWeather.ino
arduino
Code for Data Receiver (Arduino Mega)
1#include <AltSoftSerial.h> 2 3#include <Adafruit_Sensor.h> 4#include <VirtualWire.h> 5 6#include <OneWire.h> 7#include <DallasTemperature.h> 8#include <LiquidCrystal.h> 9 10#define TIMEOUT 5000 11 12//SoftwareSerial dataSerial(39, 38); // RX, TX 13 14const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; 15const String THINGSPEAK_API_WRITE_KEY = "PWLOULJXD5GO8RWP"; 16LiquidCrystal lcd(rs, en, d4, d5, d6, d7); 17int alarmLevel = 7000; 18int devCount; 19int swPin = 11; 20int RlyPin = 8; 21const int receive_pin = 9;// Pin for RF receiver for weather data from transmitter in yard 22//bool OKtoPost; 23bool HeatControl; //ON status means temperature controlling is active 24bool SuspendData; 25float t1, t2, t3, t4; 26/********************************************************************/ 27// Data wire is plugged into pin 12 on the Arduino 28#define ONE_WIRE_BUS 12 29/********************************************************************/ 30// Setup a oneWire instance to communicate with any OneWire devices 31// (not just Maxim/Dallas temperature ICs) 32OneWire oneWire(ONE_WIRE_BUS); 33/********************************************************************/ 34// Pass our oneWire reference to Dallas Temperature. 35DallasTemperature sensors(&oneWire); 36/********************************************************************/ 37DeviceAddress Probe01 = { 0x28, 0xFF, 0x67, 0x18, 0x23, 0x17, 0x04, 0xBF }; //Outdoor Sensor 38DeviceAddress Probe02 = { 0x28, 0xFF, 0xF5, 0x22, 0x23, 0x17, 0x04, 0xD8 }; //Under Stairs Sensor 39DeviceAddress Probe03 = { 0x28, 0xFF, 0xA9, 0xE7, 0x22, 0x17, 0x04, 0x7F }; // Utility Room 40DeviceAddress Probe04 = { 0x28, 0xFF, 0x7D, 0x18, 0x23, 0x17, 0x04, 0x7E };// Under Kitchen 41 42long delayMS; 43long OutdoorTrig = 25; // Trigger Relay if outdoor temp is below 44long OutdoorCut = 26; // Cutoff Relay if outdoor temp is above 45long SinkTrig = 35; 46long SinkCut = 38; 47 48struct package 49{ 50 float temperature = 0; 51 float humidity = 0; 52 float barometer = 0; 53 byte wind = 0; 54 byte maxWind = 0; 55 byte windPacketPeak = 0; 56 float rain = 0; 57 float rainRate = 0; 58 float randDate = 0; 59 float randTime = 0; 60 float battery = 0; 61 long packetID = 0; 62 float CKSum = 1; 63}; 64 65 66typedef struct package Package; 67Package data; 68Package lastData; 69 70struct postingPackage{ 71 float temperature = 0; 72 float barometer = 0; 73 float humidity = 0; 74 uint8_t avgWind = 0; 75 uint8_t peakWindThisRead = 0; 76 float rainThisRead = 0; 77 float rainRate = 0; 78 float battV = 0; 79}; 80 81typedef struct postingPackage PostingPackage; 82 83PostingPackage dataToPost; 84 85bool wxMode; 86 87void setup() { 88 pinMode(13, OUTPUT); 89 pinMode(RlyPin, OUTPUT); 90 pinMode(swPin, INPUT); 91 Serial.begin(115200); 92 Serial1.begin(57600); 93 HeatControl = false; 94 SuspendData = false; 95 //OKtoPost = false;// becomes true after first temperature readings 96 97 //Serial.println("Dallas Temperature IC Control Library Demo"); 98 // Start up the library 99 sensors.begin(); 100 lcd.begin(16, 2); 101 // Print a message to the LCD. 102 lcd.print("Pipe Protector 2"); 103 lcd.setCursor(0, 1); 104 devCount = sensors.getDeviceCount(); 105 Serial.print("Device Count: "); 106 Serial.println(devCount); 107 delayMS = 60000;// WIll increase to 60000 ms when finished. One reading per minute is plenty 108 randomSeed(analogRead(0)); 109 vw_set_rx_pin(receive_pin); 110 vw_setup(2000); // Bits per sec 111 vw_rx_start(); // Start the receiver PLL running 112 wxMode = true;// for now, we'll start in weather mode 113 //lastData. 114 115 //sensors.requestTemperatures(); 116}// End Setup 117 118void stateSwitch(void) { 119 /* if(delayMS >=50000){ 120 delayMS=10000; 121 } 122 else{ 123 delayMS=60000; 124 }*/ 125} 126 127bool SuspendToggle(void) { 128 SuspendData = !SuspendData; 129 return (SuspendData); 130 131} 132 133void sendStatus(void) { 134 String myStr;// Variable to hold all values as text string for sending over serial port 135 myStr = OutdoorTrig; 136 myStr.concat(","); 137 myStr.concat(OutdoorCut); 138 myStr.concat(","); 139 myStr.concat(SinkTrig); 140 myStr.concat(","); 141 myStr.concat(SinkCut); 142 myStr.concat(","); 143 myStr.concat(delayMS); 144 myStr.concat(","); 145 myStr.concat(HeatControl); 146 myStr.concat(","); 147 myStr.concat(SuspendData); 148 Serial.println(myStr); 149} 150 151 152 153 154int HighestTemp() { 155 int retVal; 156 for (int cnt = 0; cnt < devCount; cnt++) { 157 //int trVal = GetFTempDec(cnt); 158 int trVal = sensors.getTempFByIndex(cnt); 159 if (cnt == 0) { 160 161 retVal = trVal; 162 } 163 //Serial.println(sensors.getTempFByIndex(cnt)); 164 165 if (retVal < trVal) { 166 retVal = trVal; 167 } 168 } 169 // checkRange(retVal); 170 return (retVal); 171} 172 173float LowestTemp() { 174 float retVal; 175 for (int cnt = 0; cnt < devCount; cnt++) { 176 //int trVal = GetFTempDec(cnt); 177 int trVal = sensors.getTempFByIndex(cnt); 178 if (cnt == 0) { 179 180 retVal = trVal; 181 } 182 //Serial.println(sensors.getTempFByIndex(cnt)); 183 184 if (retVal > trVal) { 185 retVal = trVal; 186 } 187 } 188 // checkRange(retVal); 189 return (retVal); 190} 191 192float printTemperature(DeviceAddress deviceAddress) 193{ 194 195 float retVal = sensors.getTempF(deviceAddress); 196 197 if (retVal == -196.60) 198 { 199 Serial.print(F("<Error>")); 200 } 201 else 202 { 203 204 205 Serial.print(retVal); 206 207 Serial.print(F(" F ")); 208 return (retVal); 209 //Serial.print(DallasTemperature::toFahrenheit(tempC)); 210 } 211}// End printTemperature 212 213void serial1Check(){ 214String myCmd; 215 216 if(Serial1.available() > 0){ 217 Serial.println("You are there"); 218 myCmd = Serial1.readString(); 219 Serial.println(myCmd); 220 221 } 222 Serial.println("You ARE LEAVING!!"); 223} 224 225void serialCheck(){ 226 if (Serial.available() >> 0) { 227 String NewVal = Serial.readString(); 228 lcd.clear(); 229 if (NewVal == "+") { 230 //lcd.print("HEAT ON"); 231 // delay( 2000); 232 HeatControl = true; 233 234 } 235 else if (NewVal == "-") { 236 lcd.print(F("HEAT OFF")); 237 HeatControl = false; 238 //delay (2000); 239 } 240 else if (NewVal == "S") { 241 sendStatus; 242 //delay (2000); 243 } 244 else { 245 long secs = NewVal.toInt(); 246 delayMS = secs * 1000; 247 //lcd.clear(); 248 //lcd.print(delayMS); 249 //delay (2000); 250 } 251 // digitalWrite(13,HeatControl); 252 } 253} 254 255 256void pipeProtect(){ 257 sensors.requestTemperatures(); // Send the command to get temperature readings 258 259 /********************************************************************/ 260 bool RelayOn; 261 RelayOn = digitalRead(RlyPin); 262 digitalWrite(13, HeatControl); // Board LED indicates Heat Control Status 263 if (HeatControl == true) { 264 265 //if (!(t1> OutdoorTrig && t4>SinkTrig)){ 266 267 //if (digitalRead(RlyPin)==false){// Heat status is OFF 268 if (t1 > OutdoorCut) { 269 RelayOn = false; 270 } 271 272 if (t4 > SinkCut) { 273 RelayOn = false; 274 } 275 if (t1 < OutdoorTrig) { 276 RelayOn = true; 277 278 } 279 280 if (t4 > 41) { //Absolute cutoff if temp at sink is above 41. No need to heat more that? 281 RelayOn = false; 282 283 } 284 285 if (t4 < SinkTrig) { 286 RelayOn = true; 287 288 } 289 digitalWrite(RlyPin, RelayOn); 290 // } 291 } 292 else { 293 digitalWrite(RlyPin, false); 294 } 295 296 if (SuspendData == false) { 297 298 Serial.println(F(" ** Temperatures Read **")); 299 300 Serial.print(F("Outdoor temp. is: ")); 301 t1 = printTemperature(Probe01); 302 Serial.println(); 303 304 Serial.print(F("Near Furnace temp. is: ")); 305 t2 = printTemperature(Probe02); 306 307 Serial.println(); 308 309 Serial.print(F("Under Utility Room temp. is: ")); 310 t3 = printTemperature(Probe03); 311 Serial.println(); 312 313 Serial.print(F("Under Sink temp. is: ")); 314 t4 = printTemperature(Probe04); 315 String OutLogic; 316 OutLogic = "*&*"; 317 if (digitalRead(RlyPin) == HIGH) { 318 OutLogic.concat("+"); 319 } 320 else { 321 OutLogic.concat("-"); 322 } 323 Serial.println(); 324 Serial.println(); 325 Serial.println(OutLogic); 326 Serial.println(); 327 328 329 } 330 331 lcd.clear(); 332 lcd.setCursor(0, 0); 333 lcd.print(F("O=")); 334 lcd.print(t1); 335 lcd.print(F(" F=")); 336 lcd.print(t2); 337 lcd.setCursor(0, 1); 338 lcd.print(F("U=")); 339 lcd.print(t3); 340 lcd.print(F(" K=")); 341 lcd.print(t4); 342} 343 344 345 346void loop(void) 347{ 348 static bool notFirstIteration; 349 static long nextOneWireMillis; 350 if (!notFirstIteration) {// Occurs on first run. 351 nextOneWireMillis = millis() + delayMS; 352 pipeProtect(); 353 notFirstIteration = true; 354 } 355 356 if (wxMode == true) {// If monitoring weather station 357 358 //Serial.println("WXMODE TRUE"); 359 rxSubLoop(); 360 361 delay(100); 362 if(Serial1.available()>0){ 363 364 Serial.println("Something Returned I think"); 365 while(Serial1.available()){ 366 char c = Serial1.read(); 367 Serial.print(c); 368 } 369 Serial.println("\ 370DDDD\ 371"); 372 } 373 374 } 375 // call sensors.requestTemperatures() to issue a global temperature 376 // request to all devices on the bus 377 /********************************************************************/ 378 //Serial.print("**Requesting temperatures..."); 379 serialCheck();// Check serial ports for incoming commands 380 //serial1Check(); 381 //Serial.println("Out of Serial1Check"); 382 383 384 if (nextOneWireMillis <= millis()) { // This section is for pipe protector portion of program 385 nextOneWireMillis = millis() + delayMS; 386 pipeProtect(); 387 // You can have more than one DS18B20 on the same bus. 388 // 0 refers to the first IC on the wire 389 // delay(delayMS+200); 390 } 391 392 393} 394 395
MegaWeather.ino
arduino
Code for Data Receiver (Arduino Mega)
1#include <AltSoftSerial.h> 2 3#include <Adafruit_Sensor.h> 4#include 5 <VirtualWire.h> 6 7#include <OneWire.h> 8#include <DallasTemperature.h> 9#include 10 <LiquidCrystal.h> 11 12#define TIMEOUT 5000 13 14//SoftwareSerial dataSerial(39, 15 38); // RX, TX 16 17const int rs = 2, en = 3, d4 = 4, d5 = 5, d6 = 6, d7 = 7; 18const 19 String THINGSPEAK_API_WRITE_KEY = "PWLOULJXD5GO8RWP"; 20LiquidCrystal lcd(rs, 21 en, d4, d5, d6, d7); 22int alarmLevel = 7000; 23int devCount; 24int swPin = 11; 25int 26 RlyPin = 8; 27const int receive_pin = 9;// Pin for RF receiver for weather data 28 from transmitter in yard 29//bool OKtoPost; 30bool HeatControl; //ON status 31 means temperature controlling is active 32bool SuspendData; 33float t1, t2, t3, 34 t4; 35/********************************************************************/ 36// 37 Data wire is plugged into pin 12 on the Arduino 38#define ONE_WIRE_BUS 12 39/********************************************************************/ 40// 41 Setup a oneWire instance to communicate with any OneWire devices 42// (not just 43 Maxim/Dallas temperature ICs) 44OneWire oneWire(ONE_WIRE_BUS); 45/********************************************************************/ 46// 47 Pass our oneWire reference to Dallas Temperature. 48DallasTemperature sensors(&oneWire); 49/********************************************************************/ 50DeviceAddress 51 Probe01 = { 0x28, 0xFF, 0x67, 0x18, 0x23, 0x17, 0x04, 0xBF }; //Outdoor Sensor 52DeviceAddress 53 Probe02 = { 0x28, 0xFF, 0xF5, 0x22, 0x23, 0x17, 0x04, 0xD8 }; //Under Stairs Sensor 54DeviceAddress 55 Probe03 = { 0x28, 0xFF, 0xA9, 0xE7, 0x22, 0x17, 0x04, 0x7F }; // Utility Room 56DeviceAddress 57 Probe04 = { 0x28, 0xFF, 0x7D, 0x18, 0x23, 0x17, 0x04, 0x7E };// Under Kitchen 58 59long 60 delayMS; 61long OutdoorTrig = 25; // Trigger Relay if outdoor temp is below 62long 63 OutdoorCut = 26; // Cutoff Relay if outdoor temp is above 64long SinkTrig = 35; 65long 66 SinkCut = 38; 67 68struct package 69{ 70 float temperature = 0; 71 float 72 humidity = 0; 73 float barometer = 0; 74 byte wind = 0; 75 byte maxWind = 76 0; 77 byte windPacketPeak = 0; 78 float rain = 0; 79 float rainRate = 0; 80 81 float randDate = 0; 82 float randTime = 0; 83 float battery = 0; 84 long 85 packetID = 0; 86 float CKSum = 1; 87}; 88 89 90typedef struct package Package; 91Package 92 data; 93Package lastData; 94 95struct postingPackage{ 96 float temperature 97 = 0; 98 float barometer = 0; 99 float humidity = 0; 100 uint8_t avgWind = 101 0; 102 uint8_t peakWindThisRead = 0; 103 float rainThisRead = 0; 104 float rainRate 105 = 0; 106 float battV = 0; 107}; 108 109typedef struct postingPackage PostingPackage; 110 111PostingPackage 112 dataToPost; 113 114bool wxMode; 115 116void setup() { 117 pinMode(13, OUTPUT); 118 119 pinMode(RlyPin, OUTPUT); 120 pinMode(swPin, INPUT); 121 Serial.begin(115200); 122 123 Serial1.begin(57600); 124 HeatControl = false; 125 SuspendData = false; 126 127 //OKtoPost = false;// becomes true after first temperature readings 128 129 130 //Serial.println("Dallas Temperature IC Control Library Demo"); 131 // Start 132 up the library 133 sensors.begin(); 134 lcd.begin(16, 2); 135 // Print a message 136 to the LCD. 137 lcd.print("Pipe Protector 2"); 138 lcd.setCursor(0, 1); 139 140 devCount = sensors.getDeviceCount(); 141 Serial.print("Device Count: "); 142 143 Serial.println(devCount); 144 delayMS = 60000;// WIll increase to 60000 ms when 145 finished. One reading per minute is plenty 146 randomSeed(analogRead(0)); 147 vw_set_rx_pin(receive_pin); 148 149 vw_setup(2000); // Bits per sec 150 vw_rx_start(); // Start the receiver 151 PLL running 152 wxMode = true;// for now, we'll start in weather mode 153 //lastData. 154 155 156 //sensors.requestTemperatures(); 157}// End Setup 158 159void stateSwitch(void) 160 { 161 /* if(delayMS >=50000){ 162 delayMS=10000; 163 } 164 else{ 165 166 delayMS=60000; 167 }*/ 168} 169 170bool SuspendToggle(void) { 171 SuspendData 172 = !SuspendData; 173 return (SuspendData); 174 175} 176 177void sendStatus(void) 178 { 179 String myStr;// Variable to hold all values as text string for sending over 180 serial port 181 myStr = OutdoorTrig; 182 myStr.concat(","); 183 myStr.concat(OutdoorCut); 184 185 myStr.concat(","); 186 myStr.concat(SinkTrig); 187 myStr.concat(","); 188 189 myStr.concat(SinkCut); 190 myStr.concat(","); 191 myStr.concat(delayMS); 192 193 myStr.concat(","); 194 myStr.concat(HeatControl); 195 myStr.concat(","); 196 197 myStr.concat(SuspendData); 198 Serial.println(myStr); 199} 200 201 202 203 204int 205 HighestTemp() { 206 int retVal; 207 for (int cnt = 0; cnt < devCount; cnt++) { 208 209 //int trVal = GetFTempDec(cnt); 210 int trVal = sensors.getTempFByIndex(cnt); 211 212 if (cnt == 0) { 213 214 retVal = trVal; 215 } 216 //Serial.println(sensors.getTempFByIndex(cnt)); 217 218 219 if (retVal < trVal) { 220 retVal = trVal; 221 } 222 } 223 // checkRange(retVal); 224 225 return (retVal); 226} 227 228float LowestTemp() { 229 float retVal; 230 for 231 (int cnt = 0; cnt < devCount; cnt++) { 232 //int trVal = GetFTempDec(cnt); 233 234 int trVal = sensors.getTempFByIndex(cnt); 235 if (cnt == 0) { 236 237 retVal 238 = trVal; 239 } 240 //Serial.println(sensors.getTempFByIndex(cnt)); 241 242 243 if (retVal > trVal) { 244 retVal = trVal; 245 } 246 } 247 // checkRange(retVal); 248 249 return (retVal); 250} 251 252float printTemperature(DeviceAddress deviceAddress) 253{ 254 255 256 float retVal = sensors.getTempF(deviceAddress); 257 258 if (retVal == -196.60) 259 260 { 261 Serial.print(F("<Error>")); 262 } 263 else 264 { 265 266 267 Serial.print(retVal); 268 269 270 Serial.print(F(" F ")); 271 return (retVal); 272 //Serial.print(DallasTemperature::toFahrenheit(tempC)); 273 274 } 275}// End printTemperature 276 277void serial1Check(){ 278String myCmd; 279 280 281 if(Serial1.available() > 0){ 282 Serial.println("You are there"); 283 284 myCmd = Serial1.readString(); 285 Serial.println(myCmd); 286 287 288 } 289 Serial.println("You ARE LEAVING!!"); 290} 291 292void serialCheck(){ 293 294 if (Serial.available() >> 0) { 295 String NewVal = Serial.readString(); 296 297 lcd.clear(); 298 if (NewVal == "+") { 299 //lcd.print("HEAT ON"); 300 301 // delay( 2000); 302 HeatControl = true; 303 304 } 305 else if 306 (NewVal == "-") { 307 lcd.print(F("HEAT OFF")); 308 HeatControl = 309 false; 310 //delay (2000); 311 } 312 else if (NewVal == "S") { 313 314 sendStatus; 315 //delay (2000); 316 } 317 else { 318 long 319 secs = NewVal.toInt(); 320 delayMS = secs * 1000; 321 //lcd.clear(); 322 323 //lcd.print(delayMS); 324 //delay (2000); 325 } 326 // digitalWrite(13,HeatControl); 327 328 } 329} 330 331 332void pipeProtect(){ 333 sensors.requestTemperatures(); // Send 334 the command to get temperature readings 335 336 /********************************************************************/ 337 338 bool RelayOn; 339 RelayOn = digitalRead(RlyPin); 340 digitalWrite(13, 341 HeatControl); // Board LED indicates Heat Control Status 342 if (HeatControl 343 == true) { 344 345 //if (!(t1> OutdoorTrig && t4>SinkTrig)){ 346 347 //if 348 (digitalRead(RlyPin)==false){// Heat status is OFF 349 if (t1 > OutdoorCut) 350 { 351 RelayOn = false; 352 } 353 354 if (t4 > SinkCut) { 355 RelayOn 356 = false; 357 } 358 if (t1 < OutdoorTrig) { 359 RelayOn = true; 360 361 362 } 363 364 if (t4 > 41) { //Absolute cutoff if temp at sink is above 41. 365 No need to heat more that? 366 RelayOn = false; 367 368 } 369 370 371 if (t4 < SinkTrig) { 372 RelayOn = true; 373 374 } 375 digitalWrite(RlyPin, 376 RelayOn); 377 // } 378 } 379 else { 380 digitalWrite(RlyPin, false); 381 382 } 383 384 if (SuspendData == false) { 385 386 Serial.println(F(" ** 387 Temperatures Read **")); 388 389 Serial.print(F("Outdoor temp. is: ")); 390 391 t1 = printTemperature(Probe01); 392 Serial.println(); 393 394 Serial.print(F("Near 395 Furnace temp. is: ")); 396 t2 = printTemperature(Probe02); 397 398 Serial.println(); 399 400 401 Serial.print(F("Under Utility Room temp. is: ")); 402 t3 = printTemperature(Probe03); 403 404 Serial.println(); 405 406 Serial.print(F("Under Sink temp. is: ")); 407 408 t4 = printTemperature(Probe04); 409 String OutLogic; 410 OutLogic 411 = "*&*"; 412 if (digitalRead(RlyPin) == HIGH) { 413 OutLogic.concat("+"); 414 415 } 416 else { 417 OutLogic.concat("-"); 418 } 419 Serial.println(); 420 421 Serial.println(); 422 Serial.println(OutLogic); 423 Serial.println(); 424 425 426 427 } 428 429 lcd.clear(); 430 lcd.setCursor(0, 0); 431 lcd.print(F("O=")); 432 433 lcd.print(t1); 434 lcd.print(F(" F=")); 435 lcd.print(t2); 436 lcd.setCursor(0, 437 1); 438 lcd.print(F("U=")); 439 lcd.print(t3); 440 lcd.print(F(" K=")); 441 442 lcd.print(t4); 443} 444 445 446 447void loop(void) 448{ 449 static bool notFirstIteration; 450 451 static long nextOneWireMillis; 452 if (!notFirstIteration) {// Occurs on first 453 run. 454 nextOneWireMillis = millis() + delayMS; 455 pipeProtect(); 456 457 notFirstIteration = true; 458 } 459 460 if (wxMode == true) {// If monitoring 461 weather station 462 463 //Serial.println("WXMODE TRUE"); 464 rxSubLoop(); 465 466 467 delay(100); 468 if(Serial1.available()>0){ 469 470 Serial.println("Something 471 Returned I think"); 472 while(Serial1.available()){ 473 char c 474 = Serial1.read(); 475 Serial.print(c); 476 } 477 Serial.println("\ 478DDDD\ 479"); 480 481 } 482 483 } 484 // call sensors.requestTemperatures() to issue a global temperature 485 486 // request to all devices on the bus 487 /********************************************************************/ 488 489 //Serial.print("**Requesting temperatures..."); 490 serialCheck();// Check 491 serial ports for incoming commands 492 //serial1Check(); 493 //Serial.println("Out 494 of Serial1Check"); 495 496 497 if (nextOneWireMillis <= millis()) { // This 498 section is for pipe protector portion of program 499 nextOneWireMillis = millis() 500 + delayMS; 501 pipeProtect(); 502 // You can have more than one DS18B20 on 503 the same bus. 504 // 0 refers to the first IC on the wire 505 // delay(delayMS+200); 506 507 } 508 509 510} 511 512
RX_Lib.ino
arduino
Data Receiver Code for Arduino Mega
1 2bool CheckData() { 3 float CkVal = data.humidity + data.temperature 4 + data.barometer + data.wind + data.rain + data.maxWind + data.rainRate + data.packetID 5 + data.windPacketPeak + data.randDate + data.randTime + data.battery; 6 7 bool 8 ckB = ((CkVal == data.CKSum) && (data.CKSum > 30000)); 9 if (ckB == false) { 10 11 data.temperature = 0; 12 data.humidity = 0; 13 data.barometer = 0; 14 15 data.wind = 0; 16 data.rain = 0; 17 data.CKSum = 1; 18 19 } 20 return 21 (ckB); 22 23} 24 25float rainFallRate() { 26 27 28}// END rainFallRate() 29 ********************** 30 31 32float windChill(float mTempF, float mMPH) {// 33 Calculate wind chill if temp <50, wind >3 34 float Twc; 35 if ((mTempF < 50.0) 36 && (mMPH > 3.0)) { 37 Twc = 35.74 + 0.6215 * mTempF - 35.75 * pow(mMPH, 0.16) 38 + 0.4275 * mTempF * pow(mMPH, 0.16); 39 } 40 else 41 { 42 Twc = mTempF;// 43 return temp unchanged if no wind chill 44 } 45 46 return (Twc); 47}// End 48 windChill()--------------------------------------------- 49 50 51float RandianDate(byte 52 dayOfMonth, byte month, byte year) { // Date to integer format - 01-01-1980 becomes 53 111180 54 String myStr; 55 byte myDay = dayOfMonth + 10;// Adding 10 to values 56 to make all 2 digit. No need to do the years. 57 byte myMonth = month + 10; 58 59 byte myYear = year + 10; 60 //month += 10; 61 myStr.concat(myMonth); 62 63 64 myStr.concat(myDay); 65 66 myStr.concat(myYear); 67 68 return (myStr.toFloat()); 69 70 //return(0); 71} 72 73 74float RandianTime(byte hours, byte minutes, byte 75 seconds) { // Time to integer format - 14:56:03 becomes 145603 76 String myStr; 77 78 hours += 10; // Adding 10 to these values to ensure all are 2 digits. 79 minutes 80 += 10; // Will subtract 10 again when decoded 81 seconds += 10; 82 myStr.concat(hours); 83 84 85 myStr.concat(minutes); 86 87 myStr.concat(seconds); 88 89 return (myStr.toFloat()); 90 91 //return(0); 92} 93 94String RandianToDate(float RandDate) { 95 String msg 96 = ""; 97 msg.concat(RandDate); 98 String token; 99 String myDt; 100 int 101 trans; 102 103 for ( int cnt = 0; cnt < 6 ; cnt++) { 104 token.concat(msg.charAt(cnt)); 105 106 if ((cnt == 1) || (cnt == 3)) { 107 trans = token.toInt() - 10; 108 if 109 (trans < 10) { 110 myDt.concat("0"); 111 } 112 myDt.concat(trans); 113 114 myDt.concat("-"); 115 token = ""; 116 } 117 118 else if (cnt 119 == 5) { 120 trans = token.toInt() - 10; 121 myDt.concat("20"); 122 myDt.concat(trans); 123 124 } 125 126 } 127 return (myDt); 128} 129 130String RandianToTime(float RandTime) 131 { 132 String msg = ""; 133 msg.concat(RandTime); 134 String token; 135 String 136 myDt; 137 int trans; 138 139 for ( int cnt = 0; cnt < 6 ; cnt++) { 140 token.concat(msg.charAt(cnt)); 141 142 if ((cnt == 1) || (cnt == 3) || (cnt == 5)) { 143 trans = token.toInt() 144 - 10; 145 if (trans < 10) { 146 myDt.concat("0"); 147 } 148 myDt.concat(trans); 149 150 if (cnt < 5) { 151 myDt.concat(":"); 152 } 153 154 token 155 = ""; 156 } 157 158 159 } 160 return (myDt); 161} 162 163void showReport(void) 164 { 165 Serial.print(F("\ 166Temperature: ")); 167 Serial.print(data.temperature); 168 169 Serial.print(F(" Degrees F\ 170Humidity: ")); 171 Serial.print(data.humidity); 172 173 Serial.print(F("% \ 174Barometer: ")); 175 Serial.print(data.barometer); 176 177 Serial.print(F(" Inches Hg \ 178Wind (current): ")); 179 Serial.print(data.wind); 180 181 Serial.print(F(" Mph\ 182 Feels like ")); 183 Serial.print(windChill(data.temperature, 184 data.wind)); 185 186 Serial.print(F(" Wind Chill\ 187Peak Wind this Read: ")); 188 189 Serial.print(data.windPacketPeak); 190 Serial.print(F(" Mph\ 191Peak Wind Today: 192 ")); 193 Serial.print(data.maxWind); 194 Serial.print(F(" Mph\ 195Rainfall: ")); 196 197 Serial.print(data.rain); 198 Serial.print(F(" Inches\ 199Rain Rate: ")); 200 201 Serial.print(data.rainRate); 202 Serial.print(F(" Inches per Hour\ 203\ 204Packet 205 ID: ")); 206 207 Serial.print(data.packetID); 208 //Serial.print("\ 209Check Sum: 210 "); 211 //Serial.println(data.CKSum); 212 Serial.print(F("\ 213Date: ")); 214 215 Serial.println(RandianToDate(data.randDate)); 216 Serial.print(F("Time: ")); 217 218 Serial.println(RandianToTime(data.randTime)); 219 Serial.println(""); 220 Serial.print(F("Battery: 221 ")); 222 Serial.print(data.battery); 223 Serial.println(F(" Volts\ 224\ 225****************************************\ 226")); 227 228 229 230} 231 232void 233 dataPrep() { // Process incoming data, prepare dataToPost for transmission to network 234 interface. Average some values 235 236 //static bool firstSeries; 237 static 238 int avgCounter; 239 static float tempAvg; 240 static int windAvg; 241 static 242 int windPeak; 243 static int windRing[10]; 244 static float tempRing[10];// the 245 "Ring arrays keep the last 10 readings for averaging, constatly rotating through 246 247 static float rainVals[10]; 248 static float barVals[10]; 249 static float humVals[10]; 250 251 float tempTot; 252 float batt; 253 float rainfallRate; 254 static int clearCount; 255 256 257 if (avgCounter == 0) { // Reset some vals for next post 258 windPeak = 0; 259 260 for (int ct; ct < 10 ; ct++) { 261 rainVals[ct] = 0; 262 tempRing[ct] 263 = 0; 264 tempTot = 0; 265 } 266 267 } 268 windRing[avgCounter] = data.wind; 269 270 if (data.windPacketPeak > windPeak) { 271 windPeak = data.windPacketPeak; 272 273 } 274 tempRing[avgCounter] = data.temperature; 275 humVals[avgCounter] = data.humidity; 276 277 barVals[avgCounter] = data.barometer; 278 rainVals[avgCounter] = data.rain;// 279 - lastData.rain;// Rain measurement from station is a daily total-we need to calculate 280 rain per package 281 String trTime = RandianToTime(data.randTime); 282 bool saveNOW 283 = (trTime.charAt(4) == '0') && (avgCounter > 0);// will cause update at least every 284 10 packets, but should keep it at 00 minutes 285 if ((avgCounter == 9)|| (saveNOW)) 286 { //Last of data packets. Prepare values, insert into dataToPost, then send to Network 287 Interface 288 float rainTot; 289 float windTot; 290 float humTot; 291 float 292 barTot; 293 // int tempTot; 294 for (int ct = 0; ct < avgCounter+1 ; ct++) 295 { 296 rainTot = rainVals[ct];// for rain, just use last reading sent. No need 297 to average, will send as total for day 298 windTot += windRing[ct]; 299 tempTot 300 += tempRing[ct]; 301 barTot += barVals[ct]-28.00;// Subtracting out lowest 302 likely reading. Averaging difference to increase accuracy in the event of errors 303 304 humTot += humVals[ct]; 305 /* Serial.println(); 306 Serial.print(tempRing[ct]); 307 308 Serial.print(" "); 309 Serial.println(tempTot); 310 //Serial.println(); 311 312 */ 313 } 314 avgCounter ++;// increment for calculating averages (due 315 to zero based array counter) 316 dataToPost.battV = data.battery; 317 dataToPost.temperature 318 = tempTot / float(avgCounter); 319 dataToPost.barometer = (barTot / float(avgCounter))+28.00; 320 321 dataToPost.humidity = humTot / float(avgCounter); 322 dataToPost.avgWind 323 = windTot / (avgCounter); 324 dataToPost.peakWindThisRead = windPeak; 325 dataToPost.rainThisRead 326 = rainTot; 327 dataToPost.rainRate = data.rainRate; 328 Serial.println(F("\ 329~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")); 330 331 Serial.print(F("\ 332Data to Post:\ 333")); 334 Serial.println(dataToPost.temperature); 335 336 Serial.println(dataToPost.barometer); 337 Serial.println(dataToPost.humidity); 338 339 Serial.println(dataToPost.avgWind); 340 Serial.println(dataToPost.peakWindThisRead); 341 342 Serial.println(dataToPost.rainThisRead); 343 Serial.println(F("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~\ 344")); 345 346 delay (2000); 347 String url = "@";// add start character 348 url += 349 String(dataToPost.temperature); 350 url += ",2="; 351 url += String(dataToPost.humidity); 352 353 url += ",3="; 354 url += String(dataToPost.avgWind); 355 url += ",4="; 356 357 url += String(dataToPost.peakWindThisRead); 358 url += ",5="; 359 url 360 += String(dataToPost.rainThisRead); 361 url += ",6="; 362 url += String(dataToPost.barometer); 363 364 url += ",7="; 365 url += String(dataToPost.rainRate); 366 url += ",8="; 367 368 url += String(dataToPost.battV); 369 url += "~";// add end character 370 371 372 String datStr; 373 datStr.concat(dataToPost.temperature); 374 datStr.concat(","); 375 376 datStr.concat(dataToPost.humidity); 377 datStr.concat(","); 378 datStr.concat(dataToPost.avgWind); 379 380 datStr.concat(","); 381 datStr.concat(dataToPost.peakWindThisRead); 382 383 datStr.concat(","); 384 datStr.concat(dataToPost.rainThisRead); 385 datStr.concat(","); 386 387 datStr.concat(dataToPost.barometer); 388 Serial.println (datStr); 389 Serial1.print(url);// 390 This line is where data is submitted to Network Interface (NodeMCU) 391 delay(10000); 392 // Lets wait a little while then 393 Serial1.print(url);// Send again 394 to minimize data gaps due to errors in transmission 395 396 avgCounter = 397 -1; 398 // Serial.print("IN the Test"); 399 } 400 401 avgCounter ++; 402 403 if (avgCounter > 9) { 404 avgCounter = 0; 405 } 406 407 408} 409 410 411void 412 simulateData() { 413 static long cnt; 414 415 data.temperature = t1; 416 data.humidity 417 = t2; 418 data.barometer = t3; 419 data.wind = random(t4); 420 data.maxWind = 421 t4 + random(0, 21); 422 data.windPacketPeak = t4 + random(0, 21); 423 data.rain 424 = t1; 425 data.rainRate = t2; 426 data.randDate = 101218; 427 data.randTime = 428 131313; 429 data.packetID = cnt; 430 cnt ++; 431 432} 433 434 435 436void rxSubLoop(void) 437 { 438 439 // Serial.println("In the rxSubLoop"); 440 uint8_t buf[sizeof(data)]; 441 442 uint8_t buflen = sizeof(data); 443 //Serial.println("in Loop"); 444 //vw_wait_message(); 445 446 if (vw_have_message()) // Is there a packet for us? 447 { 448 vw_get_message(buf, 449 &buflen); 450 memcpy(&data, &buf, buflen); 451 // delay(500); 452 bool 453 myCkV = CheckData();// Check for valid Packet-return true if valid 454 if (myCkV 455 == true) { 456 457 if (data.packetID != lastData.packetID) { 458 dataPrep(); 459 460 showReport(); 461 462 lastData = data; 463 464 } 465 466 467 468 } 469 else { 470 Serial.print(F("Bad Packet")); 471 Serial.print(F("\ 472\ 473****************************************\ 474\ 475")); 476 477 } 478 479 } 480 /*else{//A place to add a line for data simlation-for devel 481 purposes 482 // This ELSE clause will be commented out after new transmitter 483 comes in 484 485 simulateData(); 486 dataPrep(); 487 showReport(); 488 489 490 lastData = data; 491 492 delay(30000);// want data packets simulated every 493 1 minute 494 //Serial.println("Exiting RX_Lib"); 495 }*/ 496 497 498 499 500} 501
Wx-Tx.ino
arduino
Code for weather station sensors/transmitter
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 8#include <avr/power.h> 9#include <avr/sleep.h> 10#include <avr/wdt.h> 11 12 13#define DS3231_I2C_ADDRESS 0x68 14#define OFF false 15#define ON true 16#define TOGGLE 2// Use if you want to toggle a value instead of just ON/OFF/TRUE/FALSE-for radio function 17dht myDHT; // create instance of DHT sensor 18Adafruit_MPL3115A2 baro = Adafruit_MPL3115A2();// Create instance of Barometric sensor 19 20 21time_t myTime;// Is System Time Object 22time_t upTime;// Contains time System Timer was set 23 24const uint8_t ledPin = 13; 25const uint8_t transmit_pin = 11; 26const uint8_t rainPin = 2;// Wind and rain readings handled by interrupts 27const uint8_t windPin = 3; // Wind and rain readings handled by interrupts 28const uint8_t dhtPin = 4; 29const uint8_t rfPower = 5;// control line for RF Power Relay 30 31const float rainPerTip = .0202;// Specific to dimensions of rain gauge built 32const int timeComp = -1516;// Value for periodic time compensation. After this many seconds, 33// 1 second adjustment is added or subtracted for on the fly Sys Clock a Correction 34// Value was computed after 24 hours running, to determine approximate adjustment value. 35// This may be further refined as I use unit for longer periods of time. 36float rainInches; 37volatile long rainLastMillis; // Millis of previous rain "tip" 38volatile long rainMillis; // Millis of current rain tip 39float windAdj = 9.5; //default value for wind speed (Anemometer) adjustment 40volatile long windLastMillis; // last millis reading from anemometer 41volatile long revTime; // time in millis of current anemometer revolution 42volatile int f_wdt = 1; 43volatile long nextSleepMillis; 44volatile long wokeUpMillis; 45 46long xmitRate = 60000; // xmitRate is how often packets will be transmitted, in milliseconds. 47int tipCount; // Rain gauge bucket "tips", .0202 inch per tip for my gauge. Resets at midnight 48float tempDHT; // Temperature from DHT 49float humDHT; // Humidity from DHT 50float curWindMPH; // Calculated wind speed 51float topWind; 52bool needsReset; // Set to true at 11:59 PM, to trigger reset at midnight 53bool baroSensorPresent; // Set to true if barometric pressure sensor is detected at startup 54long timeCompTrigger;// value of next time compensation in millis 55bool serialDump; 56bool testMode; 57byte testMinutes = 2; 58 59byte ckHour;// ckHour and ckMinute are used to see if time to reset (at midnight) 60byte ckMinute; 61byte ckSecond; 62volatile bool beenAsleep; 63 64struct package 65{ 66 float temperature ; 67 float humidity ; 68 float barometer ; 69 byte wind ; 70 byte maxWind; 71 byte windPacketPeak; 72 float rain ; 73 float rainRate; 74 float randDate; 75 float randTime; 76 float battery; 77 long packetID; 78 float CKSum ; 79}; 80 81 82typedef struct package Package; 83Package data; 84 85//DHT dht(DHTPIN, DHTTYPE); 86 87void setup() 88{ 89 testMode = true; // Will start in test mode, this will time out in 5 minutes. Helps aim antenna 90 beenAsleep = false; 91 serialDump = testMode; 92 // Initialise the IO and ISR 93 vw_set_tx_pin(transmit_pin); 94 vw_set_ptt_inverted(true); // Required for DR3100 95 vw_setup(2000); // Bits per sec 96 Serial.begin(9600); 97 Serial.println(F("Working to setup")); 98 99 Wire.begin(); 100 //serialDump = false; 101 //serialDump = true; 102 baroSensorPresent = true; 103 if (! baro.begin()) { 104 Serial.println(F("Couldnt find sensor")); 105 baroSensorPresent = false; 106 //return; 107 } 108 else { 109 110 baro.write8(0x2D, 0x23);// calibration for altitude 111 } 112 113 pinMode (rainPin, INPUT_PULLUP); 114 pinMode (dhtPin, INPUT); 115 pinMode(ledPin, OUTPUT); 116 pinMode (windPin, INPUT_PULLUP); 117 pinMode(rfPower, OUTPUT); 118 attachInterrupt(0, rain_Count, FALLING);// Define interrupt pins and processes required 119 attachInterrupt(1, wind_Count, FALLING); 120 121 //needsReset = true;// used in testing only 122 tipCount = 0;// Initial value 0 "tips", 0 inches of rain 123 rainInches = 0; 124 revTime = 0; 125 readDHT(); 126 /*** Setup the WDT ***/ 127 128 /* Clear the reset flag. */ 129 MCUSR &= ~(1 << WDRF); 130 131 /* In order to change WDE or the prescaler, we need to 132 set WDCE (This will allow updates for 4 clock cycles). 133 */ 134 WDTCSR |= (1 << WDCE) | (1 << WDE); 135 136 /* set new watchdog timeout prescaler value */ 137 WDTCSR = 1 << WDP0 | 1 << WDP3; /* 8.0 seconds */ 138 139 /* Enable the WD interrupt (note no reset). */ 140 WDTCSR |= _BV(WDIE); 141 142 143 delay(2000);// Delay to prevent re-read of DHT prematurely after startup 144 radio(OFF); 145 146} // END Setup() ******************* 147 148//!!!!!!!!!!!!!!!!!! The following 3 functions are used by RTC. DO NOT CHANGE !!!!!!!!!!!!!!!!!!! 149byte decToBcd(byte val) 150{ 151 return ( (val / 10 * 16) + (val % 10) ); 152} 153// Convert binary coded decimal to normal decimal numbers 154byte bcdToDec(byte val) 155{ 156 return ( (val / 16 * 10) + (val % 16) ); 157} 158 159 160void readRTCTime(byte *second, 161 byte *minute, 162 byte *hour, 163 byte *dayOfWeek, 164 byte *dayOfMonth, 165 byte *month, 166 byte *year) 167{ 168 Wire.beginTransmission(DS3231_I2C_ADDRESS); 169 Wire.write(0); // set DS3231 register pointer to 00h 170 Wire.endTransmission(); 171 Wire.requestFrom(DS3231_I2C_ADDRESS, 7); 172 // request seven bytes of data from DS3231 starting from register 00h 173 *second = bcdToDec(Wire.read() & 0x7f); 174 *minute = bcdToDec(Wire.read()); 175 *hour = bcdToDec(Wire.read() & 0x3f); 176 *dayOfWeek = bcdToDec(Wire.read()); 177 *dayOfMonth = bcdToDec(Wire.read()); 178 *month = bcdToDec(Wire.read()); 179 *year = bcdToDec(Wire.read()); 180} 181 182 183// !!!!!!!!!!!!!!!! END OF DO NOT CHANGE SECTION !!!!!!!!!!!!!!!!!!!!!!!!!!! 184 185// ** INTERRUPT PROCESSOR SECTION ** 186//************************************************************* 187 188void rain_Count() { // Interrupt Process for Rain Gauge Tip Counting 189 rainLastMillis = rainMillis; 190 rainMillis = millis(); 191 tipCount ++; // All we aneed to do here is increment the tip counter 192} // END of Interrupt Processor rain_Count -------------------- 193 194// ************************************************************ 195//************************************************************* 196 197void wind_Count() { // Interrupt Process for Wind measuring 198 if (beenAsleep) { 199 /* 200 nextSleepMillis = millis() + 10000;// wait 10 seconds to see if another wind pulse comes in before sleeping again. 201 windLastMillis = nextSleepMillis - 10000; 202 */ 203 //long adj = 15; 204 long myVal = millis(); 205 //long newRevTime = myVal - windLastMillis; 206 nextSleepMillis = myVal + 9000;// stay awake for a little while to wait for more wind pulses. 207 if (1) { //(((curWindMPH > 8) && (newRevTime < revTime/2)) || ((curWindMPH <8) && (newRevTime < revTime/3))) {// Probably Noise-ignore pulse 208 209 } 210 211 else { 212 213 revTime = myVal - windLastMillis; 214 windLastMillis = myVal; 215 nextSleepMillis = myVal + 12000; 216 } 217 218 } 219 else { 220 long myVal = millis(); 221 long newRevTime = myVal - windLastMillis; 222 if (((curWindMPH > 8) && (newRevTime < revTime/2)) || ((curWindMPH <8) && (newRevTime < revTime/3))) {// Probably Noise-ignore pulse 223 224 } 225 226 else { 227 228 revTime = myVal - windLastMillis; 229 windLastMillis = myVal; 230 } 231 232 } 233 234 //Serial.println("TRIGGERED"); 235 //} 236 237} // END of Interrupt Processor wind_Count 238 239 240ISR(WDT_vect)// Watchdog timer interrupt routine 241{ 242 if (f_wdt == 0) 243 { 244 f_wdt = 1; 245 } 246 else 247 { 248 //Serial.println("WDT Overrun!!!"); 249 } 250} 251 252 253// ************************************************************ 254 255void sleepNow() 256{ 257 Serial.println(F("Going to sleep now")); 258 // Choose our preferred sleep mode: 259 set_sleep_mode(SLEEP_MODE_IDLE); 260 261 // Set sleep enable (SE) bit: 262 sleep_enable(); 263 power_adc_disable(); 264 power_spi_disable(); 265 power_timer0_disable(); 266 power_timer2_disable(); 267 power_twi_disable(); 268 // Put the device to sleep: 269 sleep_mode(); 270 271 // Upon waking up, sketch continues from this point. 272 sleep_disable(); 273 Serial.println(F("GOOD MORNING VIET NAM!")); 274 power_all_enable(); 275} 276 277 278void radio(uint8_t action) { 279 int pwrOnDly = 500; 280 if (action < 2) { 281 282 digitalWrite(rfPower, action); // If action = ON or OFF, comply 283 if (action == ON) { 284 delay(pwrOnDly);// Give radio a moment to power up before using0 285 } 286 287 } 288 else { 289 digitalWrite(rfPower, !digitalRead(rfPower)); // Otherwise Toggle 290 delay(pwrOnDly);// see above 291 } 292} 293 294float readBattery(void) { 295 float chipVoltage = 5.096;// Set this value to the measured voltage on 5 v pin on Arduino, USING EXPECTED POWER SUPPLY!! 296 int sum = 0; // sum of samples taken 297 unsigned char sample_count = 0; // current sample number 298 // take a number of analog samples and add them up 299 while (sample_count < 10) { 300 sum += analogRead(A1); 301 sample_count++; 302 303 delay(10); 304 } 305 float voltage = ((float)sum / 10.0 * chipVoltage ) / 1024.0; 306 // Serial.println(voltage * 1.922); 307 return (voltage * 2); 308} 309 310void readDHT() { 311 312 static long nextReadMillis; 313 if (millis() >= nextReadMillis) { 314 int readData = myDHT.read22(dhtPin); 315 tempDHT = myDHT.temperature * 1.8 + 32; 316 humDHT = myDHT.humidity; 317 nextReadMillis = millis() + 2000;// DHT can only be read every 2 seconds. This variable prevents premature readings 318 } 319 320}// END of readDHT()------------------------------------------- 321 322void rain_Set(float myVal) {// Set rain to a specific value, used if restarting during day with rain 323 324 rainInches = myVal; 325 tipCount = rainInches / rainPerTip; 326 rainLastMillis = 0; 327 Serial.println(""); 328 Serial.print(F("Rainfall Measurement SET to ")); 329 Serial.print(myVal); 330 Serial.println(F(" Imches\ 331")); 332}// END of rain_Set()----------------------------------------- 333 334void rain_Reset() { 335 336 tipCount = 0; 337 rainInches = 0; 338 rainLastMillis = 0; 339 Serial.println(""); 340 Serial.println(F("Rainfall Measurement RESET!\ 341")); 342 Serial.println(F("")); 343 344 345}// END of rain_Reset()----------------------------------------- 346 347void wind_Reset() { 348 349 topWind = 0; 350 Serial.println(); 351 Serial.println(F("Maximum Wind RESET!\ 352")); 353 Serial.println(); 354 355 356}// END of wind_Reset()----------------------------------------- 357 358void all_Reset() { 359 360 wind_Reset(); 361 rain_Reset(); 362 363 364}// END of all()----------------------------------------- 365 366 367float RandianDate(byte dayOfMonth, byte month, byte year) { // Date to integer format - 01-01-1980 becomes 111180 368 String myStr; 369 byte myDay = dayOfMonth + 10;// Adding 10 to values to make all 2 digit. No need to do the years. 370 byte myMonth = month + 10; 371 byte myYear = year + 10; 372 //month += 10; 373 myStr.concat(myMonth); 374 375 myStr.concat(myDay); 376 377 myStr.concat(myYear); 378 379 return (myStr.toFloat()); 380 //return(0); 381} 382 383 384float RandianTime(byte hours, byte minutes, byte seconds) { // Time to integer format - 14:56:03 becomes 145603 385 String myStr; 386 hours += 10; // Adding 10 to these values to ensure all are 2 digits. 387 minutes += 10; // Will subtract 10 again when decoded 388 seconds += 10; 389 myStr.concat(hours); 390 391 myStr.concat(minutes); 392 393 myStr.concat(seconds); 394 395 return (myStr.toFloat()); 396 //return(0); 397} 398 399String RandianToDate(float RandDate) { 400 String msg = ""; 401 msg.concat(RandDate); 402 String token; 403 String myDt; 404 int trans; 405 406 for ( int cnt = 0; cnt < 6 ; cnt++) { 407 token.concat(msg.charAt(cnt)); 408 if ((cnt == 1) || (cnt == 3)) { 409 trans = token.toInt() - 10; 410 if (trans < 10) { 411 myDt.concat("0"); 412 } 413 myDt.concat(trans); 414 myDt.concat("-"); 415 token = ""; 416 } 417 418 else if (cnt == 5) { 419 trans = token.toInt() - 10; 420 myDt.concat("20"); 421 myDt.concat(trans); 422 } 423 424 } 425 return (myDt); 426} 427 428String RandianToTime(float RandTime) { 429 String msg = ""; 430 msg.concat(RandTime); 431 String token; 432 String myDt; 433 int trans; 434 435 for ( int cnt = 0; cnt < 6 ; cnt++) { 436 token.concat(msg.charAt(cnt)); 437 if ((cnt == 1) || (cnt == 3) || (cnt == 5)) { 438 trans = token.toInt() - 10; 439 if (trans < 10) { 440 myDt.concat("0"); 441 } 442 myDt.concat(trans); 443 if (cnt < 5) { 444 myDt.concat(":"); 445 } 446 447 token = ""; 448 } 449 450 451 } 452 return (myDt); 453} 454 455void stampTime(void) { 456 String dateStr; 457 String timeStr; 458 byte second; 459 byte minute; 460 byte hour; 461 462 byte dayOfWeek; 463 byte dayOfMonth; 464 byte month; 465 byte year; 466 readRTCTime(&second, &minute, &hour, &dayOfWeek, &dayOfMonth, &month, 467 &year); 468 ckMinute = minute; 469 ckHour = hour; 470 ckSecond = second; 471 data.randDate = RandianDate(dayOfMonth, month, year); 472 data.randTime = RandianTime(hour, minute, second); 473 /* 474 Serial.print("Hour: "); 475 Serial.print(hour); 476 Serial.print(" Minute: "); 477 Serial.print(minute); 478 Serial.print(" Second "); 479 Serial.print(second); 480 Serial.print("\ 481\ 482"); 483 Serial.println(data.randTime); 484 485 //Serial.println(data.randTime); 486 Serial.println(data.randDate); 487 488 */ 489 490 491} 492 493void serialReport(void) { 494 Serial.print("\\Temperature: "); 495 Serial.print(data.temperature); 496 Serial.print(F(" Degrees F\ 497Humidity: ")); 498 Serial.print(data.humidity); 499 Serial.print(F("% \ 500Barometer: ")); 501 Serial.print(data.barometer); 502 Serial.print(F(" Inches Hg \ 503Wind (current): ")); 504 Serial.print(data.wind); 505 Serial.print(F(" Mph\ 506Peak Wind this Read: ")); 507 Serial.print(data.windPacketPeak); 508 Serial.print(F(" Mph\ 509Peak Wind Today: ")); 510 Serial.print(data.maxWind); 511 Serial.print(F(" Mph\ 512Rainfall: ")); 513 Serial.print(data.rain); 514 Serial.print(F(" Inches\ 515Rain Rate: ")); 516 Serial.print(data.rainRate); 517 Serial.print(F(" Inches per Hour\ 518Packet ID: ")); 519 Serial.print(data.packetID); 520 Serial.print(F("\ 521Check Sum: ")); 522 Serial.println(data.CKSum); 523 Serial.print(F("Date: ")); 524 Serial.print(RandianToDate(data.randDate)); 525 Serial.print(F("\ 526Time: ")); 527 Serial.println(RandianToTime(data.randTime)); 528 Serial.print(F("Battery Voltage: ")); 529 Serial.print(data.battery); 530 Serial.print(F(" Vdc\ 531\ 532")); 533 534 if (testMode == true) { 535 536 537 Serial.print(F("** TEST MODE ** TEST MODE **\ 538\ 539")); 540 } 541} 542 543float CheckSum() { // A Check to ensure valid packet received. Basic Check Sum (Sum of all fields-all are numeric) 544 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); 545} // END CheckSum ************************** 546 547 548void setDS3231time(byte second, byte minute, byte hour, byte dayOfWeek, byte 549 dayOfMonth, byte month, byte year) 550{ 551 // sets time and date data to DS3231 552 Wire.beginTransmission(DS3231_I2C_ADDRESS); 553 Wire.write(0); // set next input to start at the seconds register 554 Wire.write(decToBcd(second)); // set seconds 555 Wire.write(decToBcd(minute)); // set minutes 556 Wire.write(decToBcd(hour)); // set hours 557 Wire.write(decToBcd(dayOfWeek)); // set day of week (1=Sunday, 7=Saturday) 558 Wire.write(decToBcd(dayOfMonth)); // set date (1 to 31) 559 Wire.write(decToBcd(month)); // set month 560 Wire.write(decToBcd(year)); // set year (0 to 99) 561 Wire.endTransmission(); 562} 563 564void sendData() { // Send data packet by RF transmitter 565 radio(ON); 566 digitalWrite(ledPin, HIGH); // Flash a light to show transmitting 567 //readSensors(); now doing in loop, not here - prevents differences in "same" packet sends 568 vw_send((uint8_t *)&data, sizeof(data)); 569 vw_wait_tx(); // Wait until the whole message is gone 570 digitalWrite(ledPin, LOW); 571 // delay(2000); 572 radio(OFF); 573}// END sendData ******************* 574 575 576void readSensors()// Read all sensors and build data package 577{ 578 579 readDHT(); 580 data.humidity = humDHT; 581 data.temperature = tempDHT; 582 data.barometer = baroReading(); 583 data.wind = Wind_Speed(); 584 585 data.maxWind = topWind; 586 587 data.rainRate = rainFallRate(); 588 data.rain = rainInches; 589 data.battery = readBattery(); 590 data.CKSum = CheckSum(); 591} // END readSensors() ****************************** 592 593 594float rainFallRate() { 595 if (tipCount > 0) { 596 597 float tipDuration = rainMillis - rainLastMillis; 598 if (millis() > rainMillis + 600000) {// no new tips in last 10 minutes 599 tipDuration = millis() - rainLastMillis; 600 } 601 602 if (tipDuration > 120 * 60000) { // tip takes over 2 hour2, effective rate 0 for our purposes 603 return (0); 604 } 605 else { 606 float tipSeconds = tipDuration / 1000.00; 607 float tipsPerHour = 3600.00 / tipSeconds; 608 609 return ( rainPerTip * tipsPerHour); 610 } 611 612 } 613 else { 614 return (0); 615 } 616 617 618} 619 620float baroReading() { 621 if (baroSensorPresent == true) { 622 float pascals = baro.getPressure(); 623 // Our weather page presents pressure in Inches (Hg) 624 // Use http://www.onlineconversion.com/pressure.htm for other units 625 // Serial.print(pascals/3377); Serial.println(" Inches (Hg)"); 626 return ((pascals / 3377.00) + 0.87); // 0.87 is barometric adjustment 627 628 } 629 else { 630 return (99.99); // bogus reading if sensor not detected. 631 632 } 633 634 635}// End baroReading() ---------------------------------------------- 636 637/* 638 float rainfallRate() { 639 float tipDuration = rainMillis - rainLastMillis; 640 float tipSeconds = tipDuration / 1000; 641 float tipsPerHour = 3600 / tipSeconds; 642 float myRainRate = rainPerTip * tipsPerHour; 643 return (myRainRate); 644 }// END of RainfallRate() ************************ 645*/ 646int Wind_Speed() { 647 648 float retValF = 717.00 * windAdj / (revTime); 649 650 if (millis() >= windLastMillis + 10000) { // No wind pulses in 10 seconds, wind is effectively 0 651 retValF = 0.00; 652 } 653 curWindMPH = retValF; 654 if (data.windPacketPeak < retValF){ 655 data.windPacketPeak = retValF; 656 } 657 if (topWind<data.wind){ 658 topWind = data.wind; 659 660 } 661 return retValF; 662 663}// END of Wind_Speed() --------------------------------------------- 664 665 666float baroTempReading() { 667 668 float tempF = baro.getTemperature() * 1.8 + 32; 669 //Serial.println(tempF); 670 //Serial.println(tempF); 671 return (tempF); 672 // Serial.print(tempC); Serial.println("*C"); 673 674}// End baroTempReading() ----------------------------------------- 675 676void showHelp() { 677 678 Serial.println(F("- Valid Serial Commands -")); 679 Serial.println(F("W ## - Sets Max Wind to ##")); 680 Serial.println(F("I ## - Interval in seconds - Sets Packet Interval")); 681 Serial.println(F("R ## - Sets Rainfall")); 682 Serial.println(F("+ Wind Adj up 1")); 683 Serial.println(F("- Wind Adj down 1")); 684 Serial.println(F("XW - Max Wind Reset")); 685 Serial.println(F("XR - Rainfall Reset")); 686 Serial.println(F("XX - ALL Reset")); 687 Serial.println(F("S - Toggle Serial Dump Mode")); 688 Serial.println(F("\ 689** ? - Shows This Help Screen **")); 690}// END showHelp()------------------------------------------------ 691 692 693void checkSerial(void) { 694 if (Serial.available() > 0) { // Check for and Begin Processing of incoming Serial commands 695 String myCmd = Serial.readString(); 696 char myChr = myCmd.charAt(0); 697 698 if ((myChr == 'W') || (myChr == 'w')) { // "w" should be followed by a number to set max wind to 699 700 myCmd.replace("w", ""); 701 myCmd.replace("W", ""); 702 myCmd.replace(",", ""); 703 myCmd.replace(" ", ""); 704 float newWind = myCmd.toFloat(); 705 data.maxWind = newWind; 706 topWind = newWind; 707 708 } 709 if ((myChr == 'I') || (myChr == 'i')) { // "I" should be followed by a number to set data transmission interval 710 711 myCmd.replace("i", ""); 712 myCmd.replace("I", ""); 713 myCmd.replace(",", ""); 714 myCmd.replace(" ", ""); 715 float newInterval = myCmd.toFloat(); 716 xmitRate = newInterval * 1000;// entry will be in seconds, converting to millis() 717 718 } 719 if ((myChr == 'R') || (myChr == 'r')) { // "R" should be followed by a number to set rainfall 720 myCmd.replace("r", ""); 721 myCmd.replace("R", ""); 722 myCmd.replace(",", ""); 723 myCmd.replace(" ", ""); 724 float rcmd = myCmd.toFloat(); 725 if (rcmd > 0) { // If number is entered, set rainfall to that, else add 1 tip 726 rain_Set(rcmd); 727 } 728 else { 729 rain_Count(); 730 731 } 732 733 } 734 if ((myChr == 'S') || (myChr == 's')) { // toggles Serial Dump mode 735 736 serialDump = !serialDump; 737 } 738 739 if (myChr == '+') { 740 741 windAdj ++; 742 Serial.print(F("Wind Adj = ")); 743 Serial.println(windAdj); 744 } 745 if (myChr == '-') { 746 windAdj --; 747 Serial.print(F("Wind Adj = ")); 748 Serial.println(windAdj); 749 } 750 if (myChr == '!') { // Toggle Test Mode 751 752 testMode = !testMode; 753 serialDump = testMode; 754 Serial.print(F("Toggling Test Mode - Mode=")); 755 Serial.println(testMode); 756 } 757 if (myChr == '?') { 758 showHelp(); 759 } 760 } 761 762}// END checkSerial() ***************************************** 763 764 765void enterSleep(void) 766{ 767 set_sleep_mode(SLEEP_MODE_PWR_SAVE); 768 wdt_reset(); 769 sleep_enable(); 770 771 772 /* Disable all of the unused peripherals. This will reduce power 773 consumption further and, more importantly, some of these 774 peripherals may generate interrupts that will wake our Arduino from 775 sleep! 776 */ 777 power_adc_disable(); 778 power_spi_disable(); 779 power_timer0_disable(); 780 power_timer2_disable(); 781 power_twi_disable(); 782 beenAsleep = true; 783 /* Now enter sleep mode. */ 784 sleep_mode(); 785 786 /* The program will continue from here after the timer timeout*/ 787 sleep_disable(); /* First thing to do is disable sleep. */ 788 power_all_enable(); 789 //wokeUpMillis = millis()-10; 790 /* Re-enable the peripherals. */ 791 792} 793 794 795void loop() 796{ 797 798 799 static int oldTipCount;//Use to check if a Rain "Tip" has generated an Interrupt response 800 static long nextSendMillis; 801 static byte nextSendSecond; 802 static byte nextSendMinute; 803 static long packetCount; 804 static float maxWindThisPkt; 805 long initTestEnd = long(60000 * testMinutes); 806 static bool doneFirstLoop; 807 808 // Serial.println("SofarSOgood"); 809 //initTestEnd = 0;// Testing line-to be removfed 810 stampTime();// called here to check time for reset at midnight. stampTime updates values in ckHour, ckMinute, ckSecond 811 if (!doneFirstLoop) { // first iteration. Set up a few things for future iterations 812 if (xmitRate >= 60000) { 813 nextSendMinute = ckMinute + (xmitRate / 60000); 814 nextSendSecond = 00;//ckSecond; 815 816 } 817 else if (xmitRate < 60000) { 818 nextSendMinute = ckMinute; 819 nextSendSecond = ckSecond + xmitRate / 1000; 820 } 821 822 doneFirstLoop = true; 823 824 } 825 826 if ((millis() >= initTestEnd) && (millis() <= initTestEnd + 60000)) { 827 testMode = false; 828 829 } 830 831 if ((needsReset == false) && (ckHour == 23) && (ckMinute == 59)) { 832 needsReset = true; 833 //rain_Reset(); 834 } 835 836 if ((needsReset == true) && (ckMinute < 5)) { 837 all_Reset();// Resets Rain, wind Counter, stores todays values as yesterday at midnight, ready for a brand new day! 838 needsReset = false; 839 840 // ********************************************************************************* 841 } 842 843 checkSerial(); 844 //serialReport; 845 if (xmitRate < 5000) { // Don't allow less than 5 second interval. 846 xmitRate = 5000; 847 } 848 849 rainInches = tipCount * rainPerTip; 850 readSensors(); 851 if (maxWindThisPkt <= data.wind) { 852 maxWindThisPkt = data.wind; 853 if ((data.maxWind < maxWindThisPkt) && (maxWindThisPkt < 120)) { // if maxWindThisPkt >120, either data is corrupted, *OR* 854 data.maxWind = maxWindThisPkt;// Weather Station is being destroyed by tornado 855 topWind = data.maxWind; 856 } 857 858 } 859 860 /* 861 Serial.println("---"); 862 Serial.println(ckMinute); 863 Serial.println(nextSendMinute); 864 Serial.println(ckSecond); 865 Serial.println(nextSendSecond); 866 Serial.println("---"); 867 */ 868 869 if (((ckMinute >= nextSendMinute) && (ckSecond >= nextSendSecond)) || (testMode == true)) { // Time to send data packet. 870 if ((ckMinute == 59) && (nextSendMinute == 0)) { //Problem condition-need to skip 871 872 } 873 else { 874 875 876 data.windPacketPeak = maxWindThisPkt; 877 maxWindThisPkt = 0; 878 packetCount ++; 879 nextSendMillis = millis() + xmitRate; 880 stampTime(); 881 data.packetID = packetCount; 882 readSensors(); 883 for (int cnt = 0; cnt < 2 ; cnt++) { // Send each packet 3 times, to hopefully eliminate/minimize lost packets. 884 sendData(); 885 //d+elay(500);// NO longer needed, delays built into SendData for turning radio on. 886 } 887 if (serialDump == true) { 888 serialReport(); 889 } 890 891 if (xmitRate >= 60000) { 892 nextSendMinute = (xmitRate / 60000) + ckMinute; 893 //nextSendSecond = ckSecond; 894 if (nextSendMinute > 59) { 895 nextSendMinute -= 60; 896 } 897 898 } 899 else if (xmitRate < 60000) { 900 //nextSendMinute = ckMinute; 901 nextSendSecond = ckSecond + xmitRate / 1000; 902 if (nextSendSecond > 59) { 903 nextSendSecond -= 60; 904 } 905 } 906 907 } 908 909 }//******* 910 911 if ((!testMode) && (millis() > nextSleepMillis)) { 912 913 914 Serial.println("Sleeping"); 915 delay(300); 916 beenAsleep = true; 917 enterSleep(); 918 beenAsleep = false; 919 Serial.println("Back to Life"); 920 } 921 //*/ 922 // 923}/// END OF LOOP!!!! 924 925
Comments
Only logged in users can leave comments
randtekk
0 Followers
•0 Projects
Table of contents
Intro
35
0