ESP8266 Weatherstation
I decided show my school work of my own board for weather station based on ESP8266 - 12 with BME280 (as temperature, humidity and pressure sensor) and with photoresistor as detector of sunlight. I add ADC 1115 for get voltage from voltage divider (sunlight measure and voltage from battery).
Pros:
Using solar cell to charge Lithium - ion battery (18650)
Using Wi-Fi to connect ThingSpeak
BOM
Parts (affiliate links):
ESP8266 - 12 (you can buy ESP8266 - 7)
White adapter for ESP8266 - 12 (need solder esp chip to board)
3.3 V Voltage regulator
new regulator (not affiliate) 3 V with low quescient current
ADS1115
Analog - digital converter, which is ude for measure voltage from battery and for get value of sunlight.
BME280
Fake BME280= BMP280 (not sure if it is not fake BME280 = BMP280!)
Capacitors
Diode
diode (for protection solar cell from reversing current)
Tactile push buttons
Dip swtich (just 1 way needed or any switch)
http://s.click.aliexpress.com/e/PdRW7ze
NPN BC337
Set of NPN transistors (set)
Resistors
4.7K 2.2K 10K 10K D1160_12 0.46K 1M 1M
TP4056
TP4056 (5 pcs) (5 pcs)
Solar cell (I prefer 6 V better then 5V, 1W give maximum 160 mA, which is not enough for winter, better buy with more Watts )
18650 battery
18650 holder
Waterproof case
(works good, I try in my previous instructable project) (works good, I try in my previous instructable project)
Cables
if you dont create Eagle and want using universal PCB
Code
I graph diagram of code for better understanding. For programming, here is code, don't forgot to change ssid, password, ThingSpeak apikey, and in setup body also ssid code.
// Wifi commands #include "WiFiConfig.h" const char* WiFi_hostname = "weatherstation1"; const char* ssid = "xyz"; // here write your wifi "WIFI-MA"; const char* password = "mypassword to xyz"; // here password from your wifi; const char* server = "api.thingspeak.com"; const char* api_key = "myapikeyfromthingspeak"; // here write apikey from ThingSpeak WiFiClient client; #include <Wire.h><br> #include <SPI.h> // bme 280 #include <Adafruit_Sensor.h> #include <Adafruit_BME280.h> #define BME280_ADRESA (0x76) // adress of BME280 Adafruit_BME280 bme; //Adafruit_BME280 bme(BME_CS); // hardware SPI //Adafruit_BME280 bme(BME_CS, BME_MOSI, BME_MISO, BME_SCK); // bme variable float temp; float humidity; float pressure; // esp voltage reference = get voltage from ADC pin on esp // = input voltage to esp from regulator int refvolt; ADC_MODE(ADC_VCC); //sleep #define SLEEP_TIME_SECONDS 600 #define ALLOWED_CONNECT_CYCLES 40 // if wifi is not avalaible, esp go to sleep uint8_t counter // ADS1115 for measure voltage of battery and sunlight #include Adafruit_ADS1115 ads(0x49); float rawlux = 0; float rawvolt = 0; // wifi variable for getting number of wifi networks //+ get strength of connected xyz wifi network int strength; int n;
// setting of bme 280 sensitivity // Forced mode as recommended for weather station usage by Bosch (sec 5.5.1) // Settings have to be written to the sensor before every sampling void bme_ini(){ bme.setTemperatureSampling(Adafruit_BME280::Sampling_x1); bme.setPressureSampling(Adafruit_BME280::Sampling_x1); bme.setHumiditySampling(Adafruit_BME280::Sampling_x1); bme.setFilter(Adafruit_BME280::Filter_Off); bme.setMode(Adafruit_BME280::Forced); //Forced or Sleep bme.begin(BME280_ADRESA); }
void setup() { //Serial.begin(115200); //Serial.println(F("BME280 test")); /////////////////////// measurements //////////////////////// pinMode(14,OUTPUT); // set pin 14 as output for powering sensors digitalWrite(14,HIGH); // power sensors with digital pin 14 delay(10); refvolt = ESP.getVcc(); // measure input voltage to esp, usually should be 3.3 V delay(10); //Wire.begin(13, 12); //for set i2c pin, Wire.begin(sda,scl), default GPIO4 SDA, GPIO5 scl ////////////////// BME280 = temperature, humidity and pressure ////////////// bme_ini(); delay(100);// before read temperate and firts value important is wait some time temp = bme.readTemperature(); delay(10); humidity = bme.readHumidity(); delay(10); pressure = bme.readPressure() / 100.0F; delay(10); ///////////////// voltage and sunglight ///////////////////// int16_t adc0, adc2, adc3; ads.setGain(GAIN_TWOTHIRDS); ads.begin(); delay(100); rawlux = ads.readADC_SingleEnded(0); // read sunglight = read signal from voltage divider delay(100); rawvolt = ads.readADC_SingleEnded(2); // read voltage of battery from voltage divider delay(10); /////////////////////// write values to one variable - dataToThingspeak/////////// String dataToThingSpeak = ""; dataToThingSpeak += "GET /update?api_key="; dataToThingSpeak += api_key; dataToThingSpeak += "&field1="; dataToThingSpeak += temp; // writing to field 1 temperature from first sensor dataToThingSpeak += "&field2="; dataToThingSpeak += humidity; // writing to field 2 temperature from second sensor dataToThingSpeak += "&field3="; dataToThingSpeak += pressure; dataToThingSpeak += "&field4="; dataToThingSpeak += rawlux; dataToThingSpeak += "&field6="; dataToThingSpeak += rawvolt; dataToThingSpeak += "&field7="; dataToThingSpeak += refvolt; /////////// connect to WiFi, if can't, then go to sleep (after 40 cycles)/////////////// WiFi.hostname(); WiFi.begin(ssid, password); while (WiFi.status() != WL_CONNECTED) { delay(500); Serial.print(".");counter++; if (counter > ALLOWED_CONNECT_CYCLES) { Serial.print("sleep"); ESP.deepSleep(SLEEP_TIME_SECONDS * 1000000); //sleeping if can't connect } } //Serial.println("WiFi connected"); // WiFi.disconnect(); // ADC values fluctuate, they are crazy, problem can be in wifi connection, so try to disconnect it //WiFi.mode(WIFI_OFF); //uncomment if you have problems with ADC // WiFi.forceSleepBegin(); // uncomment if you have proble // ESP.eraseConfig(); ////////////////// measure number of Wifi networks, and strength of connected////////// if (client.connect(server, 80)) { int n = WiFi.scanNetworks(); for (int thisNet = 0; thisNet < n; thisNet++) { if (WiFi.SSID(thisNet) = "xyz") // replace xyz with ssid in beginning { strength= WiFi.RSSI(thisNet); // get strength of wifi in d } } dataToThingSpeak += "&field5="; dataToThingSpeak += strength; dataToThingSpeak += "&field8="; dataToThingSpeak += n; // write to field 8 number of wifi networks //dataToThingSpeak+="&field8="; //dataToThingSpeak+=WiFi.RSSI(); dataToThingSpeak += " HTTP/1.1\r\nHost: a.c.d\r\nConnection: close\r\n\r\n"; // just write this line dataToThingSpeak += ""; ////////////////// sending to thingspeak variable dataToThingspeak/////////// client.print(dataToThingSpeak); //Serial.print(dataToThingSpeak); delay(100); // wait 1 second = 1000 miliseconds /////////////////////// show data at serial monitor, uncoment! /////////////////// /* Serial.println( temp); Serial.println(humidity); Serial.println( pressure); Serial.println(rawlux); Serial.println(rawvolt); // or // Serial.println(dataToThingspeak) Serial.println(WiFi.macAddress()); */ //////////////////////// power off sensors + go to sleep ////////////////////////// digitalWrite(14,LOW); ///Serial.print("sleep"); ESP.deepSleep(SLEEP_TIME_SECONDS*1000000); //sleeping } // end of void setup and sleep for SLEEP_TIME_SECONDS, then restart
void loop() { }
Circuit
1. I connect ESP8266 - 12 with regulator (from 5V to 3.3 V) to battery. Also, I add two push buttons, one for restart, second for set programming mode.
2. I power BME280, ADS1115 and photoresistor with regulator. But I switch off/on them witn NPN transistor, because they drain battery too.
3. I measure sunlight with voltage divider (one resistor is 0,46 kohm, second is photoresistor).
4. I measure voltage of battery with voltage divider (used pair of 1 Mohm resistors).
5. ADS1115, BME280 communicated with esp using I2C.
6. I charger battery with solar cell (6 V) and TP4056 board.
7. For turn off/on device, I use one dip switch (slide type).
8. Female programme pins are 3 inputs for programming ESP chip - Tx, Rx, GND.
Voltage Divides (examples on Arduino)
I measure voltage of battery and sunlight using voltage divider.
Instead of ADS1115 with analog pins, I show you basic principle using Arduino UNO, which has also analog pins.
Example of battery:
1. two resistors must be connected to create votlage divider (2x 10 kOhm) to one node (joint).
2. That node is connected to analog pin.
3. Then one resistor connect to + terminal of battery, another resistor to - terminal of battery.
Example of photoresistor:
1. One end of photoresistor connect to 3.3 Voltage.
2. One end of resistor connect to GND of Arduino.
3. Node of photoresistor and resistor connect to analog pin. It needs calibrate, but I don't do that.
PCB
I design and create own PCB in Eagle.
Thingspeak Server
I use ThingSpeak for visualize data.
1. I measure temperature of air. It need better cooling during hot days or radiation shield for sure.
2. Relative humidity sensor work one year. Then it degrade.
3. Pressure sensor works good, and is for predict cloudiness or rain. It works with 2 - 3 days prediction! Nice.
4. Photoresistor depend on temperature and degrade with time. I don't think is good solution.
5. All resistors in voltage divides (measure sunlight and voltage of battery) should be temperature independent. I use classical resisistors, not good. Also, check % of error of resistance of resistors. 5 % resistance is not good, because is hard to get real voltage of battery.
Laboratory Sample
Graphs
As you can see, I can make some graphs using Google Tables:
1. Temperature - need solar shield because of preheated.
2. Humidity - after some time (1 - 2 years) it degrade.
3. Temperature and Humidity - you can see, when temperature is highest, humidity is lowest and when temperature is lowest, humidity is highest.
4. Sunlight - because I have weather station on balcony, Sun is sometimes hidden behind house. Sun beams don't fall to photoresistor, mostly in morning and evening. That's why you can see steps, when suddenly beam fall to photoresistor.
5. Pressure - I measure local pressure of air, so it needs calibrate to air pressure reduced to sea level.
Check this nice online calculator. https://keisan.casio.com/exec/system/1224575267
Sea - level pressure depend on temperature of air, altitude of weather station, and local pressure.
6. Battery level - I don't calibrate, you can see, that it depends on temperature.