From 357607fbe9159afef9ba89f1dbe86abe7966efc8 Mon Sep 17 00:00:00 2001
From: Roman Bazalevskiy <rvb@rvb.name>
Date: Sat, 3 Sep 2016 18:15:05 +0300
Subject: [PATCH] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5=D0=BD?=
 =?utf8?q?=20=D0=B4=D0=B0=D1=82=D1=87=D0=B8=D0=BA=20=D1=83=D1=80=D0=BE?=
 =?utf8?q?=D0=B2=D0=BD=D1=8F=20=D1=83=D0=B3=D0=BB=D0=B5=D0=BA=D0=B8=D1=81?=
 =?utf8?q?=D0=BB=D0=BE=D1=82=D1=8B=20MH-Z14?=
MIME-Version: 1.0
Content-Type: text/plain; charset=utf8
Content-Transfer-Encoding: 8bit

---
 .../Weather_Station.ino                       |  74 ++-
 Weather_WH2/Weather_WH2.ino                   | 435 ++++++++++++++++++
 web/config_local.php                          |  17 +
 web/config_local.php~                         |  17 +
 4 files changed, 502 insertions(+), 41 deletions(-)
 rename Weather_Station.ino => Weather_Station/Weather_Station.ino (81%)
 create mode 100644 Weather_WH2/Weather_WH2.ino
 create mode 100644 web/config_local.php
 create mode 100644 web/config_local.php~

diff --git a/Weather_Station.ino b/Weather_Station/Weather_Station.ino
similarity index 81%
rename from Weather_Station.ino
rename to Weather_Station/Weather_Station.ino
index 9358d3d..b42f486 100644
--- a/Weather_Station.ino
+++ b/Weather_Station/Weather_Station.ino
@@ -75,6 +75,7 @@ DHT dht;
 #define CO2_PIN A1
 #define DHT_PIN 4
 #define GAS_PIN A0
+#define MHZ14_PIN A2
 #define START_DELAY 20000
 #define DELAY 50000
 
@@ -83,8 +84,6 @@ byte HasBaro;
 #define READ_SAMPLE_INTERVAL 50
 #define READ_SAMPLE_TIMES 5
 
-#define MQ135_RES 1000
-
 float MQRead(int mq_pin)
 {
 
@@ -105,36 +104,24 @@ float MQRead(int mq_pin)
 
 /// Parameters to model temperature and humidity dependence
 
-#define CORA 0.00035
-#define CORB 0.02718
-#define CORC 1.39538
-#define CORD 0.0018
-
-float getMQ135CorrectionFactor(float t, float h) {
-  return CORA * t * t - CORB * t + CORC - (h-33.)*CORD;
-}
-
-#define RZERO 25300
-#define PARA 116.6020682
-#define PARB 2.769034857
-
-float getMQ135ppm(float Resistance) {
-  return PARA * pow((Resistance/RZERO), -PARB);  
-}
 
 void setup()
 {
   delay(START_DELAY);
 
+  Serial.begin(115200);
+  Serial.println("START");
   Serial1.begin(57600);
   Serial1.println("START");
 
   // Initialize the sensor (it is important to get calibration values stored on the device).
 
   if (pressure.begin()) {
+    Serial.println("BMP180 init success");
     Serial1.println("BMP180 init success");
     HasBaro = 1;
   } else {
+    Serial.println("BMP180 init fail\n\n");
     Serial1.println("BMP180 init fail\n\n");
     HasBaro = 0;
   }
@@ -155,6 +142,9 @@ void loop()
   double DHT_T,DHT_H;
   int DHTStatus;
   int Gas;
+  int CO2_raw;
+  int CO2_MHZ_raw;
+  float MHZ_ppm;
 
   double LastTemp;
   byte GotTemperature,GotPressure;
@@ -180,9 +170,11 @@ void loop()
         LastTemp=T;
         GotTemperature=1;
       } else {  
+        Serial.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE TEMPERATURE\n");
         Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE TEMPERATURE\n");
       }  
     } else {
+      Serial.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START TEMPERATURE MEASUREMENT\n");
       Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START TEMPERATURE MEASUREMENT\n");
     }
     
@@ -208,16 +200,19 @@ void loop()
           GotPressure=1;
 
       } else {
+        Serial.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE PRESSURE\n");
         Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED MEASURE PRESSURE\n");
       }  
     } else {
+      Serial.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START PRESSURE MEASUREMENT\n");
       Serial1.println("ERROR:TYPE=BMP180,MESSAGE=FAILED START PRESSURE MEASUREMENT\n");
     }  
     if (GotPressure || GotTemperature) {
+      Serial.print("SENSOR:TYPE=BMP180");
       Serial1.print("SENSOR:TYPE=BMP180");
-      if (GotPressure) { Serial1.print(",PRESSURE="); Serial1.print(P); }
-      if (GotTemperature) { Serial1.print(",TEMPERATURE="); Serial1.print(T); }
-      Serial1.println();
+      if (GotPressure) { Serial.print(",PRESSURE="); Serial.print(P); Serial1.print(",PRESSURE="); Serial1.print(P); }
+      if (GotTemperature) { Serial.print(",TEMPERATURE="); Serial.print(T); Serial1.print(",TEMPERATURE="); Serial1.print(T); }
+      Serial.println(); Serial1.println();
     }
   }
 
@@ -229,43 +224,40 @@ void loop()
   DHTStatus=dht.getStatus();
  
   if (DHTStatus == 0) {
+    Serial.print("SENSOR:TYPE=DHT22,TEMPERATURE=");
+    Serial.print(DHT_T);
+    Serial.print(",HUMIDITY=");
+    Serial.println(DHT_H);
     Serial1.print("SENSOR:TYPE=DHT22,TEMPERATURE=");
     Serial1.print(DHT_T);
     Serial1.print(",HUMIDITY=");
     Serial1.println(DHT_H);
   } else {
+    Serial.print("ERROR:TYPE=DHT22,MESSAGE=");
+    Serial.println(dht.getStatusString());
     Serial1.print("ERROR:TYPE=DHT22,MESSAGE=");
     Serial1.println(dht.getStatusString());
   }
   
   Gas = MQRead(GAS_PIN);
   
+  Serial.print("SENSOR:TYPE=MQ4,VALUE=");
+  Serial.println(Gas);
   Serial1.print("SENSOR:TYPE=MQ4,VALUE=");
   Serial1.println(Gas);
 
-  float MQ135_Resistance;
-  float CO2_raw;
-  float CO2_ppm;
-
-  float CO2_resistance;
-
   CO2_raw = MQRead(CO2_PIN);
-  Serial1.print("DEBUG:RAW=");
+  Serial.print("SENSOR:TYPE=MQ135,VALUE=");
+  Serial.println(CO2_raw);
+  Serial1.print("SENSOR:TYPE=MQ135,VALUE=");
   Serial1.println(CO2_raw);
 
-  MQ135_Resistance=MQ135_RES*(1023./CO2_raw-1);
-  
-  Serial1.print("DEBUG:RESISTANCE=");
-  Serial1.println(MQ135_Resistance);
-  
-  MQ135_Resistance=MQ135_Resistance/getMQ135CorrectionFactor(DHT_T,DHT_H);
-  Serial1.print("DEBUG:CORR_RESISTANCE=");
-  Serial1.println(MQ135_Resistance);  
-
-  CO2_ppm = getMQ135ppm(MQ135_Resistance);  
-  
-  Serial1.print("SENSOR:TYPE=MQ135,VALUE=");
-  Serial1.println(CO2_ppm);
+  CO2_MHZ_raw = MQRead(MHZ14_PIN);
+  MHZ_ppm=2000*(CO2_MHZ_raw*5.0/1023)/2.5;
+  Serial.print("SENSOR:TYPE=MHZ14,PPM=");
+  Serial.println(MHZ_ppm);
+  Serial1.print("SENSOR:TYPE=MHZ14,PPM=");
+  Serial1.println(MHZ_ppm);
   
   delay(DELAY);  // Pause for 50 seconds.
 }
diff --git a/Weather_WH2/Weather_WH2.ino b/Weather_WH2/Weather_WH2.ino
new file mode 100644
index 0000000..a61dbff
--- /dev/null
+++ b/Weather_WH2/Weather_WH2.ino
@@ -0,0 +1,435 @@
+/*
+  Updated code for receiving data from WH2 weather station
+  This code implements timeouts to make decoding more robust
+  Decodes received packets and writes a summary of each packet to the Arduino's
+  serial port
+  Created by Luc Small on 19 July 2013.
+  Released into the public domain.
+*/
+
+#include <dht.h>
+#include <Wire.h>
+#include <BMP085.h>
+
+// DHT11 and BMP085 wired sensors
+dht DHT;
+BMP085 bmp;
+
+// Humidity sensor at pin 4
+#define DHT11PIN 5
+int sensorPin = 0;
+#define DEBUG
+
+// LED pins
+#define REDPIN 11
+#define GREENPIN 12
+
+// Read data from 433MHz receiver on digital pin 3
+#define RF_IN 4
+// For better efficiency, the port is read directly
+// the following two lines should be changed appropriately
+// if the line above is changed.
+#define RF_IN_RAW PIND4
+#define RF_IN_PIN PIND
+
+// Port that is hooked to LED to indicate a packet has been received
+
+#define COUNTER_RATE 3200-1 // 16,000,000Hz / 3200 = 5000 interrupts per second, ie. 200us between interrupts
+// 1 is indicated by 500uS pulse
+// wh2_accept from 2 = 400us to 3 = 600us
+#define IS_HI_PULSE(interval)   (interval >= 2 && interval <= 3)
+// 0 is indicated by ~1500us pulse
+// wh2_accept from 7 = 1400us to 8 = 1600us
+#define IS_LOW_PULSE(interval)  (interval >= 7 && interval <= 8)
+// worst case packet length
+// 6 bytes x 8 bits x (1.5 + 1) = 120ms; 120ms = 200us x 600
+#define HAS_TIMED_OUT(interval) (interval > 600)
+// we expect 1ms of idle time between pulses
+// so if our pulse hasn't arrived by 1.2ms, reset the wh2_packet_state machine
+// 6 x 200us = 1.2ms
+#define IDLE_HAS_TIMED_OUT(interval) (interval > 6)
+// our expected pulse should arrive after 1ms
+// we'll wh2_accept it if it arrives after
+// 4 x 200us = 800us
+#define IDLE_PERIOD_DONE(interval) (interval >= 4)
+// Shorthand for tests
+//#define RF_HI (digitalRead(RF_IN) == HIGH)
+//#define RF_LOW (digitalRead(RF_IN) == LOW)
+#define RF_HI (bit_is_set(RF_IN_PIN, RF_IN_RAW))
+#define RF_LOW (bit_is_clear(RF_IN_PIN, RF_IN_RAW))
+
+// wh2_flags 
+#define GOT_PULSE 0x01
+#define LOGIC_HI  0x02
+volatile byte wh2_flags = 0;
+volatile byte wh2_packet_state = 0;
+volatile int wh2_timeout = 0;
+byte wh2_packet[5];
+byte wh2_calculated_crc;
+
+
+#ifdef DEBUG
+byte printed = 0;
+#endif
+
+ISR(TIMER1_COMPA_vect)
+{
+  static byte sampling_state = 0;
+  static byte count;   
+  static boolean was_low = false; 
+    
+  switch(sampling_state) {
+    case 0: // waiting
+      wh2_packet_state = 0;
+      if (RF_HI) {
+        if (was_low) {
+          count = 0;
+          sampling_state = 1;
+          was_low = false;
+        }
+      } else {
+        was_low = true;  
+      }
+      break;
+    case 1: // acquiring first pulse
+      count++;
+      // end of first pulse
+      if (RF_LOW) {
+        if (IS_HI_PULSE(count)) {
+          wh2_flags = GOT_PULSE | LOGIC_HI;
+          sampling_state = 2;
+          count = 0;        
+        } else if (IS_LOW_PULSE(count)) {
+          wh2_flags = GOT_PULSE; // logic low
+          sampling_state = 2;
+          count = 0;      
+        } else {
+          sampling_state = 0;
+        }    
+      }   
+      break;
+    case 2: // observe 1ms of idle time
+      count++;
+      if (RF_HI) {
+         if (IDLE_HAS_TIMED_OUT(count)) {
+           sampling_state = 0;
+         } else if (IDLE_PERIOD_DONE(count)) {
+           sampling_state = 1;
+           count = 0;
+         }
+      }     
+      break;     
+  }
+  
+  if (wh2_timeout > 0) {
+    wh2_timeout++; 
+    if (HAS_TIMED_OUT(wh2_timeout)) {
+      wh2_packet_state = 0;
+      wh2_timeout = 0;
+#ifdef DEBUG
+      if (printed) {
+        Serial1.println();
+        printed=0;
+      }
+#endif
+    }
+  }
+}
+
+void setup() {
+
+  Serial1.begin(115200); // Set the baud.
+ 
+   // Wait for U-boot to finish startup.  Consume all bytes until we are done.
+  do {
+     while (Serial1.available() > 0) {
+        Serial1.read();
+     }
+   
+    delay(1000);
+  } while (Serial1.available()>0);  
+
+  Serial1.begin(57600);
+  Serial1.println();
+  Serial1.println("STATUS:STARTING");
+
+  bmp.begin();
+  
+  pinMode(REDPIN,OUTPUT);
+  pinMode(GREENPIN,OUTPUT);  
+
+  pinMode(RF_IN, INPUT);
+  digitalWrite(RF_IN,HIGH);
+  
+  TCCR1A = 0x00;
+  TCCR1B = 0x09;
+  TCCR1C = 0x00;
+  OCR1A = COUNTER_RATE; 
+  TIMSK1 = 0x02;
+  
+  // enable interrupts
+  sei();
+}
+
+unsigned long previousMillis = 0;
+unsigned long indoor_interval = 60000;
+unsigned long outdoor_interval = 45000;
+unsigned long previousIndoor = 0;
+unsigned long previousOutdoor = 0;
+
+float temperature;
+float pressure;
+
+void loop() {
+  unsigned long now;
+  int gas = 0;
+  byte i;
+
+  now = millis();
+
+  if (wh2_flags) {
+    if (wh2_accept()) {
+      // calculate the CRC
+      wh2_calculate_crc();
+      
+      if (wh2_valid()) {
+        
+        Serial1.println();
+        Serial1.print("SENSOR:TYPE=OUTDOOR,");
+        
+        Serial1.print("ID=");
+        Serial1.print(wh2_sensor_id(), HEX);
+      
+        Serial1.print(",HUMIDITY=");
+        Serial1.print(wh2_humidity(), DEC);
+        
+        Serial1.print(",TEMPERATURE=");
+        Serial1.println(format_temp(wh2_temperature()));
+        
+        previousOutdoor = now;
+        digitalWrite(REDPIN,HIGH);
+        
+      } else {
+      
+        Serial1.println();
+        Serial1.println("ERROR:OUTDOOR");
+        previousOutdoor = now;
+        digitalWrite(REDPIN,LOW);
+        
+      }  
+
+   }
+   wh2_flags = 0x00; 
+  }
+
+  if ((unsigned long)(now - previousMillis) >= indoor_interval) {
+
+    previousMillis = now;
+ 
+    int chk = DHT.read11(DHT11PIN);
+
+    if (chk==0) {
+     
+      Serial1.println();
+      Serial1.print("SENSOR:TYPE=INDOOR,");
+      Serial1.print("HUMIDITY=");
+      Serial1.print(DHT.humidity);
+      Serial1.print(",TEMPERATURE=");
+      Serial1.print(DHT.temperature);
+
+      previousIndoor = now;
+      digitalWrite(GREENPIN,HIGH);
+
+
+    } else {
+        
+      Serial1.println();
+      Serial1.println("ERROR:INDOOR");
+      previousIndoor = now;
+      digitalWrite(GREENPIN,LOW);
+        
+    } 
+
+    pressure=bmp.readPressure();
+    temperature=bmp.readTemperature();
+    Serial1.println();
+    Serial1.print("SENSOR:TYPE=BARO,");
+    Serial1.print("PRESSURE=");
+    Serial1.print(pressure);
+    Serial1.print(",TEMPERATURE=");
+    Serial1.println(temperature);
+
+    gas = analogRead(sensorPin); // Получаем значения из датчика
+    Serial1.print("SENSOR:TYPE=GAS,VALUE=");
+    Serial1.println(gas); // Пишем в серийный порт
+
+  }
+  
+  if ((unsigned long)(now - previousIndoor) > indoor_interval*10) {
+
+      Serial1.println();
+      Serial1.println("ERROR:INDOOR TIMEOUT");
+      previousIndoor = now;
+      digitalWrite(GREENPIN,LOW);
+    
+  }
+
+  if ((unsigned long)(now - previousOutdoor) > outdoor_interval*10) {
+
+      Serial1.println();
+      Serial1.println("ERROR:OUTDOOR TIMEOUT");
+      previousOutdoor = now;
+      digitalWrite(REDPIN,LOW);
+    
+  }
+
+
+}
+
+
+// processes new pulse
+boolean wh2_accept()
+{
+  static byte packet_no, bit_no, history;
+
+  // reset if in initial wh2_packet_state
+  if(wh2_packet_state == 0) {
+     // should history be 0, does it matter?
+    history = 0xFF;
+    wh2_packet_state = 1;
+    // enable wh2_timeout
+    wh2_timeout = 1;
+  } // fall thru to wh2_packet_state one
+ 
+  // acquire preamble
+  if (wh2_packet_state == 1) {
+     // shift history right and store new value
+     history <<= 1;
+     // store a 1 if required (right shift along will store a 0)
+     if (wh2_flags & LOGIC_HI) {
+       history |= 0x01;
+     }
+     // check if we have a valid start of frame
+     // xxxxx110
+     if ((history & B00000111) == B00000110) {
+       // need to clear packet, and counters
+       packet_no = 0;
+       // start at 1 becuase only need to acquire 7 bits for first packet byte.
+       bit_no = 1;
+       wh2_packet[0] = wh2_packet[1] = wh2_packet[2] = wh2_packet[3] = wh2_packet[4] = 0;
+       // we've acquired the preamble
+       wh2_packet_state = 2;
+    }
+    return false;
+  }
+  // acquire packet
+  if (wh2_packet_state == 2) {
+
+    wh2_packet[packet_no] <<= 1;
+    if (wh2_flags & LOGIC_HI) {
+      wh2_packet[packet_no] |= 0x01;
+#ifdef DEBUG
+      Serial1.print('1');
+      printed=1;
+    } else {
+      Serial1.print('0');
+      printed=1; 
+#endif
+    }
+
+    bit_no ++;
+    if(bit_no > 7) {
+      bit_no = 0;
+      packet_no ++;
+    }
+
+    if (packet_no > 4) {
+      // start the sampling process from scratch
+      wh2_packet_state = 0;
+      // clear wh2_timeout
+      wh2_timeout = 0;
+      return true;
+    }
+  }
+  return false;
+}
+
+
+void wh2_calculate_crc()
+{
+  wh2_calculated_crc = crc8(wh2_packet, 4);
+}
+
+bool wh2_valid()
+{
+  return (wh2_calculated_crc == wh2_packet[4]);
+}
+
+int wh2_sensor_id()
+{
+  return (wh2_packet[0] << 4) + (wh2_packet[1] >> 4);
+}
+
+byte wh2_humidity()
+{
+  return wh2_packet[3];
+}
+
+/* Temperature in deci-degrees. e.g. 251 = 25.1 */
+int wh2_temperature()
+{
+  int temperature;
+  temperature = ((wh2_packet[1] & B00000111) << 8) + wh2_packet[2];
+  // make negative
+  if (wh2_packet[1] & B00001000) {
+    temperature = -temperature;
+  }
+  return temperature;
+}
+
+String format_temp(int temperature)
+{
+  byte whole, partial;
+  String s;
+  s = String();
+  if (temperature<0) {
+    temperature = -temperature;
+    s += String('-');
+  }
+       
+  whole = temperature / 10;
+  partial = temperature - (whole*10);
+
+  s += String(whole, DEC);
+  s += '.';
+  s += String(partial, DEC);
+
+  return s;
+
+}
+
+uint8_t crc8( uint8_t *addr, uint8_t len)
+{
+  uint8_t crc = 0;
+
+  // Indicated changes are from reference CRC-8 function in OneWire library
+  while (len--) {
+    uint8_t inbyte = *addr++;
+    for (uint8_t i = 8; i; i--) {
+      uint8_t mix = (crc ^ inbyte) & 0x80; // changed from & 0x01
+      crc <<= 1; // changed from right shift
+      if (mix) crc ^= 0x31;// changed from 0x8C;
+      inbyte <<= 1; // changed from right shift
+    }
+  }
+  return crc;
+}
+
+
+
+
+
+
+
+
+
diff --git a/web/config_local.php b/web/config_local.php
new file mode 100644
index 0000000..eef2134
--- /dev/null
+++ b/web/config_local.php
@@ -0,0 +1,17 @@
+<?php
+
+  $mysql_host = 'host';
+  $mysql_schema = 'meteo';
+  $mysql_user = 'meteo';
+  $mysql_pwd = 'somestrictpasswd';
+  $mysql_port = 3306;
+
+  setlocale(LC_ALL,'ru_RU.UTF8');
+<<<<<<< HEAD
+=======
+
+  $valid_ip_start = ip2long('192.168.1.161');
+  $valid_ip_end   = ip2long('192.168.1.190');
+>>>>>>> 438eca78d7802bd2758a4969b80bb0be6b9f14f6
+                
+?>
\ No newline at end of file
diff --git a/web/config_local.php~ b/web/config_local.php~
new file mode 100644
index 0000000..eef2134
--- /dev/null
+++ b/web/config_local.php~
@@ -0,0 +1,17 @@
+<?php
+
+  $mysql_host = 'host';
+  $mysql_schema = 'meteo';
+  $mysql_user = 'meteo';
+  $mysql_pwd = 'somestrictpasswd';
+  $mysql_port = 3306;
+
+  setlocale(LC_ALL,'ru_RU.UTF8');
+<<<<<<< HEAD
+=======
+
+  $valid_ip_start = ip2long('192.168.1.161');
+  $valid_ip_end   = ip2long('192.168.1.190');
+>>>>>>> 438eca78d7802bd2758a4969b80bb0be6b9f14f6
+                
+?>
\ No newline at end of file
-- 
2.34.1