Weather station: from idea to implementation

Published on May 23, 2014

Weather station: from idea to implementation


I read many articles on the development of my device, and wanted to talk about my experience. This happened a few years ago, in the 4th year of university. Now I would have done a lot differently, and at that time I was just starting to master electronics, this is my first device, so do not judge strictly.

I always wanted something more than a regular thermometer outside the window or an LCD screen of a weather station with temperatures outside and in the room. Therefore, when I thought, “what is to be done” in order to begin acquaintance with the world of microcontrollers, the answer was found by itself - my weather station. Naturally, with the display of degrees on the street and indoors, humidity and pressure. And with backlighting - I always liked the implementation of weather forecasts on Yandex - one look at the background is enough to understand if it will be warm or cold, and how much.

All further functionality was determined by a small brainstorming session. The presence of lighting is certainly a plus, but what about night and evening? I decided to install a proximity sensor. When approaching the device at a comfortable distance, the backlight turns on, at other times the screen does not light up by default. The use of IR prompted the implementation of control of the device also via the IR channel - through the remote control (at first there were fears of mutual interference, but they were not confirmed). It is quite natural for such a device to have a watch.

Arduino, which I was just starting to master, was chosen as the basis for the system. I consider Arduino itself now (and even then), as a framework - primarily a software one, which allows you to quickly build the necessary system, connecting library plug-ins if necessary. Yes, we can write in pure C / C ++, but in most ordinary tasks this gives only a slight performance increase, almost imperceptible against the background of the simplicity and convenience of loading sketches into Arduino, as well as an extensive collection of libraries for working with various hardware. (It goes without saying that there are special tasks, but now we are not talking about them).
In the hardware implementation, I prefer to use the blue Arduino board only at the prototyping stage on the “breadboard”, and at the end of the development of devices, I usually design a single board with a microcontroller and everything else. So it was that time.

I started the selection of components from the screen. Pretty quickly I found a wonderful screen with RGB-backlight www.adafruit.com/products/398 , which allowed to get almost any color. It is built on the popular HD44780 chip and is supported by a huge number of libraries, including LiquidCrystal in Arduino.

I also asked about the prices of custom-made displays. The minimum price for 1 copy of a monochrome LCD (as in a typical weather station) at that time was about 1,000 euros, for a non-commercial project in a single copy, I found such a price tag inappropriate. Sharp GP2Y0A02YK0F



was chosen as an IR sensor . An important characteristic in my case was the range of detection of objects, for this sensor it is 1.5 m, while for many other sensors it does not exceed 30 cm. As shown by the operation, for a small 16x2 screen a meter and a half is really the optimal distance. Bosch BMP085 , working according to I2C , humidity HH10D , was chosen as a pressure sensor

- with a frequency output. Looking ahead, I’ll say that now I would in no case use the latter, but would prefer exclusively I2C options, for example, HTU21D.

As external temperature sensors, everyone's favorite DS18B20 was used . Their huge advantage is the ability to connect (and disconnect if necessary) several sensors at once to one bus, without having to change the program code. I did not get involved in the wireless transmission of temperature data in my first project, especially since I had the opportunity to lay wires without compromising aesthetics.

The infrared receiver was taken the most typical, type TSOP382. The remote control for some weather recorder became the remote control for the weather station. The buzzer (aka squeaker) is the most common piezo emitter.



As a real-time clock, I chose the DS1307 , which also works on I2C, in addition, I had a tiny 24KA256 flash memory chip on 64 KB with an I2C interface. I added it to the project out of sheer curiosity - to try working with external memory by writing weather data into it. Power for the project is external, from the power supply. At the input there is a LM7805 voltage converter / stabilizer , the power supply itself is very similar to that used in Arduino (although it is not a clone).

I carried out the development by iterations, it is much easier to debug and get acquainted with a new area for myself. At the very first stage, data was read from the DS18B20 thermometer and displayed on the LCD screen. On the next - the temperature values ​​should have been converted into an RGB code for backlighting.

Here I was in wait for a color rendering feature. Screen color is controlled by pulse-width modulation for each of the three backlight LEDs (using the standard library) with 256 steps - it would seem to be a quite ordinary 24-bit color. Unfortunately, the wavelengths for the R, G and B colors of the monitor and the backlight LEDs are very different, and because of this, the usual colors like # ffff00 look completely different on the background of my LCD screen (“go to the side”). Therefore, I had to write a program in C # with three sliders and a color picker, transferring the three color components to the Arduino serial port. Then I had to recall the basics of mathematics and compose a function that converts the temperature in degrees Celsius into an RGB color scale. Naturally, I was no longer limited to the yellow-blue Yandex scale,

The next step was to connect the IR range finder, temperature and humidity sensors. And, if there were no difficulties with the first two (except for soldering BMP085 in the LCC8 package), then the humidity sensor caused a lot of problems.

The thing is that the final value of relative humidity is calculated by the formula, one of the arguments of which is the meander frequency at the sensor output. Frequency measurement is performed using the hardware timer of the microcontroller. In 328, unfortunately, there are only three such timers, and most of them are already used during PWM to illuminate the display. (Now I don’t remember all the details, maybe I missed something).

There were several ways out of this situation. If I were developing a device today, I would definitely use only I2C sensors. Another option was to use a more powerful microcontroller. I then chose the third option - to install a separate microcontroller for working with sound (tweeter) and backlight (I recall, it was primarily an educational project, and it was interesting for me to try to organize interaction between two MKs). The function of converting temperature to color has also been transferred to it, which facilitated the firmware of the main MK by a couple of kilobytes (in Atmega328 the program memory size is only 32Kb, my firmware eventually came close to this limit). The interaction between MK was still organized according to I2C.

After that, the remote control, clock, flash memory were added. The next stage was writing a convenient menu, adding software features (such as locking the backlight in the current state, large digits mode - like on a street clock, scrolling through all the parameters), supporting several temperature sensors with adding / removing them online (yes, I know that it’s better not to do that). It’s quite a common thing for a PC - and unusual at first for the device you assembled, when without changing the circuit the project’s functionality increases several times ...

The console used some proprietary protocol. I did not engage in its reverse engineering; the hexadecimal representation of each button that I received from the IRRemote library was quite enough for me. For flash memory, I chose to record weather data every 10 minutes, with a record length of 16 bytes this lasts for 4 months.

Code for working with flash memory
LOGGER.h
#ifndef LOGGER_h
#define LOGGER_h
#include <WProgram.h>
class LOGGER {
 public:
    LOGGER(int);
    void storeRecord16(byte* buffer);
    void getRecord16(unsigned int address, byte* buffer);
    int getAddress();
    void setAddress(int);
 private:
    int _FlashI2CAddress;
    void _getAddress();
    void _setAddress();
    unsigned int _addr;
};
#endif

LOGGER.cpp
#include <WProgram.h>
#include <Wire.h>
#include "LOGGER.h"
/*
MEMORY MAP:
0000 - MSB of last written address
0001 - LSB of last written address
...
0040 - 7FFF - storage,
*/
    LOGGER::LOGGER(int a)
    {
       _FlashI2CAddress = a;
     }
void LOGGER::storeRecord16(byte* buffer)
{
    byte c;
    //get address
     LOGGER::_getAddress();
    //increase addr
    delay(5);
    _addr+=16;
   if(_addr>0x7FF0) _addr = 64;
    //store buffer
    Wire.beginTransmission(_FlashI2CAddress);
    Wire.send((byte) (_addr >> 8) & 0xFF); // MSB
    Wire.send((byte) (_addr & 0xFF) );     // LSB
    for ( c = 0; c < 16; c++)
      Wire.send(buffer[c]);
    Wire.endTransmission();
    delay(20);
    //save new addr
    LOGGER::_setAddress();
}
void LOGGER::getRecord16(unsigned int address, byte* buffer)
{
    byte c;
    //set address
    Wire.beginTransmission(_FlashI2CAddress);
    Wire.send((byte) (address >> 8) & 0xFF); // MSB
    Wire.send((byte) (address & 0xFF) );     // LSB
    Wire.endTransmission();
    Wire.requestFrom(_FlashI2CAddress,16);
    for (c = 0; c < 16; c++ )
      if (Wire.available()) buffer[c] = Wire.receive();
}
void LOGGER::_getAddress()
{
    byte c;
    Wire.beginTransmission(_FlashI2CAddress);
    Wire.send(0); 
    Wire.send(0); 
    Wire.endTransmission();
    Wire.requestFrom(_FlashI2CAddress,2);
    for (c = 0; c < 2; c++ )
      if (Wire.available()) _addr = _addr * 256 + Wire.receive();
}
void LOGGER::_setAddress()
{
    Wire.beginTransmission(_FlashI2CAddress);
    Wire.send(0); // pointer
    Wire.send(0); // pointer
    Wire.send((byte) (_addr >> 8) & 0xFF); // MSB
    Wire.send((byte) (_addr & 0xFF) );     // LSB
    Wire.endTransmission();
}
void LOGGER::setAddress(int addr)
{
  _addr = addr;
  LOGGER::_setAddress();
}
int LOGGER::getAddress()
{
  LOGGER::_getAddress();
  return _addr;
}



Data is unloaded by a command from the weather station menu (somewhat reminiscent of the old Nokia or Samsung menu, only without graphics) to the serial port.

After that, the functionally completed weather station stayed in the form of Arduino and breadboard for about a week. During this time, tests revealed the possibility of freezing (caused by a violation of the tightness of the street temperature sensor). I redesigned the sensor design (today I would take only a factory one, for example, one ), but I also wanted to exclude the possibility of freezes in principle. In addition, I suggested that after 49 days of continuous operation, the millis () function will overflow., which, due to the features of the firmware algorithm, will also lead to a freeze. The thing must be reliable! Therefore, the last touch in the system was the activation of the watchdog timer, as a result, any hang-up does not last guaranteed for more than 2 seconds + 5 seconds on reboot (yes, in our digital age even weather stations need time to load.

So, the station is ready and successfully working. I think that it’s wrong to stop at this stage.The device should be convenient and have a finished look, so that it can be used comfortably and shown to everyone, not just geek friends.

I started by going to the nearest radio store and choosing a building. Of the 20-30 different options, I liked the one in the figure at the beginning of the article - because of the minimum required alteration, because of the ability to conveniently fix the range finder on the outside of the case, so that it does not protrude strongly, due to good ventilation (which means , more accurate temperature readings in the room). Today, probably, I would order printing on a 3D printer and do something in this style:



(It’s hard to find a similar picture, but in 3D modeling I’m not a pro. The screen is located at the top, everything else is in the stand). And, of course, no wires - 433 MHz for sensors and Wi-Fi for communication with a PC.

After trying and thinking about how to arrange everything better, it was the turn of the board development. In my first project, I used the Eagle system. He drew the circuit of the board, placed elements and connections on it (yes, I did this project in the “wrong” way - without a circuit diagram. More precisely, without a circuit in Eagle), the tracer easily set everything apart. Took it to production ...

Habré is very fond of the topic of manufacturing printed circuit boards, so here I will make a digression. I am familiar with LUT, but I have no desire / ability to make boards, including contacting chemistry (ferric chloride is another thing). But at the university there is a small pilot production, where at very reasonable prices (~ $ 3 per sq. Dm. At that time) they can produce almost any two-sided software. Technology - photoresist, holes - from 0.6mm, the minimum track width - seems to be 0.2mm (certainly not larger, now I can’t remember). Unfortunately, one does not have to wait for any solder masks, metallization of vias for this price, but this is all solved. In the end, for prototyping (and boards are prepared in a day or two) and small-scale production, you can do without masks (IMHO; I mean soldering manually and large).


However, when I made the order, I did not think about metallization of vias. Eagle safely used the legs of the elements as such, and cost only 2-3 separate joints between the layers. The issuing person drew attention to this and kindly offered the thinnest wire to create transitions in the holes for the elements (that is, first the wires are soldered through the hole to the upper and lower contact pads, after which the element leg itself is already inserted into it). I tried to act this way, but the results and the amount of additional work did not inspire optimism. I had to redirect the board, creating prohibition zones for the via location near all PTH elements. Then the automatic tracer refused to finish the job, and I had to breed the remaining chains manually (there was no desire and time to change the design system). The vias themselves were eventually made using exactly the same technology, but I minimized their number. Soldering a newly ordered board was incomparably easier.

Next - work with a drill, knife and files, the case acquired a window for the screen, mounts for the board. A couple of evenings - and the device in the case works successfully. And yet, something is missing ...

And there is not enough sticker on the front panel (especially after cutting through the window in it). Self-adhesive paper is a great thing for such tasks. What happened - in the title photo, do not judge strictly :) After that, the appearance of the device changed radically ...

That's how (in short) my development path for my first device looked like. There is a lot of code behind the scenes, many solutions of various small problems that arose during the course of the task. The main thing that I gained for myself was the development experience, the stuffed up "bumps", understanding of the principles of work, plus the weather station itself became a bonus. Unique and one of a kind.



PS I know that many of the solutions are not optimal, but it is thanks to them (including) that I now understand what is optimal and what is not :). As a bonus, I enclose a functional diagram in English and several photos, as well as a render of the board.

Functional diagram:





Render, a real board without a solder mask. A lithium battery holder, a piezo emitter, a DIN connector (power, PC connection, sensors) and various small things are not shown. In addition, in a real device, microcontrollers are in sockets.

The Big Digits mode, for better readability from afar: