From 357607fbe9159afef9ba89f1dbe86abe7966efc8 Mon Sep 17 00:00:00 2001 From: Roman Bazalevskiy Date: Sat, 3 Sep 2016 18:15:05 +0300 Subject: [PATCH 1/1] =?utf8?q?=D0=94=D0=BE=D0=B1=D0=B0=D0=B2=D0=BB=D0=B5?= =?utf8?q?=D0=BD=20=D0=B4=D0=B0=D1=82=D1=87=D0=B8=D0=BA=20=D1=83=D1=80?= =?utf8?q?=D0=BE=D0=B2=D0=BD=D1=8F=20=D1=83=D0=B3=D0=BB=D0=B5=D0=BA=D0=B8?= =?utf8?q?=D1=81=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 +#include +#include + +// 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 @@ +>>>>>> 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 @@ +>>>>>> 438eca78d7802bd2758a4969b80bb0be6b9f14f6 + +?> \ No newline at end of file -- 2.34.1