Experience of using LCD displays based on MELT products
This article is devoted to an exciting adventure quest that I had to go through in the process of creating an updated external sensor for the weather station described here in this article a year and a half ago. According to the operating experience of the previous version, I really wanted to create a sensor with a control display, so that it was possible to periodically check (and verify) the most whimsical component of the station without problems - the wind speed sensor. Adventures began when I began to select a display for this purpose and for a number of reasons, which I further dwelt on the products of my own MELT. But before I go to the description of the techniques of unconventional sex ways to cope with my chosen works of this company, it is worthwhile to briefly highlight the main reason for all this grand modernization, which I started.
In the comments to that article, I was rightly pointed out with regard to the design of the sensors that the axis of such a device should have a solid edge and rest on an equally solid foundation (recall the wristwatch “on so many stones”). I knew this, of course, but then I couldn’t think of a way to ensure a light axis with a tip of sufficient hardness, so, on the contrary, I chose to minimize friction, plunging a brass (for a wind vane) or dural (for a speed sensor) edge into a soft fluoroplastic (see . Drawings in this article). In the full understanding that this decision is temporary and short-lived and in the near future it is necessary to invent something more substantive.
The result of the past two seasons of operation has shown nevertheless that such a solution is quite suitable for a weather vane, which, of course, cut the fluoroplastic base to the metal with a brass axis, but this did not damage it at all - the minimum friction there is not required, even in part. It was worse with a speed sensor, in which not only the fluoroplastic at the base was sawn, but the very edge of a soft duralumin was worn out two millimeters in length. As a result, first of all, the start-off threshold was unacceptably increased, and the sensor had to be upgraded. The anemometer itself has undergone modernization, as the laser compact disc, on the basis of which it was made, exfoliated from the sun and acquired an untidy appearance (I shouldn’t have known before that the compact discs consist of two layers).
I hope to tell you more about the new sensor later, after it has been in operation for a while and you can be sure that you don’t have to modify it right away (that is, not earlier than the beginning of summer). And now only some details about the changes in the measuring scheme, as they relate to the main topic of this article.
In connection with the lowering of the breakaway threshold, the question arose of the considerable time that the measurement of low frequencies takes from the speed sensor (for details, see this publication on methods for measuring low frequencies). In order not to limit the breaking point artificially, in this case it would be necessary to measure frequencies ranging from 1-2 hertz: given that the sensor has 16 holes around the circumference (see the photo of the sensor in the original article), this corresponds to approximately one turn in 8–16 seconds, which is obviously lower than any threshold of moving off. That is, the timeout for the arrival of the next frequency pulse must be at least 1 s (see the specified article on measurement methods), which makes the history of energy saving meaningless: in order to get an acceptable update time and at the same time have time to average the data in order to avoid bounce readings on the display, we have to wake up the controller every two seconds. And if half of them will take the time to wait for the pulses, then no energy saving will be possible - considering also that the emitting diode of the sensor has been working all this time, consuming about 20 mA.
You can spoil the complex control of the controller wake-up from two sources: normally from an external interruption from the speed sensor (that is, while waiting for pulses from the sensor, the controller also goes into power saving mode), and in the absence of wind - forced from Watchdog. This would make sense only if the principle of reading the speed sensor from optical to less energy-intensive circuits (which still need to be searched - the Hall sensor, for example, consumes 5-10 mA, which is fundamentally less than the optical structure) changes. But everything was simplified due to the fact that my sensor is now powered by a solar battery, which made it possible to simply abandon the energy-saving mode.
To clock the readings, I did not bother with timers or count down Arduin millis (), but simply put a primitive external frequency generator with a period of about 1.5 seconds on the 555 timer:
As we recall, the Atmega328 “dumb” DIP controller is used in the sensor circuit -korpus, programmed through Uno and installed on the panel, the Arduino itself is used only for prototyping. The output of the generator was brought to the output of the interrupt INT0, output 4 of the chip (output D2 of the Uno board). Interruption by a positive differential (RISING) sets a certain flag, according to which the next readings are taken in the main cycle. The frequency from the sensor is also measured by the interruption method (the output of the sensor is inputted to the interrupt input INT1, pin 4 (D3), see the last method in that very article), because the maximum total waiting time is twice the period of the measured frequency. With a timeout of 1 s, thus, the minimum measured frequency is 2 Hz (one turn of the anemometer in 8 seconds). In every fourth cycle, averaging occurs and the finished data is sent to the main module, that is, the readings are updated approximately every 6 seconds.
The whole story with the updated sensor will have to be calibrated and periodically checked to see if the friction has increased, comparing readings with a manual anemometer. It is therefore very inconvenient when the readings are displayed in one place (in the house), and the external sensor is installed in a completely different position - on the garden gazebo. There was a question about installing a control LCD display in the sensor housing. Since the beauty here is not required, the information requirements for it are minimal: a single-line 10-character display is enough. But the geometric requirements are quite stringent: the display must fit into the existing case in width, which is 70 mm. I must say that because of my organic dislike for LCD displays (dull, low-contrast, with small letters, disgusting quality backlight, and also consume a lot, more on that later), I almost do not know the range available in retail. And so it immediately became clear that I needed to look for the displays I needed very much: a standard 16x2 LCD display, which dominate in stores, has a 80 mm board and doesn’t fit in my sensor, and all other types are even larger, and from the firm. In nature, of course, there are varieties of smaller sizes, but then in nature, and not in domestic retail.
In the end, I found two MELTs at once, which wonderfully fit my task. The first of these is a single-line 10-character MT-10S1 with a controller, which, as the manufacturers claim, is “ similar to HD44780 by HITACHI and KS0066 by SAMSUNG". It has rather large signs: more than 8 mm in height, which is generally characteristic of Chinese displays, which are much larger. The width of the board is 66 mm, the dimensions of the protruding screen (external) are 62x19.5. The consumption in this case worries me not very much (for the external sensor is powered by a solar battery of obviously more power than necessary), but out of habit, looking at the line in the datasheet, I found out that it is also less than usual - 0.7 mA (all normal LCD -displays on analogs HD44780 consume from 1.2 mA and above). There is still a highlight up to the heap, as usual for all such types - rather miserable and at the same time consuming a lot of energy.
The second display MT-10T7 is even more delightful: exactly 10 seven-segment digits 13 mm high fit exactly in the same dimensions. Some suspicions were caused by non-standard, and, apparently, self-made interface (for which the datasheet even gives an example of programming in the verbal pseudocode). The display does not contain a real controller: there is a set of static triggers-latches, controlled by combinational logic. But thanks to such simplicity, this whole design consumes only 30 µA, that is, it really suits devices that work on battery power around the clock (the consumption of 1.4 mA for conventional displays and even 0.7 mA for MT-10S1 greatly exceed the permissible for such use of the value - calculate for yourself how long such a display will work, even without taking into account the other components of the device, for example, from AAA batteries with a capacity of about 1500 mAh.
In short, give two!
An attempt to independently reproduce the algorithm for MT-10T7, described in the datasheet (on both the Arduino and in pure assembler), did not lead to success. I did not understand what was done wrong, because I came across this publication , where the author (eshkinkot) gave a very well-written and thoroughly executed example of handling MT-10T7, after which everything worked right away. If anyone is interested, then here is a modified example of eshkinkot, supplemented by all meaningful symbols on the seven-indicator indicators, including letters that do not coincide with the numbers:
In these pictures, the contrast of the screen is slightly trimmed by setting the divider to output Vo - 18 kΩ (to nutrition): 10 kOhm (to the ground), although without it the contrast “by default” is quite acceptable.
I then added a function to the given example that reproduces an arbitrary number within three to four decimal places - positive or negative, integer or floating point, that is, the total number of characters can reach five: “-12.7”, for example. Since the dot in the seven-segment code does not occupy a separate familiarity, the maximum number of output digits is 4. Input parameters for this function are: a) an array (char buf [5]) containing the ACSII representation of the number, b) the actual number of characters in it (ii from 1 to 5) and c) the position (pos from 0 to 9) where to put the first (left) sign of the number (used along the way functions and designations, see the eshkinkot publication or in the example by reference):
The MT-10T7 module for the control output of numeric values is more convenient than ordinary line-matrix displays: it has large numbers and the decimal point does not occupy a separate place and, therefore, it is possible to fit one more character in the same positions. But for my purposes it is more convenient if there is a possibility of outputting letters (otherwise, the direction will have to be output in compass degrees, which is somewhat unusual). Therefore, for this case, I turned my attention to the identical-size single-line matrix MT-10S1, which, despite a number of shortcomings, moved into the finished structure. At the same time he already has a backlight, which MT-10T7 is deprived of (for this it was necessary to immediately buy MT-10T8), and I decided that in this case its presence would not hurt.
The display MT-10S1 letters-tsifirki and a half times smaller, but also quite decent size. In addition, its screen is economically packaged in general dimensions: there are no 10-digit imported counterparts, but in Vinstar WH1601L (where the characters are even slightly smaller in height) there is one millimeter more of the total length of the board and screen. Well, almost twice the consumption of the controller (compared to the same WH1601L). Actually, this is where the advantages end, then “features” begin.
The module boasts that, as already mentioned, has a controller that is compatible with HITACHI HD44780. That is, it should work without any straining with your favorite Liquid Crystal. Moreover, the “default” page of the coding coincides with the English-Cyrillic page of the HD44780 and its numerous analogues, that is, the MT-10S1 should work without problems with Liquid Crystal Rus, no code pages are required for this to switch. And he really does it all, but with nuances.
The first caveat - in the single-line version, the developers, apparently, save on registers, and only 8 characters of a string (addresses 00h - 07h) fall into one register, and the remaining two characters belong to another register (40h-41h). That is, the display is de facto two-line, just the two lines are physically located in one line. Upon closer inspection, it turned out that the same is true for the WH1601 (only there the second register occupies the full eight bits). Why it is so inconveniently done is completely unclear, in regular 16x2 displays the registers are sixteen-bit, and hardly such truncation reduces the price of the product, rather the opposite because of the need to produce different versions of the controller (if they are different, which I am not at all sure about). I thought it was connected with this less than usual, the consumption of MT-10S1, but the same WH1601 consumes 1.2-1.4 mA,
Well, it would seem, and it is fine - in Liquid Crystal Rus the function setDRAMModel () and the corresponding constant LCD_DRAM_WH1601 were revealed. For such a regime, an obvious address translation is written in the library:
But I don’t know how it works on other one-line displays, and MT-10S1 in this mode refuses to work at all - the screen remains just empty. Since it’s about addressing, you can’t fix it with a simple self-written function on top of the library, but I didn’t pick the library and find out what was happening - I already have half a dozen Liquid Crystal versions that I’ve already corrected; Further.
Display MT-10S1 must be declared as two-line: lcd.begin (16, 2); (instead of 16, you can substitute 10 or 12, nothing will change, since the real number of characters in one line is still 8). Attempting to initialize it as a single-line one (tsifirka 1 in the second position) will lead to a failure — the background will turn dark. And it is possible to output multi-digit numbers only within 8 characters, for longer lines, extreme characters over 8 will simply disappear. Therefore, the 9 and 10 characters either actually are suitable only for displaying auxiliary quantities (units of measurement, for example), or you need to split the string-number into separate digits, and when switching to the 8th character, change the cursor position to the first character of the second row.
For the afflicted hereYou can download a test sketch for this display (connecting leads is in the text of the sketch or in the diagram below). By the way, the contrast (which is not a word in the factory datasheet, and the output Vo is designated as NC) is adjusted in the usual way, but this is not really necessary: in the absence of illumination, the background seems somewhat darkish, but when you try to lighten it by connecting the divider to Vo output the contrast is noticeably lost when the backlight is turned on.
After checking that everything works as it should, the question of how to dock it all with the controller of the sensor rose to its full height. To provide control from it directly, the sensor controller didn’t have enough free outputs, and there was no wish to fence the township with large controllers - it’s more convenient when building the system is modular, and the display doesn’t interfere with the basic algorithm already debugged before. It remained to use any of the serial interfaces.
This suggests I 2The C-solution is based on PCF8574 (or its numerous analogs), especially since this chip itself is just a fancy shift register, and therefore consumes several tens of μA during operation and less than 10 μA at rest. In conjunction with the MT-10T7, they form an excellent pair for creating low-power devices with indication, and MELT even has a ready-made version for this: MT-10T11 with a total consumption of 30 μA.
But for the MT-10S1 there is no such convenient solution - for some reason, additions in the form of PCF8574 analog among MELT line displays are provided only with versions of 20x4 configuration ( UPD: in the comments it was suggested that there is still MT-16S2H configuration 16x2 with the same interface, however , his dimensions go beyond the dimensions I need). Ready module of the type describedin this article , in this case, it is inconvenient to use, since the second unpleasant feature of the MT-10S1 display is non-standard wiring. The conclusions are all the same (HD44780 after all, more precisely, its domestic analogue KB1013VG6), but are arranged completely in an irregular way. I checked for the sake of interest both imported 16x1, and MELT'ovskie two-line / four-line - they all have a standard order of conclusions, and MT-10S1 for some reason stands out against this background. So it is necessary to fence the self-made decision.
As a result, I simply put the same ATmega328 controller on the display, which was programmed in the same way — via UNO, and then inserted into the socket on a separate board, equipped only with the necessary accessories for the launch: quartz with conder, power capacity and RC circuit Reset (see sensor circuitin the original article , where the controller is connected in a similar way).
And two identical AVR-controllers God himself ordered to dock using the usual Serial-interface, which all the same, except the programming process, is not used anywhere else in this project, and for the use of which everything is already at hand. By the way, such a solution does not differ from the price of components based on PCF8574 and can easily compete with it in terms of energy saving in the version with MT-10T7 - in case the MT-10T11 mentioned above is not at hand.
Total scheme of the module MT-10S1 with the controller is as follows (in the diagram the designation of the conclusions of the ATmega328 is given in brackets after the conclusions of the Arduino board):
In the controller, I applied the power saving mode (well, yes, it is not very necessary here, but why keep the chip on all the way without need?). Moreover, the awakening occurs on a signal from the same generator of the meander on the 555 chip, as the clocking of the main controller, only this time along the falling front (FALLING), in order to slightly separate the functions of measuring and sending data.
Data transfer from the sensor controller to the display controller via UART is organized in the form of a dialogue. When waking up, every 4th interrupt the display controller requests data in turn:
Here, buft, bufhh, bufss and bufd are arrays (not strings!) Of five bytes, which contain data on temperature, humidity, speed and direction in the form of an ASCII decomposition of the corresponding numbers. In order not to take too much, an abbreviated timeout for reception is specified in setup'e:
It is more convenient to display: first, you immediately have the length of the received number, secondly, the Serial.print () function from the sensor controller side still sends an ASCII string, with the pauses set at exactly the same 10 ms between the packages :
The calculation of speed in m / s here is identical to that which is performed in the main module of the station (the start-off threshold is set at random to 0.3 m / s) and will also have to be changed based on the calibration results.
If you try to accept data with the usual Serial.read () and then display the result of the reception with a function like lcd.print (t, 1), where t is the temperature in degrees, for example, 12.7, then MT-10S1 responds to such the command will output "49.5". Guess or suggest? These are the first three characters in the sequence "49 50 46 55", that is, in the ASCII decomposition of the number "12.7". Therefore, it is easier to immediately receive an array of characters and directly display as many characters as were sent (count is the counter that is incremented by each interrupt):
The last line needs decoding. The point is that the direction data is sent in code 0-15 (to which they are still transferred from the Gray code when implementing vector averaging ). In the case of the seven-segment display MT-10T7, they were converted to compass degrees:
And here we can write directly in Russian letters, as well as in the main module of the weather station (which is why this display was actually chosen):
The photo shows the appearance of the display with the connected controller in working condition:
This is how the module of the modified sensor looks like:
The backlight parameters are those shown in the diagram above. Since the voltage drop on the backlight in the MELT modules is 4.5 V, then at 12 V power supply, the backlight current is 50 mA (at the maximum for this module 60 mA).
The case is maximally sealed to avoid ingress of moist air inside (the black frame of the display screen is made of rubber sheath of a thin cable). The white plate on the right is the enclosure of the SHT-75 humidity-temperature sensor, which is outside the enclosure (the sensor itself is located behind it). The yellow wire above is a 433 MHz transmitter antenna. On the left are the connectors where the speed and direction sensors are connected.
And this is what the readings on the display of the main module of the weather station look like (the black module with the white antenna on the right is a 433 MHz receiver):
In the comments to that article, I was rightly pointed out with regard to the design of the sensors that the axis of such a device should have a solid edge and rest on an equally solid foundation (recall the wristwatch “on so many stones”). I knew this, of course, but then I couldn’t think of a way to ensure a light axis with a tip of sufficient hardness, so, on the contrary, I chose to minimize friction, plunging a brass (for a wind vane) or dural (for a speed sensor) edge into a soft fluoroplastic (see . Drawings in this article). In the full understanding that this decision is temporary and short-lived and in the near future it is necessary to invent something more substantive.
The result of the past two seasons of operation has shown nevertheless that such a solution is quite suitable for a weather vane, which, of course, cut the fluoroplastic base to the metal with a brass axis, but this did not damage it at all - the minimum friction there is not required, even in part. It was worse with a speed sensor, in which not only the fluoroplastic at the base was sawn, but the very edge of a soft duralumin was worn out two millimeters in length. As a result, first of all, the start-off threshold was unacceptably increased, and the sensor had to be upgraded. The anemometer itself has undergone modernization, as the laser compact disc, on the basis of which it was made, exfoliated from the sun and acquired an untidy appearance (I shouldn’t have known before that the compact discs consist of two layers).
I hope to tell you more about the new sensor later, after it has been in operation for a while and you can be sure that you don’t have to modify it right away (that is, not earlier than the beginning of summer). And now only some details about the changes in the measuring scheme, as they relate to the main topic of this article.
About sensor measuring circuit
In connection with the lowering of the breakaway threshold, the question arose of the considerable time that the measurement of low frequencies takes from the speed sensor (for details, see this publication on methods for measuring low frequencies). In order not to limit the breaking point artificially, in this case it would be necessary to measure frequencies ranging from 1-2 hertz: given that the sensor has 16 holes around the circumference (see the photo of the sensor in the original article), this corresponds to approximately one turn in 8–16 seconds, which is obviously lower than any threshold of moving off. That is, the timeout for the arrival of the next frequency pulse must be at least 1 s (see the specified article on measurement methods), which makes the history of energy saving meaningless: in order to get an acceptable update time and at the same time have time to average the data in order to avoid bounce readings on the display, we have to wake up the controller every two seconds. And if half of them will take the time to wait for the pulses, then no energy saving will be possible - considering also that the emitting diode of the sensor has been working all this time, consuming about 20 mA.
Some details in brackets
Замечу в скобках, что в связи с этой проблемой я сразу вспомнил измеритель течений, который был сконструирован в нашем ОКБ в начале восьмидесятых, еще до появления всяческих контроллеров. В нем было реализовано истинное векторное осреднение: а именно запись всех показаний тактировалась самим сигналом с вертушки датчика скорости — примерный аналог побудки по внешнему прерыванию. Иными словами, если течения никакого нет, то никакой записи и не производилось, и схема ничего не потребляла — работали только часы реального времени. Порог трогания той вертушки, выполненной в виде импеллера с нулевой плавучестью, составлял, правду сказать, 2-3 см/сек, а направление измеритель указывал, поворачиваясь всем корпусом. Дык то в воде, которая в 700 раз плотнее воздуха! За время осреднения, которое там составляло часы, такая вертушка хоть разок, да провернется, потому пустых измерений там почти не было. А для метеостанции, как уже говорилось, математически корректный метод осреднения не подходит, так как она и при отсутствии ветра должна что-то реальное показывать. Следовательно, тут мы не можем обойтись без искусственно ограниченного таймаута на ожидание импульсов с датчика.
You can spoil the complex control of the controller wake-up from two sources: normally from an external interruption from the speed sensor (that is, while waiting for pulses from the sensor, the controller also goes into power saving mode), and in the absence of wind - forced from Watchdog. This would make sense only if the principle of reading the speed sensor from optical to less energy-intensive circuits (which still need to be searched - the Hall sensor, for example, consumes 5-10 mA, which is fundamentally less than the optical structure) changes. But everything was simplified due to the fact that my sensor is now powered by a solar battery, which made it possible to simply abandon the energy-saving mode.
To clock the readings, I did not bother with timers or count down Arduin millis (), but simply put a primitive external frequency generator with a period of about 1.5 seconds on the 555 timer:
As we recall, the Atmega328 “dumb” DIP controller is used in the sensor circuit -korpus, programmed through Uno and installed on the panel, the Arduino itself is used only for prototyping. The output of the generator was brought to the output of the interrupt INT0, output 4 of the chip (output D2 of the Uno board). Interruption by a positive differential (RISING) sets a certain flag, according to which the next readings are taken in the main cycle. The frequency from the sensor is also measured by the interruption method (the output of the sensor is inputted to the interrupt input INT1, pin 4 (D3), see the last method in that very article), because the maximum total waiting time is twice the period of the measured frequency. With a timeout of 1 s, thus, the minimum measured frequency is 2 Hz (one turn of the anemometer in 8 seconds). In every fourth cycle, averaging occurs and the finished data is sent to the main module, that is, the readings are updated approximately every 6 seconds.
The whole story with the updated sensor will have to be calibrated and periodically checked to see if the friction has increased, comparing readings with a manual anemometer. It is therefore very inconvenient when the readings are displayed in one place (in the house), and the external sensor is installed in a completely different position - on the garden gazebo. There was a question about installing a control LCD display in the sensor housing. Since the beauty here is not required, the information requirements for it are minimal: a single-line 10-character display is enough. But the geometric requirements are quite stringent: the display must fit into the existing case in width, which is 70 mm. I must say that because of my organic dislike for LCD displays (dull, low-contrast, with small letters, disgusting quality backlight, and also consume a lot, more on that later), I almost do not know the range available in retail. And so it immediately became clear that I needed to look for the displays I needed very much: a standard 16x2 LCD display, which dominate in stores, has a 80 mm board and doesn’t fit in my sensor, and all other types are even larger, and from the firm. In nature, of course, there are varieties of smaller sizes, but then in nature, and not in domestic retail.
Solution: oh, MELT!
In the end, I found two MELTs at once, which wonderfully fit my task. The first of these is a single-line 10-character MT-10S1 with a controller, which, as the manufacturers claim, is “ similar to HD44780 by HITACHI and KS0066 by SAMSUNG". It has rather large signs: more than 8 mm in height, which is generally characteristic of Chinese displays, which are much larger. The width of the board is 66 mm, the dimensions of the protruding screen (external) are 62x19.5. The consumption in this case worries me not very much (for the external sensor is powered by a solar battery of obviously more power than necessary), but out of habit, looking at the line in the datasheet, I found out that it is also less than usual - 0.7 mA (all normal LCD -displays on analogs HD44780 consume from 1.2 mA and above). There is still a highlight up to the heap, as usual for all such types - rather miserable and at the same time consuming a lot of energy.
The second display MT-10T7 is even more delightful: exactly 10 seven-segment digits 13 mm high fit exactly in the same dimensions. Some suspicions were caused by non-standard, and, apparently, self-made interface (for which the datasheet even gives an example of programming in the verbal pseudocode). The display does not contain a real controller: there is a set of static triggers-latches, controlled by combinational logic. But thanks to such simplicity, this whole design consumes only 30 µA, that is, it really suits devices that work on battery power around the clock (the consumption of 1.4 mA for conventional displays and even 0.7 mA for MT-10S1 greatly exceed the permissible for such use of the value - calculate for yourself how long such a display will work, even without taking into account the other components of the device, for example, from AAA batteries with a capacity of about 1500 mAh.
In short, give two!
MT-10T7
An attempt to independently reproduce the algorithm for MT-10T7, described in the datasheet (on both the Arduino and in pure assembler), did not lead to success. I did not understand what was done wrong, because I came across this publication , where the author (eshkinkot) gave a very well-written and thoroughly executed example of handling MT-10T7, after which everything worked right away. If anyone is interested, then here is a modified example of eshkinkot, supplemented by all meaningful symbols on the seven-indicator indicators, including letters that do not coincide with the numbers:
In these pictures, the contrast of the screen is slightly trimmed by setting the divider to output Vo - 18 kΩ (to nutrition): 10 kOhm (to the ground), although without it the contrast “by default” is quite acceptable.
I then added a function to the given example that reproduces an arbitrary number within three to four decimal places - positive or negative, integer or floating point, that is, the total number of characters can reach five: “-12.7”, for example. Since the dot in the seven-segment code does not occupy a separate familiarity, the maximum number of output digits is 4. Input parameters for this function are: a) an array (char buf [5]) containing the ACSII representation of the number, b) the actual number of characters in it (ii from 1 to 5) and c) the position (pos from 0 to 9) where to put the first (left) sign of the number (used along the way functions and designations, see the eshkinkot publication or in the example by reference):
Function code
voidwriteASCIIdig_serial(char buf[5], byte ii, byte pos)//отображает на дисплее число из буфера{
boolean dot; //признак присутствия точки в массиве//выравнивание числа вправо, начиная от pos:
pos=pos+(4-ii);
//если есть точка, то на символ меньше: for (byte i=0; i <= ii; i++) if (buf[i]=='.') pos++;
//выводим поразрядно:for (byte i=0; i <= ii; i++){
//если след. символ точка, то выводим с точкой:if (buf[i+1]=='.') dot=true; else dot=false;
switch (buf[i]) { //decoder ASCII -> 7-сегментный кодcase'0':
writeSymbol(pos, DIGIT_ZERO, dot);
break;
case'1':
writeSymbol(pos, DIGIT_ONE, dot);
break;
case'2':
writeSymbol(pos, DIGIT_TWO, dot);
break;
case'3':
writeSymbol(pos, DIGIT_THREE, dot);
break;
case'4':
writeSymbol(pos, DIGIT_FOUR, dot);
break;
case'5':
writeSymbol(pos, DIGIT_FIVE, dot);
break;
case'6':
writeSymbol(pos, DIGIT_SIX, dot);
break;
case'7':
writeSymbol(pos, DIGIT_SEVEN, dot);
break;
case'8':
writeSymbol(pos, DIGIT_EIGHT, dot);
break;
case'9':
writeSymbol(pos, DIGIT_NINE, dot);
break;
case'-':
writeSymbol(pos, SYMBOL_MINUS, dot);
break;
} //end decoderif (buf[i]!='.') pos++; //если не точка, то +1 позиция
}//end for i
}
The MT-10T7 module for the control output of numeric values is more convenient than ordinary line-matrix displays: it has large numbers and the decimal point does not occupy a separate place and, therefore, it is possible to fit one more character in the same positions. But for my purposes it is more convenient if there is a possibility of outputting letters (otherwise, the direction will have to be output in compass degrees, which is somewhat unusual). Therefore, for this case, I turned my attention to the identical-size single-line matrix MT-10S1, which, despite a number of shortcomings, moved into the finished structure. At the same time he already has a backlight, which MT-10T7 is deprived of (for this it was necessary to immediately buy MT-10T8), and I decided that in this case its presence would not hurt.
MT-10S1
The display MT-10S1 letters-tsifirki and a half times smaller, but also quite decent size. In addition, its screen is economically packaged in general dimensions: there are no 10-digit imported counterparts, but in Vinstar WH1601L (where the characters are even slightly smaller in height) there is one millimeter more of the total length of the board and screen. Well, almost twice the consumption of the controller (compared to the same WH1601L). Actually, this is where the advantages end, then “features” begin.
The module boasts that, as already mentioned, has a controller that is compatible with HITACHI HD44780. That is, it should work without any straining with your favorite Liquid Crystal. Moreover, the “default” page of the coding coincides with the English-Cyrillic page of the HD44780 and its numerous analogues, that is, the MT-10S1 should work without problems with Liquid Crystal Rus, no code pages are required for this to switch. And he really does it all, but with nuances.
The first caveat - in the single-line version, the developers, apparently, save on registers, and only 8 characters of a string (addresses 00h - 07h) fall into one register, and the remaining two characters belong to another register (40h-41h). That is, the display is de facto two-line, just the two lines are physically located in one line. Upon closer inspection, it turned out that the same is true for the WH1601 (only there the second register occupies the full eight bits). Why it is so inconveniently done is completely unclear, in regular 16x2 displays the registers are sixteen-bit, and hardly such truncation reduces the price of the product, rather the opposite because of the need to produce different versions of the controller (if they are different, which I am not at all sure about). I thought it was connected with this less than usual, the consumption of MT-10S1, but the same WH1601 consumes 1.2-1.4 mA,
Well, it would seem, and it is fine - in Liquid Crystal Rus the function setDRAMModel () and the corresponding constant LCD_DRAM_WH1601 were revealed. For such a regime, an obvious address translation is written in the library:
if (ac>7 && ac<0x14) command(LCD_SETDDRAMADDR | (0x40+ac-8));
But I don’t know how it works on other one-line displays, and MT-10S1 in this mode refuses to work at all - the screen remains just empty. Since it’s about addressing, you can’t fix it with a simple self-written function on top of the library, but I didn’t pick the library and find out what was happening - I already have half a dozen Liquid Crystal versions that I’ve already corrected; Further.
Display MT-10S1 must be declared as two-line: lcd.begin (16, 2); (instead of 16, you can substitute 10 or 12, nothing will change, since the real number of characters in one line is still 8). Attempting to initialize it as a single-line one (tsifirka 1 in the second position) will lead to a failure — the background will turn dark. And it is possible to output multi-digit numbers only within 8 characters, for longer lines, extreme characters over 8 will simply disappear. Therefore, the 9 and 10 characters either actually are suitable only for displaying auxiliary quantities (units of measurement, for example), or you need to split the string-number into separate digits, and when switching to the 8th character, change the cursor position to the first character of the second row.
For the afflicted hereYou can download a test sketch for this display (connecting leads is in the text of the sketch or in the diagram below). By the way, the contrast (which is not a word in the factory datasheet, and the output Vo is designated as NC) is adjusted in the usual way, but this is not really necessary: in the absence of illumination, the background seems somewhat darkish, but when you try to lighten it by connecting the divider to Vo output the contrast is noticeably lost when the backlight is turned on.
Interface with controller
After checking that everything works as it should, the question of how to dock it all with the controller of the sensor rose to its full height. To provide control from it directly, the sensor controller didn’t have enough free outputs, and there was no wish to fence the township with large controllers - it’s more convenient when building the system is modular, and the display doesn’t interfere with the basic algorithm already debugged before. It remained to use any of the serial interfaces.
This suggests I 2The C-solution is based on PCF8574 (or its numerous analogs), especially since this chip itself is just a fancy shift register, and therefore consumes several tens of μA during operation and less than 10 μA at rest. In conjunction with the MT-10T7, they form an excellent pair for creating low-power devices with indication, and MELT even has a ready-made version for this: MT-10T11 with a total consumption of 30 μA.
But for the MT-10S1 there is no such convenient solution - for some reason, additions in the form of PCF8574 analog among MELT line displays are provided only with versions of 20x4 configuration ( UPD: in the comments it was suggested that there is still MT-16S2H configuration 16x2 with the same interface, however , his dimensions go beyond the dimensions I need). Ready module of the type describedin this article , in this case, it is inconvenient to use, since the second unpleasant feature of the MT-10S1 display is non-standard wiring. The conclusions are all the same (HD44780 after all, more precisely, its domestic analogue KB1013VG6), but are arranged completely in an irregular way. I checked for the sake of interest both imported 16x1, and MELT'ovskie two-line / four-line - they all have a standard order of conclusions, and MT-10S1 for some reason stands out against this background. So it is necessary to fence the self-made decision.
As a result, I simply put the same ATmega328 controller on the display, which was programmed in the same way — via UNO, and then inserted into the socket on a separate board, equipped only with the necessary accessories for the launch: quartz with conder, power capacity and RC circuit Reset (see sensor circuitin the original article , where the controller is connected in a similar way).
By the way, about the chain of Reset
Кстати, о цепочке по Reset: у меня там на резистор в несколько кОм стоит конденсатор аж 1 мкФ, то есть время задержки при включении питания составляет несколько миллисекунд. Не много ли? Пособие нас учит, что, как и для всего семейства Mega, внешняя цепочка здесь вообще не требуется, корректный запуск по идее осуществляет внутренняя схема, причем гораздо быстрее. Но привычка ставить внешнюю RC-цепочку по выводу 1 контроллера для задержки запуска при включении осталась у меня со времен забытого уже семейства AVR Classic, где при недостаточно быстром нарастании напряжения питания контроллер мог запускаться некорректно. Да и в семействе Mega Brown-out Detector может работать не очень как следует. В критичных случаях все равно стоит ставить внешний монитор питания, ну, а здесь RC-цепочка ничему не помешает, зато может помочь в случаях с плохими источниками питания. Разработчики Arduino-плат это, кстати, прекрасно знают, потому на плате Uno, например, стоит такая же цепочка 10 кОм/100 нФ.
And two identical AVR-controllers God himself ordered to dock using the usual Serial-interface, which all the same, except the programming process, is not used anywhere else in this project, and for the use of which everything is already at hand. By the way, such a solution does not differ from the price of components based on PCF8574 and can easily compete with it in terms of energy saving in the version with MT-10T7 - in case the MT-10T11 mentioned above is not at hand.
Total scheme of the module MT-10S1 with the controller is as follows (in the diagram the designation of the conclusions of the ATmega328 is given in brackets after the conclusions of the Arduino board):
In the controller, I applied the power saving mode (well, yes, it is not very necessary here, but why keep the chip on all the way without need?). Moreover, the awakening occurs on a signal from the same generator of the meander on the 555 chip, as the clocking of the main controller, only this time along the falling front (FALLING), in order to slightly separate the functions of measuring and sending data.
Mystery of nature
С этим связана одна загадка природы, разрешить которую я так и не смог. Известно, что Mega вывести из состояния глубокого сна можно только внешним асинхронным прерыванием, так как тактовый генератор при этом выключен и синхронное прерывание просто не может произойти. А все семейство 28-выводных AVR-контроллеров, ведущее свою родословную от ATmega8 (48/88/168/328) имеет в качестве такового только прерывания INT0 и INT1 по низкому уровню (и еще прерывание PCINT, но в Arduino оно не задействовано). С этим связаны все официальные рекомендации и в материалах Atmel и на сайтах Arduino. В примере на сайте arduino.cc прямо написано: «In all but the IDLE sleep modes only LOW can be used». И это как бы не подвергается сомнению, например, то же самое более развернуто повторяет Монк в своей книжке: «Обратите внимание на то, что выбран тип прерывания LOW. Это единственный тип прерывания, который можно использовать в данном примере. Типы RISING, FALLING и CHANGE не будут работать».
Прерывание по низкому уровню очень неудобное в применении, так как один раз произойдя, при наличии этого самого низкого уровня на выводе оно будет происходить снова и снова, и надо принимать специальные меры, чтобы избавляться от лишних срабатываний. Так вот, ковыряясь на форумах в поисках различных решений этой задачи, я вдруг пару раз наткнулся на примеры кода, в которых для выхода из сна явным образом используется INT0 типа RISING или FALLING. Разумеется, я отнес это на счет безграмотности авторов. Но когда вот здесь споткнулся о фразу: «Хотя можно использовать и любой другой тип прерываний (RISING, FALLING, CHANGE) — все они выведут процессор из состояния сна», то решил, назло врагам, провести живой эксперимент — благо для этого все было под рукой.
И, к моему изумлению, все отлично заработало. Режим энергосбережения — SLEEP_MODE_PWR_DOWN; в силу ненадобности здесь я не принимал меры для дополнительного снижения потребления с отключением всяких других функций, но все равно тактовый генератор заведомо отключен. И тем не менее контроллер исправно просыпается по falling edge, запрашивает данные, отображает их на дисплее и засыпает снова. Для чистоты эксперимента я извлек МК из платы UNO и вставил в свою панельку с подключенным кварцем, и все равно всё продолжало работать. Это видно по потреблению: почти 17 мА в обычном режиме и 0,9-1 мА при включенном энергосбережении (из них 0,7 мА следует отнести на счет дисплея).
Не выходя из изумленного состояния, я перечитал даташиты от Atmel, заглянул в книжку Евстифеева (с их переводом), даже просмотрел старинное Atmel’овское пособие по семейству Classic, потом затратил полдня на поиски хоть какого-то объяснения происходящего (и по-русски и по-английски) в двух известных всем поисковиках, но нигде не нашел даже намека. Разве что в Atmel’овские Application Notes не полез, потому что сомнительно, чтобы там публиковалось что-то противоречащее даташитам.Буду счастлив, если кто-нибудь знающий объяснит мне, чего я здесь недопонимаю.
UPD: живая проверка на ассемблере (ATmega8) показала полное соответствие даташитам, то есть работает только прерывание по уровню. Единственное объяснение, которое приходит на ум — в Arduino каким-то образом подключили к обычному прерыванию еще и прерывание PCINT. Попытка прояснить ситуацию изучением текста системных библиотек Arduino ничего не дала — там черт ногу сломит.
Прерывание по низкому уровню очень неудобное в применении, так как один раз произойдя, при наличии этого самого низкого уровня на выводе оно будет происходить снова и снова, и надо принимать специальные меры, чтобы избавляться от лишних срабатываний. Так вот, ковыряясь на форумах в поисках различных решений этой задачи, я вдруг пару раз наткнулся на примеры кода, в которых для выхода из сна явным образом используется INT0 типа RISING или FALLING. Разумеется, я отнес это на счет безграмотности авторов. Но когда вот здесь споткнулся о фразу: «Хотя можно использовать и любой другой тип прерываний (RISING, FALLING, CHANGE) — все они выведут процессор из состояния сна», то решил, назло врагам, провести живой эксперимент — благо для этого все было под рукой.
И, к моему изумлению, все отлично заработало. Режим энергосбережения — SLEEP_MODE_PWR_DOWN; в силу ненадобности здесь я не принимал меры для дополнительного снижения потребления с отключением всяких других функций, но все равно тактовый генератор заведомо отключен. И тем не менее контроллер исправно просыпается по falling edge, запрашивает данные, отображает их на дисплее и засыпает снова. Для чистоты эксперимента я извлек МК из платы UNO и вставил в свою панельку с подключенным кварцем, и все равно всё продолжало работать. Это видно по потреблению: почти 17 мА в обычном режиме и 0,9-1 мА при включенном энергосбережении (из них 0,7 мА следует отнести на счет дисплея).
Не выходя из изумленного состояния, я перечитал даташиты от Atmel, заглянул в книжку Евстифеева (с их переводом), даже просмотрел старинное Atmel’овское пособие по семейству Classic, потом затратил полдня на поиски хоть какого-то объяснения происходящего (и по-русски и по-английски) в двух известных всем поисковиках, но нигде не нашел даже намека. Разве что в Atmel’овские Application Notes не полез, потому что сомнительно, чтобы там публиковалось что-то противоречащее даташитам.Буду счастлив, если кто-нибудь знающий объяснит мне, чего я здесь недопонимаю.
UPD: живая проверка на ассемблере (ATmega8) показала полное соответствие даташитам, то есть работает только прерывание по уровню. Единственное объяснение, которое приходит на ум — в Arduino каким-то образом подключили к обычному прерыванию еще и прерывание PCINT. Попытка прояснить ситуацию изучением текста системных библиотек Arduino ничего не дала — там черт ногу сломит.
Data transfer from the sensor controller to the display controller via UART is organized in the form of a dialogue. When waking up, every 4th interrupt the display controller requests data in turn:
. . . . .
if (flag==1) { //флаг устанавливается каждое 4-е прерывание ~6 с
Serial.print('T'); //посылаем запрос данныхwhile(!Serial.available()); //ждем градусов T
iit = Serial.readBytes(buft,5); // считать 5 байт максимум,// в ii реально прочитаное количество
Serial.print('H'); //посылаем запрос данныхwhile(!Serial.available()); //ждем влажности
iihh=Serial.readBytes(bufhh,5); // считать 5 байт максимум,// в ii реально прочитаное количество
Serial.print('S'); //посылаем запрос данныхwhile(!Serial.available()); //ждем скорости
iiss=Serial.readBytes(bufss,5); // считать 5 байт максимум,// в ii реально прочитаное количество
Serial.print('D'); //посылаем запрос данныхwhile(!Serial.available()); //ждем направления
iid=Serial.readBytes(bufd,5); // считать 5 байт максимум,// в ii реально прочитаное количество
flag=0; //сброс флага запроса
}
. . . . .
Here, buft, bufhh, bufss and bufd are arrays (not strings!) Of five bytes, which contain data on temperature, humidity, speed and direction in the form of an ASCII decomposition of the corresponding numbers. In order not to take too much, an abbreviated timeout for reception is specified in setup'e:
. . . . .
Serial.begin(9600);
Serial.setTimeout(10); // лимит времени 10 миллисекунд
. . . . .
It is more convenient to display: first, you immediately have the length of the received number, secondly, the Serial.print () function from the sensor controller side still sends an ASCII string, with the pauses set at exactly the same 10 ms between the packages :
. . . . .
//посылка данных на дисплей по запросу:if (Serial.available()>0) //ждем запроса
{ char ch=Serial.read();
if (ch=='T') {
Serial.print(temperature,1);
delay(10);}
if (ch=='H') {
Serial.print(humidity,0);
delay(10);}
if (ch=='S') {
float wFrq=(3+0.8*f)/10; //из герц в м/с if (wFrq>0.3) Serial.print(wFrq,1);
else Serial.print(0.0,1);
delay(10);}
if (ch=='D') {
// Serial.println(wind_G);
Serial.println(wind_Avr);
delay(10);
}//end ch
}//end serial
. . . . .
The calculation of speed in m / s here is identical to that which is performed in the main module of the station (the start-off threshold is set at random to 0.3 m / s) and will also have to be changed based on the calibration results.
If you try to accept data with the usual Serial.read () and then display the result of the reception with a function like lcd.print (t, 1), where t is the temperature in degrees, for example, 12.7, then MT-10S1 responds to such the command will output "49.5". Guess or suggest? These are the first three characters in the sequence "49 50 46 55", that is, in the ASCII decomposition of the number "12.7". Therefore, it is easier to immediately receive an array of characters and directly display as many characters as were sent (count is the counter that is incremented by each interrupt):
. . . .
if (count%8==0){ //каждые 8 прерываний выводим
lcd.clear();
if (buft[0]!='-') lcd.print("+");
for (byte i = 0; i < iit; i++)
lcd.print(buft[i]); //вывели температуру
lcd.setCursor(6, 0);
for (byte i = 0; i < iihh; i++)
lcd.print(bufhh[i]); //вывели влажность
lcd.setCursor(0, 1);
lcd.print("%");
}
if ((count+4)%8==0){ //еще через 4 прерывания
lcd.clear();
lcd.setCursor(0, 0);
for (byte i = 0; i < iiss; i++)
lcd.print(bufss[i]); //вывели скорость
lcd.setCursor(5, 0);
dir_dd(bufd); //выводим направление
}
. . . . .
The last line needs decoding. The point is that the direction data is sent in code 0-15 (to which they are still transferred from the Gray code when implementing vector averaging ). In the case of the seven-segment display MT-10T7, they were converted to compass degrees:
. . . . .
dd=atoi(bufd); //преобразуем в число
dd=dd*22.5; //пересчитываем в градусы
itoa(dd,bufd,10); //преобразуем обратно в строку
. . . . .
And here we can write directly in Russian letters, as well as in the main module of the weather station (which is why this display was actually chosen):
. . . . .
voiddir_dd(char dd[]){switch(atoi(dd)) {
case0:
{lcd.print("С"); break;}
case1:
{lcd.print("CСЗ"); break;}
case2:
{lcd.print("CЗ"); break;}
case3:
{lcd.print("ЗCЗ"); break;}
case4:
{lcd.print("З"); break;}
case5:
{lcd.print("ЗЮЗ"); break;}
case6:
{lcd.print("ЮЗ"); break;}
case7:
{lcd.print("ЮЮЗ"); break;}
case8:
{lcd.print("Ю"); break;}
case9:
{lcd.print("ЮЮВ"); break;}
case10:
{lcd.print("ЮВ"); break;}
case11:
{lcd.print("ВЮВ"); break;}
case12:
{lcd.print("В"); break;}
case13:
{lcd.print("ВCВ"); break;}
case14:
{lcd.print("CВ"); break;}
case15:
{lcd.print("CСВ"); break;}
}//end switch
}//end dir
. . . . .
Appearance
The photo shows the appearance of the display with the connected controller in working condition:
This is how the module of the modified sensor looks like:
The backlight parameters are those shown in the diagram above. Since the voltage drop on the backlight in the MELT modules is 4.5 V, then at 12 V power supply, the backlight current is 50 mA (at the maximum for this module 60 mA).
The case is maximally sealed to avoid ingress of moist air inside (the black frame of the display screen is made of rubber sheath of a thin cable). The white plate on the right is the enclosure of the SHT-75 humidity-temperature sensor, which is outside the enclosure (the sensor itself is located behind it). The yellow wire above is a 433 MHz transmitter antenna. On the left are the connectors where the speed and direction sensors are connected.
And this is what the readings on the display of the main module of the weather station look like (the black module with the white antenna on the right is a 433 MHz receiver):