Ultraschall Füllstandsmesser Display-Seite auf Deutsch
Ultraschall Füllstandsmesser Display-Seite auf Deutsch

Display

Display

The display unit uses an ATmega128, again with a clock of 3.6864 MHz. I chose it because of its two serial interfaces, one to the sensor unit and one (RS232) to the host PC or to a home bus (RS485). Starting with revision 2.0 a Bluetooth module has been added. For the baud rate, 9600 baud has been selected. This is more than enough for measuring the water level once per minute but may be good enough for further tasks like reading energy meters or switching arbitrary loads but this is a different story...

The Bluetooth module is set to 9600 baud by default. If you chose a different baud rate it is not enough to set it at the PC and the display. The Bluetooth module has to be reprogrammed also! I did not do this and can only advice the datasheet of the ARF32!

So, the display is requesting the level once per minute, calculates the water level and displays it. By the way, it also calculates the difference to the previous hour and the past day. The time being displayed relates to the latest power on, it can be set via the serial interface (or via Bluetooth) or by a connected DCF77 receiver.

Acquiring the water level, 10 measurements of the sensor are averaged. After that, the sensor supply is shut down. This not only saves energy, it also reduces self heating of the sensor what is good for accuracy of the temperature measurement. By the way, the sensor is reset if it should 'hang' for some reason.

Praxis showed that the distance metering works very accurate and repeatable. Indeed, you can follow the liters go away while measurement is active. During rainfall, the surface is in turbulent movement and even splashes can induce false measurements unless you have a subsurface inlet, that's why the averaging.

The display is built for always on and thus contains some means for energy savings. Energy consumption is, according to an energy meter from Conrad Electronics at 0.0 W (it is below the measurement resolution of about 2.0 W).

For the case I decided for a Heidenreich ZA16 that was accidentally available. It is good for wall mounting, can easily be disassembled and the front panel suits perfectly for our LCD display. It is not really stylish but between other devices in my heating room it looks really good...

Connecting the Sensor Unit

The connection between the display and the sensor unit should be a standard network cable. It is cheep, easy to get and of high quality for data transmission. According to the low baud rate used, UTP should also work. But you should avoid control cable with parallel wiring. If you have already buried it, well, try it out. 80 cm below the surface there should not be much EMI. The shield (if it has one) should be connected to GND at the display unit (it is providing the supply) and be isolated at the sensor end. We need only one pair for data and one for supply. If you use a network cable it can only be good to use the spare pairs for supply (one line of each pair to +, the other to GND).

The display switches the 15 V (Unreg) via a simple constant current source (T1, D1 and R3). This prevents voltage dips in the display's supply and/or overloading T1. The current source 'costs' only two diodes (in a single SMD package and really cheap!) and a resistor compared to a simple switching transistor.
The current source is not short circuit proof, though. If the sensor supply was shorted to GND, T1 would deliver some 40 mA from the display supply. This would lead to overheating and failure of T1 within a few seconds. But it can give you a chance to draw back the probes. A switching transistor would die in milliseconds...
The 15 Ω resistor R112 in the sensor unit is for damping oscillations that might occur by the inductance of the line and the input capacitor of the sensor. Long lines and high performance ceramic capacitors can form resonating circuits of astoundingly high quality that can produce disturbing, if not destroying power if switched hardly. If you want to play a little, here a simple simulation of the current source in LTspice.

Termination

According to wide spread public literature, the line has to be terminated with 120 Ω at both ends. This is no fault, of course, integrity of the signal can only take profit of this, but it significantly increases current consumption.

Unfortunately, the 120 Ω are not a natural constant but are the characteristic impedance of the cable you use. For different cables, you need different termination resistors to get optimal results.

What is characteristic impedance?

Einstein states, there is nothing faster than light. Now, when the current source switches on, how should it now about the load at the end of the cable? Although the cable is only 10 m long (light would need about 30 ns for this). Well, it does not. At the beginning a current will flow that matches the characteristic impedance of the line. When it arrives at the end of the line a part of it will go into the load, the rest is reflected and arrives 30 ns later at the source. It appears there as a positive (or negative, depending on the load) voltage which now, in series with the source, drives a higher (or lower) current into the line. So the reflected current superimposes the initial current and it will finally settle to the value actually needed. Thereby, in worst case, overshoots may occur that make twice the voltage applied.

In fact, signal speed will be about 2/3×c0 so we would have to calculate with roughly 45 ns per 10 meters.

Termination becomes necessary if the rise and fall times of the signal come into the region of the travel time on the line. We take advantage of slew rate limited drivers what reduces reflections. Additionally, the receiver does not act on edges it sees but it samples the level in the middle of a bit (i.e. at 9600 baud about 50 µs after the falling edge). Until then, reflections are simply eaten up by the cable resistance (they would have traveled about 500 times forth and back through the line), they are gone. That's why I refused to terminate the line. I have about 10 m of cable to the sensor and it works without trouble. Even on the scope you cannot see anything of reflections.

Using higher baud rates, the maximum cable length without termination would decrease. Reflections have to relax below the threshold of the receiver until it samples the bit value.

I recommend not to terminate the line. It is not necessary since all reflections are gone until the receiver samples the bit value.

If you want termination, you must increase the current of the constant current source, i.e. lower R3 and in consequence also R8 to deliver enough base current else the sensor supply would break down during transmission.

My choice for this way: R3=6.8 Ω, R8=4.7 kΩ but this is only an estimation. I did not terminate and I did not test this.

Doing so would increase the load for the display and the ripple on Unreg. These are complications you can simply avoid.

Although, if your line to the sensor is very long (10s or 100s of meters) you should check back with your scope before you seal the sensor.

Interfaces

The display controller has two USARTs. USART0 is used for communication with the sensor via a RS485 physical layer, USART1 can be selected via placing option or jumpering to communicate via Bluetooth, RS232 or RS485 with a host PC. Sending always is done via all Interfaces, only the receive signal is selected.

The jumper header is monstrous (especially since according to the datasheet the Bluetooth module also needs RTS and CTS) and I'm not really happy with it but it is the cheapest solution, we have enough board space and it normally has to be set only once.

The support for RTS/CTS handshake can be enabled by define in the sources or by configuration flag. In my sources the handshake is enabled, you can disable it by command. This would be necessary if no permanent device is listening on the host interface else sending data will not be possible and the display would block as soon as the transmit buffer is full.

The USART supports switching the transmitter via interrupt flags (needed for RS485 as a half duplex media) what makes it very comfortable from the software view.

Communication with the Host

The display unit communicates with the host at 9600 baud, 8N1 (i.e. with a PC or Laptop). Since the 9th bit would cause problems together with PCs i refused to use 9 bit communication and all communication is done in human readable ASCII characters. The interface is always active. I did not use a select device what would be necessary in a bus system with multiple devices until now.

The Bluetooth module uses the same baud rate by default so it can be used without special precautions.

The routines used for transmission and reception are controlled by interrupt. Sending is done as usual via a FIFO in SRAM. In the receive routine, characters are collected until a <LF> appears. (<CR>s are ignored). The line is then interpreted at whole. A command always starts with a keyword eventually followed by parameters, separated by spaces.

And what if no <LF> follows? Anyone would press <Return> after sending a command!

NO! This is the classical buffer overflow attack! Characters still come in, even if you do not expect them if the Host is not benign or if there simply are EMI problems. They would be stored in a range that was not intended to. The result may be currupted variables and erroneous display, a simple crash or execution of unintended or foreign code!
I decided for a buffer wrap, i.e. characters that do not fit into the buffer start overwriting it from start. You could also ignore characters if the buffer is full, that is just a matter of taste. The main thing is not to write beyond the buffer!

Such an attack may go over both directions: it sends more characters than you expect or it produces more responses than your transmit buffer can capture. Be prepaired for both of them!

Luckily the different formats of host commands allows to separate host commands from telegrams from the bluetooth module. So the receiving routine can set separate flags for each of those events.
Detecting the bluetooth telegram is not quite easy since the end delimiter (ETX, 0x03) can also appear in the data so we have to parse the telegram.
Only a few telegrams should appear in our case since we normally use only transparent mode. The first one should be the LMX9830_READY which is sent on power up or reset of the bluetooth module. This is followed by a SPP_INCOMING_LINK_ESTABLISHED and if the link gets lost, may interchange with SPP_LINK_RELEASED. With these telegrams we can detect if we have bluetooth at all and if a host is actually connected.

RTC

Timer 0 causes 100 interrupts per second. By the way, we create a real time (HH:MM:SS) clock that is reset at 24:00:00 (days will not be counted). It sets flags for every second, minute, hour and day so the main loop can execute secondly, minutely, hourly or daily events.

At the end of the main loop we execute a sleep, which does not cost money but reduces the power consumption significantly since until the next interrupt much less energy is consumed.

DCF77

For synchronizing the display time with the official time you may connect an external DCF77 receiver. Correct reception is verified by measuring pulse times and checking the frame of the telegram received. Valid telegrams will set the RTC within a second of difference to the time received. Polarity of the receiver signal can be set via command.

There is no special type of receiver required, it only has to operate at a 5 V supply and has to produce a TTL compatible signal. If you see no valid telegrams, try to invert the DCF signal (see also command dcfinv). I would recommend the Meinberg RU226 since it proved reliable for me.

A very simple algorithm allows to smoothly adjust the RTC. If the time received differs for more than 60 s, the RTC is adjusted hard. For this, two valid telegrams have to be received and both of them must be within 60 s. (In practice, I really received single valid telegrams with nothing but nonsense in its data. Multiple bit errors are the reason for this.) When setting the time the hard way, hourly or daily events may get lost since they are only caused by the timer interrupt.

Smaller deviations make the RTC running 1% faster or slower than normal until the deviation is less than a second. So no timer events get lost i.e. one RTC interrupt is skipped or an additional virtual interrupt is added.

You can use the stat command to see if DCF77 synchronization works. Remember that it can take up to three minutes for the RTC to get in sync, even without reception errors. Two succeeding telegrams with the same difference have to be received before a hard sync is executed. An erroneous telegram restarts this time from zero...

An antenna symbol (¡) appears on the display if DCF77 reception succeeds. The system time then has not necessarily been set since this happens only after the second telegram. Vice versa, the antenna symbol may disappear if reception fails. System time then continues running with crystal accuracy.

DCF77 Receiver

It would not give a good return to try saving a few Euros here to get a cheaper receiver. It would cause more trouble than those few bucks are worth while. If you want it cheap, disassemble a Chinese €5 radio clock, if you don't want to be annoyed, use a good receiver. Anything in between only causes trouble. Use a receiver like the Meinberg RU226 and keep attention to the mounting directives. The antenna has to be directed orthogonal to Frankfurt (that's where the transmitter is) and must not be mounted near metal surfaces or conductive loops. Also, interfering transmitters like the display itself (especially its Bluetooth module) should be as far away as possible. You can make no bigger mistake than mounting the receiver in the terminal block just because there is enough space to do so. That's the only way to get an error free signal.

The frequency of the DCF77 carrier (77.5 kHz) is nearly exactly the 5th overtone of the line frequency of PAL television. If you still use an 'old' TV set near by (like I do), it could also prevent an error free signal.

In my lab, there were disturbances nearly everywhere (lots of computers and other 'transmitters') but on a small place somewhere on my desktop. If you experience signal problems, try to move the receiver half a meter around and try again. Sometime, you will succeed!

If you live more than 1000 km from Frankfurt, you will probably not be able to receive DCF77. But similar Transmitters exist in several Countries, each with its own protocol. It may be not too much work to modify the decoding loop to work with a transmitter in your vicinity.

Signal Outputs

Since there were still unused terminals, I added two signal (alert) outputs. These are the photo transistors of two optocouplers that can be used to initiate external actions. Each of them can be programmed to be active below and/or above a certain threshold.

The phototransistors have a common emitter so they are suitable to pull two inputs of an external circuit against its ground.

Each output has two parameters, active below and active above. The values are in liters, ranging from 0 to 65535.

An active above of 65535 will never become active as well as an active below of 0.

By wisely choosing these limits, several configurations are possible, like

If you don't use an output and want to save the power of the optocoupler set active below to 0 and active above to 65535. So the optocoupler will never become active. These are also the default values.

Electrical Safety of the Outputs

The outputs are isolated by optocouplers from the rest of the circuit. But only with a clearance of 5 mm. The circuit you connect to these must not be directly connected to the mains else you would lose the clearance to the display and the sensor! Some people think, 3 mm are enough, well, no risk no fun, I would prefer better safe than sorry in those cases.

This means you must not e.g. directly control a TRIAC connected to the mains. But you may switch the inputs of an SPC or another device isolated from the mains like the parallel port of a PC

One terminal next to the mains is left unused to keep 8 mm clearance to the mains.

Display Layout

Note: The low cost 2×16 LCD is no longer supported and may appear neglected in current firmware versions. Please read the following lines nevertheless since they affect the 4×20 display as well.

The display (two lines with 16 characters each) shows something like this:

1234L<PChh:mm:ss
±1234 l/h ±1234*

The first line constantly shows the volume in liters and the time since system midnight. The volume is the average of 10 measurements. While the measurement is active, it shows the actual result, after that, the average value. To distinguish between, while measurement is active, a small letter l is used and for the average, a capital L.

The characters starting at position 5 (<PC) are error flags and never should appear. At position 5 you can see a < if less than 10 values have been received from the sensor (most likely, none at all). This can indicate a disrupted sensor cable or failure of the sensor device. It can also be a > if more than 10 values arrived. Normally the display shuts down the sensor supply after the 10th measurement. The > can indicate a failure around the constant current source T1, i.e. the display cannot switch off the sensor supply.

The P means parity error and the C checksum error communicating with the sensor. This may be due to a too long sensor cable or a cabling otherwise unsuited. It may also indicate a too low current of the constant current source so the sensor supply collapses while it is sending (this may especially happen if you use termination).

An S indicates that not a single telegram has been received during the past minute (Sensor Dead).

The volume displayed is possibly unreliable or totally wrong if one of these flags appear!

The error flags remain even if the error no longer persists and will be cleared next hour (or after a device reset).

The second line is periodically stepped between the following values:

Extended Display

For me, the low cost version with only a two line display has proved inadequate. So you have the possibility to chose a bigger display with 4 lines and 20 characters per line if you are willing to afford this kind of luxury in hardware (in fact, we are talking of a few Euros).

The following values will be displayed e.g. on a Winstar WH2004A:

1234L<PChh:mm:ss  ¡Ê
01234  l/h 01234*  Î
01234  l/d 01234*  Î
 12.3°C   340.1m/s Î

The first line is identical compared with the 2×16 display. In the second and third line you can see the volume change for the actual and the passed hour as well as yesterday and today.

The fourth line cycles between the following values:

Only in the extended display you can see an antenna symbol if DCF77 reception succeeds.

Backlight

The display has a LED backlight what we won't left unused, of course. We already use a high efficiency switch mode regulator so we can avoid complex circuits and just connect the backlight via a 4.7 Ω resistor to the 5 V supply. I added a transistor as a switch so the display unit can switch it on or off and can even dim it via PWM. I measured 183 mA (at 100 %) in my circuit.

Sound

Since we still have unused port pins and timers I decided to add a piezo beeper connected to timer 3. The sound routines are capable of playing arbitrary tones, musical notes or complete music sequences via interrupt with minimal overhead. The music is only monotone. I did not plan to build a music synthesizer...

To calculate the timer values for musical notes I made this calculator.

Sequences can be played for

The sequences itself are in the current version only programmable in source code and cannot be configured in the running system.

The sequence for system startup is played on each reset and cannot be deactivated.

The sequence for alert output 1 is played every minute in the 10th second and sounds more aggressive. Alert output 1 therefore is suited for urgent alerts.

The sequence for alert output 2 is more discrete and will only play once per hour in the 20th second.

Since this can be annoying you can define a time span out of this no acoustic alerts are played.

Additionally there is a soundmask which enables the following signals:

To calculate the soundmask, simply add the values mentioned above. If you want to hear alert 1 always and you like the hour bell, the soundmask would be 5.
The hour bell is nothing what really belongs to a device like this but I thought about what can be made and because of pure boredom I implemented it.

A visitor of my website finally gave me another idea: from the first production version there will be an

Analog Output

For nostalgic versions you can also completely omit the LCD and use a 100 µA moving coil meter to display the water level in %. I used a RC circuit connected to timer 1 C for averaging and used the second OpAmp as a voltage controlled current source to provide a smooth analog signal mostly free of AC components. The signal is not ground referenced but for a moving coil meter this is absolutely ok.

The meter is connected via X12 which provides the analog signal as well as the dimmable lighting signal and +5 V which you can use to illuminate the meter. Use a twisted wire pair for the analog signal and for the backlight to avoid crosstalk between the backlight PWM and the sensitive analog line.
The pin order of X12 makes it reverse polarity tolerant. If you accidentally place X12 in the wrong orientation, the meter will show negative values and the polarity of the illumination is reversed what would not matter for tungsten lamps and even LEDs should tolerate it.

The current source gives 100 µA at 2.7 V. This allows tolerances to be eliminated by software. A calibration procedure for the meter FSR has been implemented and will be executed within a Calibrate command.

The OpAmp is a not a true rail-to-rail type so we cannot use the complete voltage swing. Its swing to GND is pretty good but it cannot provide output voltages close to VCC.

Since the timer has 8 bits of resolution, the value on the meter can only be changed in roughly 1 % steps but you cannot read an analog meter more precisely than this, anyway. Measurements with an accurate digital Meter confirm a precision better than 1 % FSR.

If you omit the LCD be sure to set the display type to analog. Most parts of the firmware would work if you left it to LCD since the LCD routines have a timeout if the display does not answer but there may be situations where it may cause a watchdog reset.

Well, this was probably the last inspiration I got from a visitor. Since September 2013 Google seems not to provide information about the Keywords you used and that really upset me. That's why i only can recommend don't use Google since I do no longer know what you've been looking for (I don't know who you are anyway even if Google probably does) and I cannot improve my website or my project according to your needs. Don't use Google!

Stackchk

A module named Stackchk has been added to estimate the amount of free memory between heap and stack. It only is present if you #define WITH_STACKCHK, else all calls to its functions would reduce to a simple return. You can do this under project properties - compiler - symbols. A well designed optimizer should eliminate calls to a return. Unfortunately in the current version this is not the case but we only lose three bytes of program memory what normally should be no problem.

In the current version this reports nearly 300 spare bytes so we do not need to worry about stack collisions.

Commands

The following commands have been implemented until now:

Abbreviating Commands

Commands are generally case insensitive. They are only evaluated up to the length of the command given, e.g. cal is the same as Calibrate or, taking it to the limit, d is the same as DCFInf. If you use abbreviations like this it is good policy to use unique abbreviations. There may be commands being added in the future that may collide with the ones you used. Possibly, the order of commands in the source code is not the one you expect. Especially in scripts or other program controlled actions it is good policy to use the full keywords as a command.

Please note: all changes in configuration are only stored temporarily until you execute a Write command! Else the values will be lost with the next device reset.
But you can also use it for testing and get a clean device afterwards.

Parameters cannot be abbreviated. E.g. you can send a deb dcf instead of debug dcf but deb d will not work!

Debug LEDs

For debugging I added four LEDs of different colors. In the current firmware they indicate the following:

These signals are also accessible for the scope via X9.

The blue LED is also needed for the factory test and should not be changed unless you have a very good reason!

Brightness

You cannot find a brightness that will be widely accepted. Some people fear their retina being burned, others say you cannot see them from 15 feet away. I chose 10 mA to supply the LEDs. Modern LEDs are, let's say, bright then. If you use different LED types you may have to adjust the currents. A jumper allows connecting a scope to each of them so you can accurately measure the times. Only for the blue LED, I slightly decreased the current since it seems too bright else.

Of course, you may use the LEDs for other purposes. My sources are yours...

Factory Test

I implemented a simple factory test capable of detecting shorts between two outputs or any output and the supply.

Inputs cannot be checked since the software cannot influence the state of an input line.

For this, a walking zero and a walking one test is executed, i.e. all output pins are set to 1 and a single 0 starts walking through all the pins. As long as only this pin changes to 0 everything is o.k. After that, all pins are set to 0 and a 1 starts walking. This way, many (but not all) short circuits can be recognized.

The supply voltages are measured and compared with predefined limits. The calibration procedure should have been done before to be sure about the limits.

Additionally, the SWUnreg switch can be tested since the controller can measure the voltage. It displays the rise time (up to 90 % of Unreg) and the fall time (down to 10 % of Unreg) which are predictable. So the correct operation of the constant current source can be verified. Typical values are hardly a millisecond for the rise time and about 20 milliseconds for the fall time.

It can be called anytime by the command FTest. Note that spikes may occur at the alert outputs or serial lines that may produce unwanted side effects if they are connected to external circuitry.

The factory test always ends with a watchdog reset.

LITERS_T

LITERS_T is a typedef in my sources for all volume measures in the system and is defined as a double value.

Some people might say, an integer would be sufficient. I use double precision for most of the calculations for the following reasons:

If you have to do complex calculations, do it as double values! Keep in mind that the == operator is not usable then. 2 is not the same as 1.9999973!

As far as I can say, there are only few reasons to do it other ways:

Both of these lists are subject to be expanded. If you think, int_16 is sufficient for LITERS_T, feel free to redefine it. I cannot guarantee if it works although I tried to keep the interface compatible. At least, do not use unsigned types! The volume may become negative if your cistern is one inch deeper than you measured. The results might be irritating.

Layout

A few tips according to the Layout.

Generally, in circuits with a high di/dt inductive components have to be minimized. We experience high di/dt of course in the DC/DC converter but also in the PWM circuit used for dimming the backlight.

Inductance decreases if you make the traces wider and increases with the area they surround.

Use wide traces. 0.3 mm are not enough, even if they can support the current that flows. 1 mm is not enough, either. Use areas, as wide as possible and as short as possible! Think of the path that the current will take on its way back and place the forward and backward path as close as possible to reduce the area surround. Every mm you can save improves the result.

Since the return is normally via GND, the ground plane has to be the first plane below the component side.

DC/DC Converter

For the DC/DC converter this means:
U8 is the switching device, so the highest di/dt is around U8. Minimize the area around C10, U8, L2, C12 as well as D2, L2 and C12.

PWM Dimming

For the dimmer circuit this means:
Minimize the area around C5, backlight, R12 and T3