Home weather station on Arduino and sending data to "People's monitoring". My homemade weather station on Arduino Nano Weather station on arduino with wireless sensor

A colleague of mine recently hosted a small science fair.
My teacher asked me to present an electronics project to college students. I had two days to come up with something interesting and simple enough.



Since the weather conditions here are quite changeable, and the temperature fluctuates in the range of 30-40 ° C, I decided to make a home weather station.

What are the functions of a home weather station?
An Arduino weather station with a display is a device that collects data on weather and environmental conditions using a variety of sensors.

Usually these are the following sensors:

  • wind
  • humidity
  • rain
  • temperature
  • pressure
  • heights

My goal is to make a portable desktop weather station with my own hands.

It should be able to define the following parameters:

  • temperature
  • humidity
  • pressure
  • height

Step 1: Buy the right components







  • DHT22, temperature and humidity sensor.
  • BMP180, pressure sensor.
  • Solder
  • Single row connector 40 outputs

From the equipment you will need:

  • soldering iron
  • nose pad pliers
  • wires

Step 2: DHT22 temperature and humidity sensor







Various sensors are used to measure temperature. DHT22, DHT11, SHT1x are popular

I will explain how they differ from each other, and why I used DHT22.

The AM2302 sensor uses a digital signal. This sensor works on a unique coding system and sensor technology, so its data is reliable. Its sensor element is connected to an 8-bit single-chip computer.

Each sensor of this model is thermally compensated and precisely calibrated, the calibration coefficient is stored in a one-time programmable memory (OTP memory). When reading a reading, the sensor will recall the coefficient from memory.

Small size, low power consumption, long transmission distance (100m) make AM2302 suitable for almost all applications, and 4 outputs in a row make installation very easy.

Let's look at the pros and cons of the three sensor models.

DHT11

Pros: does not require soldering, the cheapest of the three models, fast stable signal, range over 20 m, strong interference.
Cons: Library! No resolution options, temperature measurement error +/- 2°С, relative humidity level measurement error +/- 5%, inadequate range of measured temperatures (0-50°С).
Applications: gardening, agriculture.

DHT22

Pros: does not require soldering, low cost, smooth curves, small measurement errors, large measurement range, range over 20 m, strong interference.
Cons: sensitivity could be higher, slow tracking of temperature changes, library needed.
Applications: environmental studies.

SHT1x

Pros: no soldering required, smooth curves, small measurement errors, fast response, low power consumption, automatic sleep mode, high stability and data consistency.
Cons: two digital interfaces, error in measuring the humidity level, the range of measured temperatures is 0-50°C, a library is needed.
Applications: operation in harsh environments and in long-term installations. All three sensors are relatively inexpensive.

Compound

  • Vcc - 5V or 3.3V
  • Gnd - with Gnd
  • Data - to the second Arduino pin

Step 3: BMP180 pressure sensor



BMP180 is a barometric atmospheric pressure sensor with I2C interface.
Barometric pressure sensors measure the absolute value of the ambient air. This indicator depends on the specific weather conditions and on the height above sea level.

The BMP180 module had a 3.3V 662k ohm regulator, which I, by my own stupidity, accidentally blew up. I had to do a power stroke directly to the chip.

Due to the lack of a stabilizer, I am limited in choosing a power source - voltages above 3.3V will destroy the sensor.
Other models may not have a stabilizer, be sure to check for it.

Connection diagram of the sensor and I2C bus with Arduino (nano or uno)

  • SDA-A4
  • SCL-A5
  • VCC - 3.3V
  • GND-GND

Let's talk a little about pressure, and how it relates to temperature and altitude.

Atmospheric pressure at any point is not constant. The complex interplay between the Earth's rotation and the tilt of the Earth's axis results in many areas of high and low pressure, which in turn results in daily weather patterns. By observing the change in pressure, you can make a short-term weather forecast.

For example, a drop in pressure usually means rainy weather or the approach of a thunderstorm (approaching a low pressure area, a cyclone). Rising pressure usually means dry, clear weather (an area of ​​high pressure, an anticyclone, is passing over you).

Atmospheric pressure also changes with altitude. The absolute pressure at the base camp at Everest (5400 m above sea level) is lower than the absolute pressure at Delhi (216 m above sea level).

Since absolute pressure readings vary at each location, we will refer to relative pressure, or sea level pressure.

Height measurement

The mean pressure at sea level is 1013.25 GPa (or millibars). If you rise above the atmosphere, this value will drop to zero. The curve of this fall is quite understandable, so you can calculate the altitude yourself using the following equation: alti=44330*

If you take the sea level pressure of 1013.25 GPa as p0, the solution to the equation is your current altitude.

Precautionary measures

Keep in mind that the BMP180 sensor needs access to the atmosphere to be able to read air pressure, do not place the sensor in a closed case. A small vent will suffice. But do not leave it too open - the wind will knock down pressure and altitude readings. Consider wind protection.

Protect from heat. Accurate temperature readings are required to measure pressure. Try to protect the sensor from temperature fluctuations and do not leave it near sources of high temperatures.

Protect from moisture. The BMP180 sensor is sensitive to moisture levels, try to prevent possible water intrusion on the sensor.

Don't blind the sensor. The surprise was the sensitivity of the silicone in the sensor to light, which can fall on it through a hole in the chip cover. For the most accurate measurements, try to protect the sensor from ambient light.

Step 4: Assembling the device







Installing single-row connectors for Arduino Nano. Basically, we cut them to size and sanded them a bit so they look like they were. Then we solder them. After, we install single-row connectors for the DHT22 sensor.

Install a 10kΩ resistor from the data output to ground (Gnd). We solder everything.
Then, in the same way, we install a single-row connector for the BMP180 sensor, we make the power supply 3.3V. We connect everything with the I2C bus.

Lastly, we connect the LCD display to the same I2C bus as the BMP180 sensor.
(I plan to later connect an RTC module (real time clock) to the fourth connector so that the device also shows the time).

Step 5: Coding




Download Libraries

To install libraries on Arduino, follow the link

#include
#include #include #include "DHT.h" #include

SFE_BMP180 pressure;

#define ALTITUDE 20.56 #define I2C_ADDR 0x27 //<<- Add your address here. #define Rs_pin 0 #define Rw_pin 1 #define En_pin 2 #define BACKLIGHT_PIN 3 #define D4_pin 4 #define D5_pin 5 #define D6_pin 6 #define D7_pin 7

#define DHTPIN 2 // what digital pin we "re connected to

// Uncomment whatever type you"re using! //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302), AM2321 DHT dht(DHTPIN, DHTTYPE); LiquidCrystal_I2C lcd(I2C_ADDR,En_pin,Rw_pin, Rs_pin,D4_pin,D5_pin,D6_pin,D7_pin);float t1,t2;

void setup() ( Serial.begin(9600); lcd.begin(16,2); //<<-- our LCD is a 20x4, change for your LCD if needed // LCD Backlight ON lcd.setBacklightPin(BACKLIGHT_PIN,POSITIVE); lcd.setBacklight(HIGH); lcd.home (); // go home on LCD lcd.print("Weather Station"); delay(5000); dht.begin(); pressure.begin(); } void loop() { char status; double T,P,p0,a; status = pressure.startTemperature(); if (status != 0) { delay(status);

status = pressure.getTemperature(T); if (status != 0) ( Serial.print("1"); lcd.clear(); lcd.setCursor(0,0); lcd.print("Baro Temperature: "); lcd.setCursor(0,1 ); lcd.print(T,2); lcd.print(" deg C "); t1=T; delay(3000);

status = pressure.startPressure(3); if (status != 0) ( // Wait for the measurement to complete: delay(status);

status = pressure.getPressure(P,T); if (status != 0) (lcd.clear(); lcd.setCursor(0,0); lcd.print("abslt pressure: "); lcd.setCursor(0,1); lcd.print(P,2 ); lcd.print(" mb "); delay(3000);

p0 = pressure.sealevel(P,ALTITUDE); // we "re at 1655 meters (Boulder, CO)

a = pressure.altitude(P,p0); lcd.clear(); lcd.setCursor(0,0); lcd.print("Altitude: "); lcd.setCursor(0,1); lcd.print(a,0); lcd.print("meters"); delay(3000); ) ) ) ) float h = dht.readHumidity(); // Read temperature as Celsius (the default) float t = dht.readTemperature(); t2=t; lcd.clear(); lcd.setCursor(0,0); // go to start of 2nd line lcd.print("Humidity: "); lcd.setCursor(0,1);lcd.print(h); lcd.print("%"); delay(3000); lcd.clear(); lcd.setCursor(0,0); // go to start of 2nd line lcd. print("DHT Tempurature: "); lcd.setCursor(0,1); lcd print(t); lcd.print("degC"); delay(3000); lcd.clear(); lcd.setCursor(0,0); // go to start of 2nd line lcd.print("Mean Tempurature: "); lcd.setCursor(0,1); lcd.print((t1+t2)/2); lcd.print("degC"); delay(3000); )

I used Arduino version 1.6.5, the code fits it exactly, later ones can work as well. If the code does not fit for some reason, use version 1.6.5 as the base one.

It is advisable to download the firmware before connecting the components to make sure that the board is working. After assembly, you can flash again, the board should calmly flash. In projects with high power consumers in the board's 5V power circuit (addressable LED strip, servos, motors, etc.), it is necessary to apply external 5V power to the circuit before connecting the Arduino to the computer, because USB will not provide the necessary current if, for example, the strip requires it. This can burn out the protection diode on the Arduino board. A guide for downloading and uploading the firmware can be found under the spoiler on the next line.

The contents of folders in the archive

  • libraries– project libraries. Replace existing versions
  • firmware- Firmware for Arduino
  • schemes– component connection diagrams

Additionally

  • As the experiment showed, outside the case the temperature sensor shows 0.5 degrees less than inside! It is necessary to more successfully arrange electronics, remove and shield heat from heating elements ...

  • If the display is too dim/white
    On the display driver board (to which the wires are connected) there is a contrast knob, with its help you can adjust the contrast to the desired one. Also, the contrast depends on the angle of view of the display (this is LCD) and you can adjust the display for a clear display even at an angle “the display is at the level of the navel, we look from above”. And the contrast strongly depends on the power supply: from 5V, the display shows as clearly and brightly as possible, while when powered from USB via Arduino, the voltage will be about 4.5V (part of it falls on the protective diode along the USB line), and the display shows not so bright. Adjust the output with a knob with an external power supply from 5V!

  • If the CO2 sensor does not work correctly (infa from Evgeny Ivanov)
    Well, there are sketches for calibration in the sensor library folder in examples. it can also be started dumb by shorting the “HD” connector to ground for 7+ seconds.
    Of course, right on the street in the cold, it’s not necessary to do this ... you can just fill the bottle with fresh air with a sensor inside and seal it. calibration takes at least 20 minutes.
    By default, the sensor is supplied with auto-calibration enabled, which occurs every day, and if the sensor is used in an unventilated room, then this calibration quickly takes the values ​​from the norm beyond the horizon, so it must be disabled.
    Documentation.

  • Sensor auto-calibration CO2 is disabled in the sketch!

  • If you have BME280 sensor not working, most likely it has a different address. The project uses the Adafruit_BME280 library, which does not have a separate address change function, so the address is set manually in the Adafruit_BME280.h library file almost at the very beginning of the file ( is in the Adafruit_BME280 folder in your libraries folder, you should have installed it there), my module had address 0x76. How can I find out the address of my BME280 module? There is a special sketch called i2c scanner. You can google it, you can. Flash this sketch, open the port and get a list of addresses of devices connected to the i2c bus. So that the other modules do not bother you, you can turn them off and leave only the BME280. We specify the received address in the library, save the file and load the weather clock firmware. Everything!

  • If the clock is behind, the problem is most likely in the power circuit. If the problem persists when changing the power supply to a better one, hang a capacitor to power the RTC module (solder directly on the board to VCC and GND): be sure to be ceramic, 0.1-1 uF (marking 103 or 104, see the marking table). You can also put an electrolyte (6.3V, 47-100 uF)

Firmware settings

#define RESET_CLOCK 0 // reset the clock while the firmware is being loaded (for a module with a non-removable battery). Do not forget to put 0 and flash again! #define SENS_TIME 30000 // refresh time of sensor readings on the screen, milliseconds #define LED_MODE 0 // RGB LED type: 0 - main cathode, 1 - main anode #define LED_BRIGHT 255 // CO2 LED brightness (0 - 255) #define BLUE_YELLOW 1 // yellow color instead of blue (1 yes, 0 no) but due to connection features yellow is not so bright #define DISP_MODE 1 // display in the upper right corner: 0 - year, 1 - day of the week, 2 - seconds #define WEEK_LANG 1 // language of the day of the week: 0 - English, 1 - Russian (transliterated) #define DEBUG 0 // display the sensor initialization log at startup #define PRESSURE 1 // 0 - pressure graph, 1 - rain forecast graph (instead of pressure ). Don't forget to fix chart limits // display limits for graphs #define TEMP_MIN 15 #define TEMP_MAX 35 #define HUM_MIN 0 #define HUM_MAX 100 #define PRESS_MIN -100 #define PRESS_MAX 100 #define CO2_MIN 300 #define CO2_MAX 2000

Do-it-yourself weather station.

It was in the evening, there was nothing to do after the new year. As usual, during the winter New Year holidays, I want to occupy my head and hands with something useful and creative too. During these New Year holidays I decided to make a weather station with my own hands. I started to prepare in advance, bought and assembled all the components before the new year, and did the main programming during the holidays.

(Lots of photos under the cut!)

First, I’ll go over the components, I won’t give links, since the goods on eBay (in my account) have gone to the archive. I bought many components leisurely on eBay. Tried the auction for the first time, used to always buy “buy it now”. What can I say, if you do not rush to buy, then some components can be bought cheaper (sometimes the difference is twice).

Pressure sensor BMP085
This is the main sensor. When I saw it on eBay, I realized that I wanted to build a home weather station.
The sensor arrived in an ordinary envelope, pasted over with a little bubble wrap inside.

Inside the envelope was the seller's business card and the sensor, packed in an antistatic bag and wrapped in another layer of bubble wrap

The anti-static bag was sealed so that moisture during the flight did not threaten the sensor

We get the sensor. On one side, a line of contacts was soldered, which were inserted into the foam so that they would not bend. On the other side is the sensor itself and the marking of the contacts.




Everything would be fine, but the marking of the contacts is applied in a mirror image.
The sensor is connected via the I2C bus and is powered by 3.3 V. That is, 4 wires are needed for normal operation (+, -, SDA, SCL)
You can interrogate the sensor in 2 ways: either through the library, or using the functions directly in the sketch.
Program example:

#include

#define BMP085_ADDRESS 0x77 // I2C address of BMP085

Const unsigned char OSS = 0; // Oversampling Setting

// Calibration values
int ac1;
intac2;
intac3;
unsigned int ac4;
unsigned int ac5;
unsigned int ac6;
int b1;
intb2;
intmb;
int mc;
intmd;

short temperature;
long pressure;

Void setup()
{
Serial.begin(9600);
Wire.begin();
bmp085Calibration();
}

Void loop()
{
temperature = bmp085GetTemperature(bmp085ReadUT());
pressure = bmp085GetPressure(bmp085ReadUP());
Serial.print("Temperature: ");
Serial.print(temperature/10.0, DEC);
Serial.println("C");
Serial.print("Pressure: ");
Serial.print(pressure/133.322, DEC);
Serial.println("mm Hg");
Serial.println();
delay(1000);
}

Void bmp085Calibration()
{
ac1 = bmp085ReadInt(0xAA);
ac2 = bmp085ReadInt(0xAC);
ac3 = bmp085ReadInt(0xAE);
ac4 = bmp085ReadInt(0xB0);
ac5 = bmp085ReadInt(0xB2);
ac6 = bmp085ReadInt(0xB4);
b1 = bmp085ReadInt(0xB6);
b2 = bmp085ReadInt(0xB8);
mb = bmp085ReadInt(0xBA);
mc = bmp085ReadInt(0xBC);
md = bmp085ReadInt(0xBE);
}

Short bmp085GetTemperature(unsigned int ut)
{
long x1, x2;
x1 = (((long)ut - (long)ac6)*(long)ac5) >> 15;
x2 = ((long)mc<< 11)/(x1 + md);
b5 = x1 + x2;

Return ((b5 + 8)>>4);
}

Long bmp085GetPressure(unsigned long up)
{
long x1, x2, x3, b3, b6, p;
unsigned long b4, b7;
b6 = b5 - 4000;
// Calculate B3
x1 = (b2 * (b6 * b6)>>12)>>11;
x2 = (ac2 * b6)>>11;
x3 = x1 + x2;
b3 = (((((long)ac1)*4 + x3)<>2;
// Calculate B4
x1 = (ac3 * b6)>>13;
x2 = (b1 * ((b6 * b6)>>12))>>16;
x3 = ((x1 + x2) + 2)>>2;
b4 = (ac4 * (unsigned long)(x3 + 32768))>>15;
b7 = ((unsigned long)(up - b3) * (50000>>OSS));
if (b7< 0x80000000)
p = (b7<<1)/b4;
else
p = (b7/b4)<<1;
x1 = (p>>8) * (p>>8);
x1 = (x1 * 3038)>>16;
x2 = (-7357 * p)>>16;
p += (x1 + x2 + 3791)>>4;
return p;
}

// Read 1 byte from the BMP085 at "address"
char bmp085Read(unsigned char address)
{
unsigned char data;

wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 1);
while(!Wire.available())
;
return Wire.read();
}

Int bmp085ReadInt(unsigned char address)
{
unsigned char msb, lsb;
Wire.beginTransmission(BMP085_ADDRESS);
wire.write(address);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 2);
while(Wire.available()<2)
;
msb = Wire.read();
lsb = Wire.read();
return (int) msb<<8 | lsb;
}

// Read the uncompensated temperature value
unsigned int bmp085ReadUT()
{
unsigned int ut;
// Write 0x2E into Register 0xF4
// This requests a temperature reading
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x2E);
Wire.endTransmission();
// Wait at least 4.5ms
delay(5);
// Read two bytes from registers 0xF6 and 0xF7
ut = bmp085ReadInt(0xF6);
return ut;
}

// Read the uncompensated pressure value
unsigned long bmp085ReadUP()
{
unsigned char msb, lsb, xlsb;
unsigned long up = 0;
// Write 0x34+(OSS<<6) into register 0xF4
// Request a pressure reading w/ oversampling setting
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF4);
Wire.write(0x34 + (OSS<<6));
Wire.endTransmission();
// Wait for conversion, delay time dependent on OSS
delay(2 + (3<// Read register 0xF6 (MSB), 0xF7 (LSB), and 0xF8 (XLSB)
Wire.beginTransmission(BMP085_ADDRESS);
Wire.write(0xF6);
Wire.endTransmission();
Wire.requestFrom(BMP085_ADDRESS, 3);
// Wait for data to become available
while(Wire.available()< 3)
;
msb = Wire.read();
lsb = Wire.read();
xlsb = Wire.read();
up = (((unsigned long) msb<< 16) | ((unsigned long) lsb << 8) | (unsigned long) xlsb) >> (8-OSS);
return up;
}


In addition, the sensor has its own thermal sensor for pressure compensation and an altimeter.

Arduino Nano v3.0
This is the heart of the whole weather station. In simple terms, the controller is in miniature size.
Bought
I will not talk in detail about the controller, since this has already been done before me:


The package with lightake was prefabricated, the controller came in a package with a USB cable and an Arduino in a sealed antistatic bag.

To estimate the size, next to the Arduino put a coin with a face value of 1 ruble.

Controller board close up



The USB cable is good, with a ferrite ring. Powered by Arduino via USB cable. The development environment can be downloaded (download page). The language is “C”-like, there were no problems with mastering it, since I program a lot on it at work.

LCD screen
At work in the bins I found a compatible LCD 1602 screen. I had to tinker with the connection, since I did not find a datasheet for it. As a result, LCD earned.

But after a short operation, I noticed that this screen is not enough for me and I won’t be able to display more data, since it has only 2 lines of 16 characters each. At first it seems that these parameters are enough, but when you start programming, you understand that you can cram a maximum of 3-4 parameters. And if you make a menu (I was thinking about making a menu on this screen), then there is 1-2 free space left for parameters.
As a result, I began to look for another screen. At first I looked at the graphic screen from Nokia 3310 and even participated in the eBay auction to buy it, but it did not work out (which I am very happy about), so I had to give up this screen. Now I understand that it would be too small for my purposes, as there is something to compare with.
While browsing the shields on the Arduino by chance, I came across the 12864 graphics screen on the ST7920 controller. This screen has the right size and good resolution for my needs (128x64). That is, you can safely place 6-7 lines of 20 characters in a normally readable font. Since the screen is graphic, in addition to text in different fonts, graphics can also be placed. In short, this is exactly what I needed, everything was present in this screen, so I could not stand it and ordered.
The parcel arrived quickly and was packaged in a standard way: a bubble wrap, inside there was another layer of bubble wrap and a screen in an antistatic bag:






To estimate the size, next to the LCD put a coin with a face value of 1 ruble.




To quickly connect the screen to the Arduino, I soldered a line of contacts to the LCD pins. LCD can be connected via serial bus and parallel. I chose the first option, since there are so few free Arduino contacts.
Connection (taken from the web):

- Pin 1 (GND) connects to the common bus
- Pin 2 (VCC) is connected to the +5V power bus, and the current consumption is relatively small and the display can be powered from the built-in Arduino regulator.
- Pins 4, 5 and 6 are connected to the Arduino digital outputs, forming the SPI serial interface:
pin 4 - (RS) - corresponds to the CS line (for example 7)
pin 5 - (RW) - corresponds to the MOSI line (for example 8)
pin 6 - (E) - corresponds to the SCK line (for example 3)
Arduino pin numbers can be anything, the main thing is not to forget to correctly indicate them later in the program text when initializing the display.
- Pin 15 (PSB) is connected to the common bus.
- Pins 19 (A) and 20 (K) are backlight power supply (+5V and GND respectively). To adjust the brightness of the backlight, you can use a 10kΩ variable resistor connected between the power rails and GND. The voltage from its engine is applied to pin 19 of the display.
According to this instruction, I connected everything except the backlight. I used the Arduino PWM as the backlight power.
In order to programmatically connect the LCD to the Arduino, the u8glib library is used. You can download. If there are download problems, then I can upload the library to narod.ru.
The library itself is not complicated and allows you to display text in different fonts, draw a line, draw the simplest geometric shapes (rectangle, circle), display your images prepared in a special way. In principle, this tool is sufficient for most tasks.
Here is the result of a simple program:

The program itself:

#include "U8glib.h"

U8GLIB_ST7920_128X64 u8g(3, 9, 8, U8G_PIN_NONE); // SPI E=3, RW=9, RS=8

// Subroutine for determining free memory
int freeRam()(
extern int __heap_start, *__brkval;
intv;
return (int) &v - (__brkval == 0? (int) &__heap_start: (int) __brkval);
}

Void setup(void) (
u8g.setFont(u8g_font_6x10); // font
u8g.setRot180(); // Flip the screen
analogWrite(6, 115); // Set screen brightness (backlight anode to 6 pin)
}

Void loop(void) (
u8g.firstPage();
do(

u8g.setPrintPos(1, 12); // position
u8g.print("Hello!!!"); // text output
u8g.drawBox(0,22,128,9); // Fill The Rectangle With White
u8g.setColorIndex(0); // white ink, black background
u8g.setPrintPos(1, 30); // position
u8g.print("Word..."); // text output

U8g.setColorIndex(1); // white ink, black background
u8g.setPrintPos(1, 50); // position
u8g.print("After start ="); // text output
u8g.setPrintPos(85, 50); // position
u8g.print(millis() / 1000); // output number of seconds after start
u8g.setPrintPos(1, 64); // position
u8g.print(freeRam()); // output how much memory is used
) while(u8g.nextPage());

delay(200);
}

Real time clock DS1307
Another component for my weather station. This shield has a real time clock. I ordered them on eBay. The seller sent a watch handkerchief in an unrealistically large box


Inside the box there were two sheets of A4 with advertising and a watch handkerchief wrapped in cellophane


I want to note that the fee does not exceed the size of 2 rubles. coin, and the box was 13x15x5 cm in size.
The board was packed in an antistatic bag

Shawl up close



I had to tinker with this module. First, there were connection difficulties. And secondly, there is no quartz on this board. If I knew that I would spend so much time on the module, then most likely I would have assembled it myself, since the network is full of schemes. The simplest circuit contains 4-5 components.
Regarding the connection. I found a library that said that the I2C interface can be connected not to the usual Arduino analog inputs (A4 and A5), but to any discrete ones. Did as written. At first, nothing worked, after a long dance with a tambourine, the clock wound up. Well, I thought, that's it, the problems are over, but after I tried to connect the same module to another Arduino, the dancing with the tambourine continued. I spent a lot of time looking for a solution to this problem, and almost everywhere it was indicated either an incorrect connection or the absence of pull-up resistors on the SCL and SDA pins. I already wanted to get into the board with a soldering iron, but on one forum I accidentally stumbled upon a code where it was said that SCL and SDA should be connected to standard I2C ports on the Arduino. After the standard connection, everything immediately worked.
Now about quartz. I don’t know what kind of quartz the Chinese put there, but watches with such quartz ran 10-11 seconds a day. This error is 5 minutes per month, and 1 hour per year. You don't need a clock like this. I had to go online again and look for how to fix this bug. The first solution that came up says that you need to ground the quartz. Did it - zero result. I found somewhere else that I needed to find an old motherboard and unsolder watch quartz from there. Done - the result is. Now the clock runs away not by 10-11 seconds, but by 1.5 seconds per day. Let's just say it got better, but far from ideal. Since it is more reluctant to fiddle with a soldering iron, it was decided to adjust the clock programmatically, that is, once a day, adjust the clock to the desired value. After 10 days, the clock was gone by no more than a second. The method is good, but only when the Arduino timing device is connected to power, otherwise the clock runs on battery and still runs away.
Small test program:

#include "Wire.h"
#define DS1307_I2C_ADDRESS 0x68 // SDA A4, SCL A5

Byte decToBcd(byte val)
{
return ((val/10*16) + (val%10));
}

Byte bcdToDec(byte value)
{
return ((val/16*10) + (val%16));
}

Void setDateDs1307(byte second, // 0-59
byte minute, // 0-59
byte hour) // 0-99
{

Wire.write(0);
Wire.write(decToBcd(second));
Wire.write(decToBcd(minute));
Wire.write(decToBcd(hour));
Wire.endTransmission();
}

Void getDateDs1307(byte *second,
byte*minute,
byte*hour)
{

Wire.beginTransmission(DS1307_I2C_ADDRESS);
Wire.write(0);
Wire.endTransmission();

Wire.requestFrom(DS1307_I2C_ADDRESS, 3);

*second = bcdToDec(Wire.read());
*minute = bcdToDec(Wire.read());
*hour = bcdToDec(Wire.read());
}

Void setup()
{
byte second, minute, hour;
Wire.begin();
Serial.begin(9600);

Second = 45;
minutes = 5;
hours = 16;

SetDateDs1307(second, minute, hour);
}

Void loop()
{
byte second, minute, hour;

GetDateDs1307(&second, &minute, &hour);
Serial.print(hour, DEC);
serial print(":");
Serial.print(minute, DEC);
serial print(":");
Serial.println(second, DEC);

delay(1000);
}


The library is not used here, and the functions are truncated for reading and writing time.

Temperature and humidity sensor DHT11
There is not much to say about this sensor. I wouldn't even use it if I didn't need moisture. Unfortunately, I didn't take a picture of it when I received it, so there won't be any pictures. Photos of the sensor can be seen below, where I connected it to the Arduino. Sensor connection is simple (+, digital output, -). Typically, sensors are made with four pins. With this form factor, the third contact is not connected to anything.
To connect to the Arduino, you can use the library. You can download.
A small test program with information output to the LCD display 1602:

// include the library code:
#include
#include

// Declare objects
dht11 Dht11;
LiquidCrystal lcd(12, 11, 6, 5, 4, 3);

#define DHT11PIN 7
int i;

Void setup()
{
lcd.begin(16, 2);
lcd.print("Status: ");
i=0;
}

Void loop()
{
int chk = DHT11.read(DHT11PIN);
lcd.setCursor(8, 0);
switch (chk)
{
case 0: lcd.print("OK "); break;// lcd.setCursor(11, 0); lcd.print(millis()/2000); break;
case -1: lcd.print(“Checksum error”); merr(); break;
case -2: lcd.print("Time out error"); merr(); break;
default: lcd.print("Unknown error"); merr(); break;
}
delay(500);
lcd.setCursor(15, 0);
switch(i)
{
case 0: lcd.print("^"); lcd.setCursor(15, 1); lcd.print(" ");break;
case 1: lcd.print("v"); lcd.setCursor(15, 1); lcd.print(" ");break;
default: lcd.setCursor(15, 1); lcd.print("E"); break;
}
i=i+1;
if (i>1) i=0;
lcd.setCursor(0, 1);
lcd.print("H=");
lcd.setCursor(2, 1);
lcd.print((float)DHT11.humidity, 0);
lcd.setCursor(4, 1);
lcd print("%");
lcd.setCursor(8, 1);
lcd.print("T=");
lcd.setCursor(10, 1);
lcd.print((float)DHT11.temperature, 0);
lcd.setCursor(12, 1);
lcd.print("C");

Void mErr()
{
lcd.setCursor(2, 1);
lcd.print("**");
lcd.setCursor(10, 1);
lcd.print("**");
i=5;
}


The sensor has disadvantages - the data from the sensor comes only in integers, and the range is weak.

It seems that he wrote about all the components. It remains to collect everything into a single whole.
Oops, almost forgot! In order to assemble the device, you need a case. The case also ordered on Ebay. The seller was from England. The parcel came quickly, but I did not take a picture of it. All photos of the body are below.

First, I assembled everything on the table with the help of special wiring. I wrote a test program and uploaded it to the controller.



In fact, the blue color of the backlight is much brighter. Even at the minimum brightness (Bright=5) the frame is exposed.

To assemble everything without wires, it was decided to make a mini motherboard, and the Arduino board and shields were put on the connectors. In which case, they can be easily removed quickly. I also decided to hook the LCD screen and control buttons on the connectors, only solder the temperature sensor on the wires.
This is how the scarf came out



In the last photo, I haven’t washed off the flux yet. I glued porous rubber under the shields next to the connectors so that there was at least some kind of support. Although, in fact, the shields in the connectors on the contacts are already perfectly held.

Motherboard with shields and Arduino board installed.

This is what a complete connection to the motherboard looks like


Instead of buttons, I used a homemade shield soldered on a breadboard. As buttons I used buttons from old mice.
As you can see, the number of wires has decreased.

The main problem of placement in the case is to cut out the groove for the LCD screen evenly. No matter how hard I tried, it still didn't work out perfectly. The gaps in some places were slightly more than 1 mm. To make everything look neat, I took a black sealant for the aquarium and filled in all the cracks, at the same time I attached the screen to this particular sealant. After the sealant had dried, I cut off the excess from the outside. In bright light, the sealant is visible, and in normal light, everything merges with the case.
This is what the case looks like from the inside with the LCD screen and the motherboard installed.

This is what it looks like from the outside in bright light (I apologize for the fingerprints, I saw them when I was sorting out the photos).

I thought for a long time how to attach the buttons to the case and, most importantly, which buttons to use ...
In electronic stores, I liked the button with a long pin and the tips that are put on this pin. These buttons are used for soldering to the board. Everything would be fine, but they have a minus - the pressing stroke is very small and loud.
I had to place the buttons in two stages: the first was to place the buttons on the board, the second was to mount this board on another board. And then put all this into the body on the guides.

This is how the scarf with buttons looks like:



This is what the board looks like:


Here you can see the guides into which the board with the buttons is inserted. I soldered some elements in order to stiffen the board.

Now we put everything in the body
Without connecting buttons:


With button connection:

Close the box and turn it on. Everything works fine, the buttons work as they should.

At the end I post a short video of the device in different modes:
http://www.youtube.com/watch?v=KsiVaUWkXNA&feature=youtu.be
For those who don't see the video here, here's the link to

It's time to end the review.
I will write a little about the program, and then brief conclusions. When I wrote the program, I did not think that I would run into a limit of 30720 bytes very quickly.


I had to optimize the code. Moved many pieces of code into subroutines. I would never have thought that a switch ... case statement in a compiled form takes up more space than several if ... else. The correct declaration of variables also saves space. If you declare an array long, although it is quite possible to get by with byte, then the memory overrun reaches 500 bytes, depending on the size of the array. When you write a program, you don’t think about it, and only later, when you analyze the program, you realize that you did some things wrong, and you start optimizing the code. After the problems with the size of the program were resolved, I ran into a limitation of RAM. This was expressed in the fact that the program began to hang after loading. I had to enter a subroutine for calculating free RAM. As a result, I was forced to abandon one weather prediction algorithm, since it must display icons on the screen. The algorithm itself works, but the output of the icons had to be reserved. I still have ideas on how to optimize the code, but in the near future I will leave the device working as it is in order to evaluate performance and identify all bugs.

Now some conclusions
Minuses
1) Price. The excuse for this minus is that a hobby is never cheap.

pros
1) Great functionality of the device
2) Function expansion is limited only by the controller used and your own desire
3) Aesthetic pleasure from contemplation and moral satisfaction from the fact that I nevertheless assembled and completed this device

I plan to buy +86 Add to favorites Liked the review +137 +304

“So, let's agree right away: you are not going to make a movie for Hollywood. Even in Wonderland, no more than five percent of all scripts are approved, and only one percent then goes into production ... So, instead of all this, you are going to create your own Hollywood. ”
Ed Gaskel "Shooting digital cinema, or Hollywood at home"

Foreword

What, another Arduino weather station?! Yes, one more and, something tells me, not the last one in the Internet of things.


Just as every programmer is required to write a “Hello World!” program, so every arduinian must have experience in building a simple or not very weather station.
A considerable number of already created projects of weather stations on the Internet are described, the reader can choose any of them for implementation. Frankly, I carefully studied about a dozen similar projects and a bunch of related ones. Therefore, it cannot be said that I created everything from scratch, of course I "stood on the shoulders of giants."


I must say right away that my plans did not include the use of third-party services for storing and displaying data. I wanted to personally feel and understand how it all works from the inside from beginning to end, from A to Z.


So for those who want to quickly rivet something out of nothing, this series of articles is most likely not suitable. It's easier to go and buy a ready-made kit with assembly instructions. Microelectronics professionals have absolutely nothing to do here, maybe neighing and remember themselves at the beginning of the journey.
But for those who really want to understand, I think they will like it. Perhaps the material will be useful as a teaching aid.



This project was implemented back in 2016, but I hope it is still relevant.

Technology set

We will study and work with simple and complex things:

  • temperature and humidity sensors type DHT22, DHT11
  • barometric pressure sensor type BMP180
  • WiFi module ESP8266
  • radio module type nRF24 2.4 GHz
  • family Arduino Pro Mini, Arduino Mega
  • solar panels and batteries
  • programming language C/C++
  • PHP programming language
  • MySQL database management system
  • the Java programming language and the Android framework (creating an application for Adnroid to display weather data on a smartphone).

Some of the topics listed are not worth a damn, and some can be studied for years. Therefore, we will touch on complex things only in the part directly related to this project, so that you understand how it all works.


But we'll start from the very beginning right. Namely, from the description and design of the future device "on the paper" so that in the end each brick lay in its place.

prototyping

As Wikipedia correctly tells us, prototyping is a quick draft implementation of a working system. Which, yes, will not work completely inefficiently and with some errors, but will give an idea of ​​​​whether the craft should be developed to an industrial design. The process of creating a prototype should not be long. The prototyping stage is followed by the analysis of the system and its refinement.


But this is in an industry where workers are employed full time.


Everyone who rivets their pet-project crafts for the “internet of things” in the evenings should be aware that they are creating a prototype, a semi-finished product. It is very far from the level of a normal industrial product. That's why you should not entrust our amateur crafts with any critical life support areas and hope they don't let us down.


An industrial product is built on an industrial element base and then goes through many more stages, including debugging, testing and maintenance, before it becomes a bestseller.


So, instead of all this tedium, we will create our own toy, but not a simple one. With elements of technical creativity, the beginnings of programming and knowledge (in the process of creation) of many other related things.


Of course, electronics engineers will have a hard time at the programming stage, and programmers will have to sweat over circuitry, but the author will try to state everything as accessible as possible and clearly describe why certain solutions were used.

Requirements

Usually this step is skipped. Deciding to do something like this right now, and then it turns out small details that put the whole project in a dead end or even make it unbearable. All our Wishlist needs to be recorded, I use Google Drive for this, it is available from a PC and from a mobile device.


So, our weather station should:

  • measure temperature and humidity outside
  • measure the temperature and humidity in the house
  • measure atmospheric pressure
  • display the indicated values ​​on the display
  • transfer data to a server on the Internet, where the data will be stored in a database and displayed on a web page, or used in a mobile application.

Sensors are used the simplest and cheapest. For example, looking ahead, I’ll say that the DHT22 measures temperature quite accurately, but it’s a little inaccurate with humidity. But, again, I repeat, it does not matter, because we have a prototype in front of us, and a scatter of 5% humidity will not affect anything important in our life.


The system architecture, hardware and software must allow the system to be further extensible to add new sensors and new capabilities.

Iron. Component Selection

This is the most important part, and not soldering or programming at all. After defining the requirements for the system, it is necessary to decide with the help of what exactly they will be implemented.


Here there is one nuance. To select components, you need to know their capabilities well, you need to know the technologies themselves. That is, in other words, here you need to be far from a beginner electronics engineer and programmer. So what now to spend a couple of years studying the whole range of possible devices?


Vicious circle? But vicious circles exist in order to break them.


There is an exit. You can just take and repeat someone's project. I studied the already existing projects of weather stations and I hope I took a step forward.


So. The architecture of the weather station is based on the Arduino. Because Arduino has a small threshold of entry and I have already dealt with this. Then it's easier to choose.


It immediately became clear that the weather station would include a remote, out-of-window sensor and a central module.


The central, main unit will be located indoors. It is important to determine this at the initial stage; such important characteristics as the temperature regime of operation and power “dance” from this.


The remote sensor (or sensors) will be without "brains", its task is to periodically take measurements and transmit data to the central home unit. The central unit receives data from all sensors, displays them on the screen and sends them to the Internet to the database. Well, it’s already much easier there, as soon as the data is in the database, you can do whatever you want with it, even draw graphs.


For communication with the outside world, the Internet was unequivocally chosen by the ESP8266 WiFi module with almost no alternative (note, perhaps now such alternatives have appeared). Ethernet expansion boards are available for Arduino, but I didn’t want to be tied to a cable at all.



An interesting question was how to provide communication between the outside sensor (or sensors, remember about the requirement for system expandability?) and the center. 433 MHz radio beacons are definitely not suitable (they are not suitable for anything at all).


Use ESP8266 again?


Cons of this solution:

    Requires stable WiFi outside the home

    communication range will not be great

    reliability will suffer, if the Internet fails, we will not see our remote sensors

    more power consumption.

    Power Consumption ESP8266:

    when transmitting 120-170 mA

    when receiving 50-56 mA

    in Deep Sleep mode 10 µA (µA)

    off state 5 µA (µA).

In the end, to connect remote sensors with the main home unit, the nRF24L01 + chip with a 2.4 GHz transmitter and receiver in one bottle was chosen, with an additional external antenna, to certainly “break through” the walls.



Power consumption nRF24L01+ 2.4 GHz:

  • when receiving 11 mA
  • when transmitting at a speed of 2Mbps - 13 mA
  • in standby-I mode - 26 μA (μA)
  • off state 900 nA (nA).

Both the ESP8266 and the nRF24L01+ have a suitable operating temperature range: from -40℃ to +80℃.


You can buy the nRF24L01+ for about $1, or with an external antenna for $3. You can buy ESP8266-01 for about $4. Read the product description carefully! Otherwise, buy one antenna.


The core of the system emerged. Let's move on to the sensors themselves.


On the street, as you know, the temperature can reach negative values, so the DHT11 sensor is not suitable, but the DHT22 is just right.



Specifications of DHT22 / AM2302:

  • 3.3V to 5V supply, 5V recommended
  • consumption 2.5mA maximum, at the time of measurement and data transfer
  • humidity measurement range 0-100% with an error of 2-5%
  • temperature measurement range from -40 to +125°C with an error of ±0.5°C
  • request for measurement no more than 0.5 Hz - once every 2 seconds.

Inside the house, I hope there will be no negative temperatures, so you can use DHT11, especially since I already had it.


Features of DHT11:

  • 3.3V to 5V supply
  • consumption 2.5 mA maximum, at the time of measurement and data transfer
  • humidity measurement range 20-80% with an error of 5%
  • temperature measurement range from 0 to +50°C with an error of ±2°C
  • measurement request no more than 1 Hz - once per second.

You can buy DHT22 for about $3. DHT11 costs less - $1, but it is also less accurate.


Now back to the Arduino again. Which board to choose?


I tested individual parts of the system on the Arduino UNO. Those. I connected the ESP module to the uno and studied it, turned it off, then connected the nRF24, etc. For the final implementation of the window sensor, I chose the Arduino Pro Mini as the closest miniature to the Uno.



In terms of power consumption, the Arduino Pro Mini also looks good:

  • there is no USB-TTL converter, which itself "eats" a lot,
  • The LED is connected through a 10k resistor.

For advanced energy conservation, it was planned:

  • remove the LED - power indicator on the Arduino Pro Mini (I regretted not spoiling the board)
  • or use a "bare" assembly on an Atmel ATmega328 microprocessor (did not use it)
  • use the Low Power Library or JeeLib .

From the libraries I chose Low Power Library, it is simple and contains only what you need.


For the central unit, since it was planned to connect numerous peripherals to it, the Arduino Mega board was chosen. In addition, it is fully compatible with UNO and has more memory. Looking ahead, I will say that this choice was fully justified.


You can buy Arduino Mega for about $8.

Power and power consumption

Now about food and power consumption.


There are two types of Arduino Pro Mini:

  • for supply voltage 5V and frequency 16MHz
  • for a supply voltage of 3.3V and a frequency of 8MHz.

Since the nRF24L01+ radio module requires 3.3V for power supply, and speed is not important here, buy an Arduino Pro Mini at 8MHz and 3.3V.


In this case, the supply voltage range of the Arduino Pro Mini is:

  • 3.35-12V for 3.3V model
  • 5-12V for 5V model.

I already had a 5V Arduino Pro Mini, which is why I used it. You can buy an Arduino Pro Mini for about $4.


The power supply of the central unit will be from the 220 V network through a small power supply unit, giving an output of 12V, 450mA, 5W. Something like this for $5. There is also a separate output for 5V.



And if this is not enough, then you can put it more powerfully. In other words, saving power for the central unit does not make much sense. But for a remote wireless sensor, energy saving is the most important part. But I don't want to lose functionality either.


Therefore, the Arduino Pro Mini and the nRF24 radio module will be powered by a bundle of 4 Ni-Mh batteries.


And remember maximum capacity of a modern battery about 2500-2700mAh, anything more is either a marketing gimmick (Ansmann 2850) or a hoax (UltraFire 3500).


I do not use Li-Ion batteries for several reasons:

  • very expensive
  • when the ambient temperature drops below 0°C, the power of the lithium-ion battery decreases to 40-50%
  • those that are cheap are made without protection and are unsafe (during a short circuit or discharge, they can explode and burn, see a bunch of videos on YouTube)
  • grow old, even if they are not used (however, this can be said about all chemical elements), after 2 years a Li-Ion battery loses about 20% of its capacity.

For a prototype, it is quite possible to get by with high-quality Ni-MH AA or AAA batteries. Moreover, we do not need large currents. The only disadvantage of Ni-MH batteries is their long charging time.

General scheme of the weather station

Let's summarize. Here is a general diagram of how it all works.



To be continued.