Charger for lithium battery 12V. Selecting a charger for lithium batteries. How to assemble a charger for lithium-ion batteries with your own hands

Charger for lithium battery 12V.  Selecting a charger for lithium batteries.  How to assemble a charger for lithium-ion batteries with your own hands
Charger for lithium battery 12V. Selecting a charger for lithium batteries. How to assemble a charger for lithium-ion batteries with your own hands

We continue to develop our weather station.

Before we move on to the update, I want to clarify a little.

One of our colleagues wrote to me asking why the watchdog timer was introduced?

The watchdog timer is in place in case of an emergency. As practice shows, the ENC28J60 does not handle more than (unless the memory fails) 4 simultaneous connections. Considering how many service connections constantly occur to maintain the operation of the network itself, and just left traffic created by all sorts of household toys (for example, modern televisions, scan available hosts on the network and their open ports) the design simply goes into a stupor. The ENC28J60 cannot work independently with network protocols and everything is implemented in libraries. Perhaps it's just them.
I checked all available libraries and different modules (suddenly defective), but achieved stable operation I couldn't do it for a long time. Maximum term was about 3-4 weeks.
This is why the “dog” spins there and, if something happens, pulls the controller. After this the problem went away.
I also do not deny that it is possible in my home network there are certain nuances or problems. But since I had a problem, another person may have it too. So far I have only found this solution.
As far as I know, chips from Wiznet (W5100 and higher) do not have this, or they just didn’t look well enough.

Let's move on to the update

Most importantly, we are moving away from the chip ENC28J60 and go to W5100. I tried to implement everything on the old chip, but there is not enough microcontroller memory due to very large libraries For ENC28J60. When using a new chip, standard libraries from the developer and everyone changes made, there remains even more 20% free microcontroller memory ATMega328. And these are new buns!

In this version (let's call it the second) the ability to transmit readings from sensors via wireless communication using frequency 433 MHz. I took the modules themselves from the Chinese, markings XY-MK-5V. I would like to note that the quality of the transmission is far from perfect. Possible signal loss, noise, inability to transmit simultaneously, etc., etc. But their price (less than $1 per set) compensates for these shortcomings. I’ll tell you a secret that these (the cheapest) modules are found in many branded weather stations for home use. Wow, unexpected?

Let's start with the base station

We are moving to Arduino UNO And Ethernet Shield(first version) based on chip W5100. This is a sandwich and there is no point in describing it. I will only describe the additionally involved contacts for the modules XY-MK-5V.

The transmitter module uses power 5V, GND(where would we be without mother) and D2 pin on the controller. Edit contact D2 (DATA) you can use the function vw_set_tx_pin from the vw library.

Unlike the previous sketch, this one uses two additional libraries:

#include #include

The sketch itself

Hidden text

#include #include #include #include #include #include #include #include #define DHTTYPE DHT22 #define DHTPIN 5 DHT dht(DHTPIN, DHTTYPE); byte mac = (0x54, 0x34, 0x31, 0x31, 0x31, 0x31); char server = "narodmon.ru"; int port = 8283; IPAddress ip(192,168,0,201); EthernetClient client; BMP085 dps = BMP085(); long Temperature = 0, Pressure = 0; float H, dP, dPt; bool interval = true; EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // Device ID int Temperature; // Temperature float Pressure; // Pressure float Humidity; // Humidity float dewPoint; // Dew/frost point ); SEND_DATA_STRUCTURE broadcast; void setup() ( // Initialize the Watchdog timer wdt_disable(); delay(8000); wdt_enable(WDTO_8S); // Initialize the console Serial.begin(9600); // Initialize the DHT sensor dht.begin(); // Initializing the 433 MHz module ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_tx_pin(2); if (Ethernet.begin(mac) == 0) Ethernet.begin(mac, ip); // Initializing 1-Wire Wire.begin(); // Initializing BMP180 with height adjustment // dps.init (MODE_STANDARD, 3200, true); // Initialize BMP180 dps.init(); Serial.println(Ethernet.localIP()); // Send the first data immediately after turning on the device send_info(true) // dewPoint function NOAA / / reference (1) : http://wahiduddin.net/calc/density_algorithms.htm // reference (2) : http://www.colorado.edu/geography/weather_station/Geog_site/about.htm double dewPoint(double celsius , double humidity) ( // (1) Saturation Vapor Pressure = ESGG(T) double RATIO = 373.15 / (273.15 + celsius); double RHS = -7.90298 * (RATIO - 1); RHS += 5.02808 * log10(RATIO); RHS += -1.3816e-7 * (pow(10, (11.344 * (1 - 1/RATIO))) - 1) ; RHS += 8.1328e-3 * (pow(10, (-3.49149 * (RATIO - 1))) - 1) ; RHS += log10(1013.246); // factor -3 is to adjust units - Vapor Pressure SVP * humidity double VP = pow(10, RHS - 3) * humidity; // (2) DEWPOINT = F(Vapor Pressure) double T = log(VP/0.61078); // temp var return (241.88 * T) / (17.558 - T); ) void send_info(bool eth) ( bool fail = true; while(fail) ( // We try to read data from the DHT humidity sensor until we get // a result. In 90% of cases everything works fine, but we need 100 % if((H = dht.readHumidity()) >= 0) ( // Getting humidity and temperature from the BMP180 sensor dps.getPressure(&Pressure); dps.getTemperature(&Temperature); // Calculate the dew point if the temperature is outside above 0 degrees Celsius // and expect a result above 0, otherwise output 0. This is necessary // so as not to be misleading during the winter season. // dP = Temperature>0?((dPt=dewPoint(Temperature*0.1, H))<0?0:dPt):0; dP = dewPoint(Temperature*0.1, H); // Отправляем данные в эфир 433 мГц broadcast.ID = 1; broadcast.Temperature = floor(Temperature*0.1); broadcast.Pressure = floor(Pressure/133.3*10)/10; broadcast.Humidity = floor(H*10)/10; broadcast.dewPoint = floor(dP*10)/10; ET.sendData(); delay(250); if(eth) { // Подключаемся к серверу "Народный мониторинг" if(client.connect(server, port)) { // Начинаем передачу данных // адрес_устройства_в_проекте, имя_устройства, GPS широта, GPS долгота client.print(F("#fe-31-31-0e-5a-3b#Arduino Uno#71.344699#27.200014\n")); // Температура client.print(F("#T0#")); client.print(Temperature*0.1); client.print(F("#Температура\n")); // Давление client.print("#P1#"); client.print(Pressure/133.3); client.print(F("#Давление\n")); // Влажность client.print("#H1#"); client.print(H); client.print(F("#Влажность\n")); // Точка росы\инея client.print("#T1#"); client.print(dP); client.print((dP <= 0)? F("#Точка инея\n"):F("#Точка росы\n")); //client.print(F("#Точка росы\n")); // Отправляем конец телеграммы client.print("##"); // Даем время отработать Ethernet модулю и разрываем соединение delay(250); client.stop(); } } // Останавливаем цикл, если передача завершена fail = !fail; break; } delay(250); } } void loop() { // Каждые 4 секунды сбрасываем сторожевой таймер микроконтроллера // Каждые 6 минут отправляем данные на "Народный мониторинг" // Каждые 30 секунд отсылаем данные в эфир 433 if(!(millis()%1000)) wdt_reset(); if(!(millis()%360000)) send_info(true); if(!(millis()%30000)) send_info(false); }

An antenna must be added to the modules themselves. For 433 MHz An ordinary long copper wire is enough 17 cm. Without an antenna, you can forget about normal operation.

Let's move on to the most important part of this update - the local wireless station

To implement it (on the knee) I used an analogue Arduino NANO(on the base ATMega328) And TFT display on a chip ST7735S with permission 128 x 160

Hidden text



Pinout display -> controller

============================ LED | 3.3V SCK | SCK (13) SDA | MOSI(11)A0 | DC (9) RESET | RST(8)CS | CS (10) GND | GND VCC | 5V ============================

The receiver module is connected in the same way as a transmitter, only DATA to pin D7.

A couple of pictures of what it looks like:

Hidden text

Receiver sketch

Hidden text

#include #include #include #include int x, y; int w = 128, h = 160; int size; // 433 EasyTransferVirtualWire ET; struct SEND_DATA_STRUCTURE( byte ID; // Device ID int Temperature; // Temperature float Pressure; // Pressure float Humidity; // Humidity float dewPoint; // Dew/frost point ); SEND_DATA_STRUCTURE broadcast; int Log_Temperature = -1; float Log_Pressure = -1; float Log_Humidity = -1; float Log_dewPoint = -1; // TFT #define cs 10 #define dc 9 #define rst 8 char Temperature, Pressure, Humidity, dewPoint; String info; TFT TFTscreen = TFT(cs, dc, rst); void setup())( Serial.begin(9600); // Initialization of the 433 MHz module ET.begin(details(broadcast)); vw_set_ptt_inverted(true); vw_set_rx_pin(7); vw_setup(2000); vw_rx_start(); // Initialization and initial display setup TFTscreen.begin(); TFTscreen.setRotation(2); TFTscreen.background(0, 0, 0); // Draw static elements // 1. Come visit us TFTscreen.stroke(255, 255, 255); TFTscreen.setTextSize(1); TFTscreen.text(" ", 10, 10); // 2. Description of readings from sensors TFTscreen.text("mmHg", w/2+5, 80); ("%", w/2+5, 100); TFTscreen.text("C", w/2+5, 120); broadcast.Temperature = 0; broadcast.Humidity = 0; .dewPoint = 0; TFTPrint(); ) void loop())( if(ET.receiveData())( if(broadcast.ID == 1) TFTPrint(); /* Serial.println(broadcast.Temperature); Serial. println(broadcast.Pressure); Serial.println(broadcast.Humidity); Serial.println(); */ ) void changes(int size, int y, bool up, bool clear = false) ( if(clear) TFTscreen.stroke(0, 0, 0); else ( changes(size, x, y, !up, true); TFTscreen.stroke((up)?0:255, 0, (up)?255:0); ) if((size%2) == 0 ) size++; while(size > 0) ( TFTscreen.line(x, y, x+(size--), y); ++x, (up)?--y:++y, --size; ) /* while( size > 0) ( TFTscreen.line(x, y, (up)?x+size-1:x, (up)?y:y+size-1); ++x, ++y, --size; ) */ ) int x_center(int w, int length, int size) ( return floor((w-length*(size*5)+size*2)/2); ) int x_alignment_right(int w, int length, int size) ( return ceil(w-length*(size*5)+size*2); ) void TFTPrint() ( size = 3; // ================= ===================================================== =============== // Display temperature readings // ============== ===================================================== ==== if(broadcast.Temperature != Log_Temperature) ( TFTscreen.setTextSize(size); // Overwrite obsolete data String info = String(Log_Temperature); info.concat(" C"); if(Log_Temperature > 0) info = "+"+info; info.toCharArray(Temperature, info.length()+1); TFTscreen.stroke(0, 0, 0); , size), 35); // Display new readings info = String(broadcast. Temperature); info.concat("C"); if(broadcast.Temperature > 0) info = "+"+info; info.toCharArray(Temperature, info.length()+1); // Change the color of the temperature value depending on the temperature itself int r, g = 0, b; if(broadcast.Temperature > 0) ( r = map(broadcast.Temperature, 0, 40, 255, 150); // Red b = map(broadcast.Temperature, 0, 40, 30, 0); // Change the hue for a more visual transition through zero ) else ( r = map(broadcast.Temperature, -40, 0, 0, 30); // Change the shade for a more visual transition through zero b = map(broadcast.Temperature, -40, 0, 150, 255); // Blue ) TFTscreen.stroke(b, g, r); // ATTENTION: the color positions in the library are mixed up, the RGB place is used by BGR! TFTscreen.text(Temperature, x_center(w, info.length()+1, size), 35); ) size = 1; // ==================================================== ==================================== // Output pressure readings // ========= ===================================================== ======================= if(broadcast.Pressure != Log_Pressure) ( TFTscreen.setTextSize(size); // Overwrite obsolete data info = String(Log_Pressure ); info.toCharArray(Pressure, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Pressure, x_alignment_right(w/2-5, info.length(), size), 80 ); // Display new readings info = String(broadcast.Pressure); info.toCharArray(Pressure, info.length()); TFTscreen.stroke(255, 255, 255); 2-5, info.length(), size), 80); changes(10, 106, 85, (broadcast.Pressure > Log_Pressure)?true:false); else ( changes(10, 106, 85, true, true); changes(10, 106, 85, false, true) // ============================ ===================================================== = // Output humidity readings // ========================================================== ========================================= if(broadcast.Humidity != Log_Humidity) ( TFTscreen.setTextSize(size); // Overwrite outdated data info = String(Log_Humidity); info.toCharArray(Humidity, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text(Humidity, x_alignment_right(w/2-5, info.length(), size), 100); // Display new readings info = String(broadcast.Humidity); info.toCharArray(Humidity, info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(Humidity, x_alignment_right(w/2-5, info.length(), size), 100); changes(10, 106, 105, (broadcast.Humidity > Log_Humidity)?true:false); ) else ( changes(10, 106, 105, true, true); changes(10, 106, 105, false, true); ) // ================== ===================================================== ============== // Display dew point/frost point readings // ============ ===================================================== ====== if(broadcast.dewPoint ! = Log_dewPoint) ( TFTscreen.setTextSize(size); // Overwrite obsolete data info = String(Log_dewPoint); info.toCharArray(dewPoint, info.length()); TFTscreen.stroke(0, 0, 0); TFTscreen.text (dewPoint, x_alignment_right(w/2-5, info.length(), size), 120); // Output new readings info = String(broadcast.dewPoint); info.toCharArray(dewPoint, info.length()); TFTscreen.stroke(255, 255, 255); TFTscreen.text(dewPoint, x_alignment_right(w/2-5, info.length(), size), 120); changes(10, 106, 125, (broadcast.dewPoint > Log_dewPoint)?true:false); ) else ( changes(10, 106, 125, true, true); changes(10, 106, 125, false, true); ) // Update the values ​​in the logs for subsequent comparison of readings Log_Temperature = broadcast.Temperature; Log_Pressure = broadcast.Pressure; Log_Humidity = broadcast.Humidity; Log_dewPoint = broadcast.dewPoint; )

The readings are displayed quite compactly, but as practice shows (and the advice of my comrades) - “taste and color, even the wife is not a friend.” I listened to a lot of advice and suggestions, but they contradict each other. Therefore, do it to your taste.

It seemed to me that design is the part of the project that takes up most of the time!

Hidden text

Some of the data is fabricated to reflect some design elements.

Artifacts on the display are dust and other dirt that has accumulated over the long time the display was in... somewhere there,... well, there, I don’t remember where I got it from! Leave me alone!

The sketch has positioning functions. They are quite primitive, but they allow you to achieve certain effects.

  1. x_center
  2. x_alignment_right

The first centers the text, and the second aligns it to the right side of the specified zone. All calculations are made relative to the size of the given text, based on the expression 1 size = 1PX x 1PX font segment.

The display also displays elements corresponding to an increase or decrease in a particular reading value. They are displayed in the form of triangles. But in the function code changes There is an alternative display in the form of triangles rotated by 45 degrees. If the readings increase, the element is red, otherwise, blue.

By the way, the color and shade of the main temperature changes depending on the temperature itself. Quite a controversial decision, but in my opinion, visually comfortable. I struggled with it for a while and realized that the values ​​in the function stroke, TFT display objects are listed in the wrong order. BGR place RGB. This is a developer error, or I don't understand something.

PS: Everything is quite interesting, but in my opinion it deserves further development. That’s what we’ll do after some time.

Introduction

Greetings everyone, today I want to tell you about a small subroutine or utility, depending on what is more convenient for you, called “Port Monitor”. If you are already familiar with the Arduino IDE, then you have come across it more than once and guessed what we will be talking about. But don't rush to leave, you will definitely have something to read as we go from the basics to full analysis her work.

And so, “Port Monitor” is a small Arduino IDE subroutine designed to receive and transmit data from-to Arduino. Due to the fact that the Arduino IDE does not have any means for debugging sketches, this is the only way to check whether everything is working correctly and as it should.

The subroutine consists of one form; when launched, the Arduino IDE transmits to it the number of the COM port with which it should work, after which it tries to connect to it and, if successful, begins to listen and display all the information received.

The Port Monitor form itself can be divided into three parts: upper, central And lower.

  1. At the top there is an input field in which the user can enter the data that he wants to send to Arduino. This can be either text or numbers (I’ll tell you more about the transmission format below). By pressing the “Send” button, as you may have guessed, the subroutine sends the entered data to the COM port and then to the Arduino.
  2. In the central part there is a text field in which all information received from the COM port is displayed, i.e. what was sent from Arduino.
  3. At the bottom of the form there are additional settings, namely:
  • “Autoscroll” - Convenient when you want to always see the latest information received from Arduino. The central part is automatically scrolled to the very bottom of the field.
  • “Postfix” - A drop-down list in which you can select one of the postfix options, i.e. when you click the “Submit” button at the top of the form, a few more bytes will be added to the data you entered in the field, which you can read below.
  • “Speed” - Drop-down list in which you need to select the baud rate.

In general, the form is not complicated, there are few elements on it, it is difficult to get confused. This is where we will finish the description and begin a detailed analysis.

Transferring data from Arduino to "Port Monitor"

We'll start with Arduino.

In order to transfer data from Arduino to the “Port Monitor”, you need to initialize the Serial class in the setup() function by calling its begin method, passing along the speed and settings of the COM port.

Syntax.

Serial.begin(speed, settings);

  • Where speed is the data transfer rate baud per second.
  • The settings (not a required parameter) indicate how many information bits are in a byte, as well as the number of stop bits and whether to add a parity bit. By default, if you do not pass settings (and we don’t need them in 99.9% of cases), the Serial class will take the standard settings, namely:
  1. The number of information bits in a byte is 8.
  2. The number of stop bits is 1.
  3. Parity bit - No parity bit.

What is a start bit, information bit, parity bit, why speed is measured in baud, I will tell you in another article, otherwise you can’t digest this large volume information, but the article will not be small, it will not be easy. Now we will use standard settings, where the speed is 9600 baud per second, and Arduino will select the settings automatically.

In total we got the following:

Void setup() ( // Initialize (start) the Serial class by calling its begin method indicating a speed of 9600 baud per second. Serial.begin(9600); )

After everything is ready, you can send data using the print and println methods of the same Serial class.

Void loop() ( // Send "Hellow World!" "); // Sleep for one second. delay(1000); )

Thus, in the port monitor we will see a line consisting of two “Hello World!” every second ( see photo above).

The Serial class contains other methods for working with the port monitor, but generally the print and println methods are sufficient for most cases.

Receiving data sent from the "Port Monitor" to Arduino

Now we will try to receive the commands sent from the port monitor to the Arduino and use them, for example, to turn an LED on or off.

The same Serial class and its method will help us with this readString.

And so on command " HIGH"we will turn on the LED, and at the command " LOW"We'll turn it off.

In order to send a command, you need to type text in the field located at the top of the form and click the “Submit” button. We will receive commands using the mentioned readString method.

In total, you should get the following.

Void setup() ( Serial.begin(9600); pinMode(13, OUTPUT); ) void loop() ( // Receive commands to turn on/off the LED on port 13. String str = Serial.readString(); // If command “HIGH” then turn on the LED. if (str == “HIGH”) digitalWrite(13, HIGH); // If the command is “LOW” then turn off the LED. ; // Sleep for 1 second. delay(1000);

This is how, without much pain, you can create Nth quantity commands and process them in Arduino.

Data transmission format

Finally, we will talk about the form in which information is exchanged between the “Port Monitor” and Arduino. No matter what data you pass from the Arduino to the port monitor, it is all converted to an ASCII format string ( see table), the same thing happens when sending data from the port monitor to Arduino. Those. By sending the number ten, you are not actually sending a number, but a string consisting of two characters, a one character and a zero character.

For example, sending one byte equal to 128, the port monitor will actually receive three bytes.

  • Byte 49 - ASCII unit character.
  • Byte 50 - Two symbol.
  • Byte 56 - Eight symbol.

When executing the println method, we will get 5 bytes. Where the first three will be described above, and the two additional ones are bytes CR (13) and LF (10), meaning a new line.

Having looked at the ASCII character table, many will notice that it contains only Latin characters, as a result of which if we send, for example, “Hello world!”, we will get some kind of gibberish in the port monitor. I would like to take this opportunity to advertise written by the authors of the portal, which understands not only inscriptions in Russian, but also in other languages.

And now, having read everything that I wrote here, I can finally tell you what “Postfix” is, the drop-down list at the bottom of the port monitor.

Postfix is ​​a byte or bytes, depending on which item you selected, that will be added to the data you entered in the sending field.

For example, by writing the number 128 in the send field and clicking on the “Send” button, we will receive the following:

  • In the postfix, “No end of line” is selected - The port monitor will send only what was entered in the send field, without adding anything.
  • In the postfix, “NL ( New line)" - The port monitor will send what was entered in the send field and add the LF (10) byte.
  • In postfix, "CR (Carriage Return)" is selected - The port monitor will send what was entered in the send field and add the CR (10) byte.
  • In postfix "NL&CR" is selected - The port monitor will send what was entered in the send field and add two bytes CR (13) and LF (10).

That's all. Write in the comments what you don’t understand, and in new articles we will try to describe it in more detail.

Well, the next article will be about how to write your own port monitor in Delphi.

Good luck to you.

Please enable javascript for comments to work.

Our organization has deployed a Zabbix server to monitor the performance of servers and workstations. Due to the peculiarities of the technical process, the equipment is “spread out” across several rooms and distributed throughout the enterprise. Naturally, along with the basic parameters of computers (works/doesn’t work), I also want to control the microclimate in the server rooms. At the same time, as usual, the possibilities are very limited, and it is impossible to “knock out” significant funds for complex systems Temperature monitoring (I include control boards with temperature sensors for APC rack UPSs) is a separate quest.

In the main server room, everything is simple - one such board is installed (purchased a long time ago by the predecessor along with the main equipment), an APC thermal sensor is plugged in, an agent is created in Zabbix, everything works via SNMP. Boring :) There is no equipment for monitoring remote hardware, nor funds - see above. Therefore, it was decided to be smart, save budget and at the same time develop a new skill by constructing a simple and cheap “knock-on” solution that nevertheless fits into the existing Zabbix monitoring infrastructure.

Required components:

  • The basis of the system is Arduino Nano V3
  • Local network module (ethernet-shield)
  • And, in fact, a digital temperature sensor based on DS18B20
The total cost of the components is $10 including delivery.

Assembling the device is not difficult. The network module is placed on the main board like a “sandwich”, the thermal sensor is soldered to its pins. Sensor connection: red +5 V, black - ground, yellow - data; Between +5V and Data we solder a 4.7 kOhm pull-up resistor.

The data pin is selected taking into account the pins used by the network module (D10 – SS; D11 – MOSI; D12 – MISO; D13 – SCK; D2 – IRQ).

Rake: in the prototype of the device I encountered a conflict - temperature data was issued randomly, “every two to three.” The reason turned out to be that I attached a temperature sensor to pin 2, which, as I later found on the Internet, is used by the network module to generate an interrupt when a packet arrives. I moved it to 4th - it worked like clockwork.

After assembling the hardware, we move on to the software.

The device will work on the network and pretend to be a Zabbix agent, for this it needs a MAC and IP address. We decide what is more convenient - hard-wire it during programming, generate a MAC from the address of the temperature sensor and obtain an IP via DHCP, etc. I took the simplest route and hardcoded both parameters.

The exchange protocol with the Zabbix server is described in the documentation. Our device will respond to two commands - agent.ping And env.temp(there is room for further creativity here; you can attach any of the expansion modules available for Arduino - even a humidity sensor, even a light sensor - whatever your heart desires). It will respond to all other commands with a standard response that is understandable to the Zabbix server.

For those who are starting from scratch (like me), Arduino programming is done using the Arduino IDE, the installation and configuration of which is simple. For the components to work, the UIPEthernet and OneWire libraries are required, which are installed and connected to the project through the Sketch menu - Connect library - Manage libraries...
If you have other components (for example, a network module not on the enc28j60, but on a different chip), you will need other libraries!

The code for working with the network module and temperature sensor is typical, from the Internet, with some assumptions and simplifications.

After uploading the code to the controller and connecting the ethernet cable, we check from the console:

$ zabbix_get -s 192.168.4.5 -k agent.ping 1 $ zabbix_get -s 192.168.4.5 -k env.temp 23.12 $ zabbix_get -s 192.168.4.5 -k bla-blah ZBX_NOTSUPPORTED
Rake: the compiled version of zabbix_get for Windows posted on zabbix.com is outdated and uses a different protocol (with the ZBXD\x01 header in the server request). The Linux version is up to date and the protocol corresponds to the given code.

Everything works as intended. In the Zabbix admin panel, we create a new host with the selected IP, it contains two keys, Numeric (unsigned) agent.ping and Numeric (float) env.temp, and enjoy the work. Charts, triggers - everything is as usual.

The device is powered via native USB. Case - optional: suitable plastic box, heat shrink, blue electrical tape.

The resolution of the sensor is approximately 0.06 (more precisely, 1/16) °C, the accuracy - when immersed in melting snow, it showed 0.19 °C (maybe it would have dropped lower, but there was little snow and it all melted quickly). I think it’s more than enough for a device that costs $10 and the purposes described.

Sketch

#include #include byte mac = ( 0xDE, 0x05, 0xB6, 0x27, 0x39, 0x19 ); // random MAC byte ip = ( 192, 168, 4, 5 ); // IP address in local network String readString = String(20); byte addr; OneWire ds(4); // DS18B20 at pin 4 EthernetServer server(10050); // Zabbix port void setup() ( Ethernet.begin(mac, ip); server.begin(); ds.search(addr); ) void loop() ( byte data; float celsius; readString = ""; if ( EthernetClient client = server.available()) ( while (client.connected()) ( if (client.available()) ( char c = client.read(); if (c == "\n") // end of query from zabbix server ( client.print("ZBXD\x01"); // response header if (readString == "agent.ping") ( byte responseBytes = (0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 , 0x00, "1"); client.write(responseBytes, 9); else if (readString == "env.temp") ( ds.reset(); ds.select(addr); ds.write(0x44) ; // start conversion with regular (non-parasite!) power delay(1000); ds.select(ds.write(0xBE); // read Scratchpad data = ds.read(); ; data = ds.read(); int16_t raw = (data<< 8) | data; celsius = (float)raw / 16.0; byte responseBytes = {(byte) String(celsius).length(), 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; client.write(responseBytes, 8); client.print(celsius); } else { byte responseBytes = {0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; client.write(responseBytes, 8); client.print("ZBX_NOTSUPPORTED"); } break; } else if (readString.length() < 20) { readString = readString + c; } } } delay(10); client.stop(); } }

When I learned about public monitoring, about the opportunity to be part of this weather monitoring system, I was overcome with excitement, and a simple weather station was made on an Arduino nano and an ethernet module.
She transmitted temperature, pressure and humidity to the site. It worked poorly, sometimes it froze, it was necessary to reboot. Then the humidity sensor died, and I started looking for an alternative device. I looked at esp8266 for a long time, but knew very little about it. What stopped me was that the code for it had to be written in an unfamiliar esplorer environment in a language unfamiliar to me. A similar device has already been published here, the device worked with shareware firmware from Homes Smart, this solution did not suit me. Later I found out that esp8266 can be quite successfully connected to arduinoIDE. I started googling intensively, and as a result I got results that suited me.
I hope the article will be useful. I think it can be regarded as a review-guide for assembly.

NodeMcu is a kind of development board for esp8266 (in my understanding). Using it, it is convenient to make prototypes of devices on breadboards. It is convenient to upload the firmware from ArduinoIDE, everything happens automatically. Naturally, you need ArduinoIDE to work with esp8266. Having prepared the working environment, I immediately sketched out a diagram, it was not difficult.
The bmp180 pressure and temperature sensor is connected via i2c to SCL(gpio05) and SDA(gpio04).
Humidity and temperature sensor dht22 connected to gpio02
The 1602 display with a soldered i2c adapter is also mounted on scl and cda, in parallel with the pressure sensor.
Power supply for sensors is 3.3V, power supply for display is 5V.

A photoresistor is connected to pin A0; it controls the brightness of the display so that the display does not glow too brightly at night. The backlight is powered by gpio14, which implements software PWM. After the transistor cascade, the backlight power goes directly to spot A (anode) on the display. it is located next to the LED. From the spi display adapter you need to remove the jumper that controls the backlight.

Photo of the prototype





I will attach the diagram and seal at the end.

It was more difficult with the code.

//arduino 181, or buried #include #include #include #include #include LiquidCrystal_I2C lcd(0x27, 16, 2); #include #include #include #include #define debug true // output debug messages #define postingInterval 300000 // interval between sending data in milliseconds (5 minutes) #define DHTPIN 2 // dht on gpio02 // Uncomment the type of sensor in use: //#define DHTTYPE DHT11 // DHT 11 #define DHTTYPE DHT22 // DHT 22 (AM2302) //#define DHTTYPE DHT21 // DHT 21 (AM2301) // Lib instantiate DHT dht(DHTPIN, DHTTYPE); Adafruit_BMP085 bmp; /**/unsigned long lastConnectionTime = 0; // time of last data transfer /**/String Hostname; //name of the piece of hardware - looks like ESPAABBCCDDEEFF i.e. ESP+mac address. float dhttemp; // buffer variable for storing temperature from dht22 int dhthum; // buffer variable for storing humidity from dht22 int topwm; // stores the value for the display brightness shim void wifimanstart() ( // Magic procedure for the initial connection to Wifi. // If you don’t know what to connect to, creates an ESP8266 access point and a configuration table http://192.168.4.1 // More details: https ://github.com/tzapu/WiFiManager WiFiManager wifiManager; wifiManager.setDebugOutput(debug); wifiManager.setMinimumSignalQuality(); if (!wifiManager.autoConnect("ESP8266")) ( if (debug) Serial.println("failed to connect and hit timeout"); delay(3000); //reset and try again, or maybe put it to deep sleep ESP.reset(); delay(5000); ) if (debug) Serial.println("connected.. ."); ) void setup() ( // pinMode(14, OUTPUT); // gpio14 will tweak the display backlight Hostname = "ESP"+WiFi.macAddress(); Hostname.replace(":",""); Serial.begin(115200); // initializing the screen lcd.begin(4, 5); // sda=gpio04, scl=gpio05 lcd.backlight(); // initializing the temperature and pressure sensor bmp180 dht.begin(); (!bmp.begin()) // if the sensor is not found, we report this to the comport and to the display ( Serial.println("Could not find BMP180 or BMP085 sensor at 0x77"); lcd.clear(); lcd.print("BMP180 FAILED"); while (1) () ) WiFi.hostname(Hostname); wifimanstart(); Serial.println(WiFi.localIP()); Serial.println(WiFi.macAddress()); Serial.print("Narodmon ID: "); Serial.println(Hostname); // issue the poppy and IP address of the hardware to the comport, and also display it on the display lcd.clear(); lcd.setCursor(0, 0); lcd.print(WiFi.localIP()); lcd.setCursor(0, 1); lcd.print(Hostname); lastConnectionTime = millis() - postingInterval + 15000; //first transmission to public monitoring in 15 seconds. ) void WriteLcdTemp (void)( // filling the display. Occurs every 5 minutes after receiving data from the sensors lcd.clear(); lcd.setCursor(1, 0); lcd.print("T1 "); lcd.setCursor(4 , 0); lcd.print(bmp.readTemperature()); lcd.set(8,0); lcd.print(" P "); )/133. 3); lcd.setCursor(1, 1); lcd.print("T2 "); lcd.setCursor(4, 1); lcd.print(dhttemp); lcd.setCursor(8,1); lcd.print("H"); lcd.setCursor(11,1); lcd.print(dhthum); lcd.setCursor(13,1); lcd.print("%"); ) bool SendToNarodmon() ( // The actual formation of the packet and sending. WiFiClient client; String buf; buf = "#" + Hostname + "#ESP_YOBA" + "\r\n"; // title AND NAME that will be displayed in popular monitoring, so as not to burn the poppy address dhttemp=dht.readTemperature(); // save data from dht22 into buffer variables so that it is convenient to operate dhthum=dht.readHumidity(); buf = buf + "#T1#" + String( bmp.readTemperature()) + "\r\n"; //temperature bmp180 buf = buf + "#T2#" + String(dhttemp) + "\r\n"; //temperature dht22 buf = buf + "# H1#" + String(dhthum) + "\r\n"; //humidity buf = buf + "#P1#" + String(bmp.readPressure()) + "\r\n"; //pressure buf = buf + "##\r\n"; // close the package if (!client.connect("narodmon.ru", 8283)) ( // attempt to connect Serial.println("connection failed"); lcd.clear( ); lcd.print("connect failed"); return false; // failed) else ( WriteLcdTemp(); client.print(buf); // and send the data if (debug) Serial.print(buf); while (client.available()) ( String line = client.readStringUntil("\r"); // if there is something in response - everything is in Serial Serial.print(line); ) ) return true; // gone ) void loop() ( //auto brightness topwm=map(analogRead(A0), 0, 1023, 10, 950); analogWrite(14, topwm); delay(100);// needed, bez dividing me did not connect to Wi-Fi if (millis() - lastConnectionTime > postingInterval) (// wait 5 minutes and send if (WiFi.status() == WL_CONNECTED) ( // well, of course, if connected if (SendToNarodmon()) ( lastConnectionTime = millis (); )else( lastConnectionTime = millis() - postingInterval + 15000; )//next attempt in 15 seconds )else( lastConnectionTime = millis() - postingInterval + 15000; Serial.println("Not connected to WiFi"); lcd .clear(); lcd.print("No WiFi");) // next attempt in 15 seconds ) yield(); // what kind of command - who knows, but ESP works stably with it and does not glitch)

What can the device do?
The device measures temperature, pressure (sensor bmp180) and humidity (sensor dht22), displays the readings on the display, and sends them to the public monitoring site.
When you turn it on for the first time after the firmware, or in the absence of friends wifi networks the device pretends to be an access point open type named ESP8266.

IN com port the device sends this:

You need to connect from your phone, laptop or tablet to a point named ESP8266, and go to 192.168.4.1
The following page will open:


Click the Configure Wifi button and you will be taken to this page


Next, select your network, enter the password, and click Save. Done, the device reboots itself and starts working. First, the IP address and mac address of the device with the ESP prefix are displayed on the display and in the com port, it must be used as a sensor ID when registering on the public monitoring site, and after 15 seconds the first ones are displayed on the display, in the com port, and on the public monitoring site readings from sensors.
T1 - temperature with bmp180
T2 - temperature with dht22
P- Atmosphere pressure. Displayed in mm. Hg Art., for public monitoring it goes in I don’t remember what units, it is converted into mm. Hg Art. automatically.
H - humidity in percent.


Lines T2 and H are heresy, because the dht22 sensor is not connected

The design worked in this form for a couple of weeks while I slowly thought through finished device.
I decided to assemble the finished device on a module (the same one is installed on nodemcu)
I quickly separated and etched the board.




There was no need to change the code at all. The port numbers for the sensors are the same, you just need to connect the bare esp8266 standard scheme, so that it can work and the firmware can be uploaded. I got 3.3 volts using an ams 1117 3.3v stabilizer.
The device is powered by a 5V telephone charger. 2A. But I think one ampere will be enough.


For firmware I installed a separate 3-pin connector with RX, TX and GND contacts.

I flashed the finished device using usb adapter-uart. The advantage of it is that it has a 5v-3.3v switch, although knowledgeable guys say that this switch only works for power, and the rx and tx levels do not change. But everything worked for me without level conversion, probably because the esp8266 is tolerant of 5v on the rx tx, although it works from 3.3.
Also on the finished board there was a switch for entering the firmware mode (red slider, lower slider for entering the firmware mode. I connected the upper slider to gpio12, just in case, perhaps to switch display modes in the future, but for now it is not used. You don’t have to be smart and just put a jumper between gpio0 and GND)

To flash the firmware you need to connect the usb-uart converter this way:
esp rx - uart tx
esp tx - uart rx
esp gnd - uart gnd

Then connect gpio0 to ground using the lower slider on the switch, press the “Reset” button on the board (located at the top), in arduinoIDE select the desired com port, download speed (115200 for most esp8266 boards), and click the “Download” button.
After the download is complete, the device will start working, the firmware switch must be returned to the OFF position, otherwise the next time you reboot or turn off the power, the device will again enter firmware mode.

Let's remember the dead dht22 sensor. Symptoms - constantly shows humidity 99.9, in dry weather it may show less. It died in the fall of 2016, having worked properly all spring and summer. There was a week of constant rain, and I received a letter from people’s monitoring by email saying that your sensor was showing the same thing for several days in a row. I did not change the sensor, but simply hid it from public access until recently.
I think the cramped housing is a possible reason for the death. An egg from Kindersurprise was used as its base. A new, more technologically advanced and spacious housing was developed from a socket box and a plug sewer pipe. Here are both buildings side by side:


I didn’t modify the sensor board, I simply replaced the dead dht22 with a live one, covered it with tsapon varnish and secured it with thermal nozzles in the upper part of the outdoor housing.
This is what the sensor board diagram looks like. You can even draw with a marker

diagram and appearance




I attached the sensors to the window and led the cable into the room. The takeaway could have been done more, and from external unit remove the air conditioner, but this is problematic.

Stuffed his guts into a mega-technological case made of distribution box for wiring. I didn’t bother with fastening, I used thermal nozzles.

Assembled

Humidity test passed successfully. The sensor is alive.

It was useful experience for me, I finally got my hands on the esp8266 and got a stably working device that was useful to me.
I hope this article is useful to someone. If you have any difficulties or questions, write in a personal message, I will answer.

Planning to buy +121 Add to favorites I liked the review +108 +214