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
- Output 1: Warning if volume < 1000 l
Output 2: Activates a feeding valve when volume < 200 l - Output 1: Activates an alert if volume <500 l,
Output2: Activates an alert if volume >5800 l (spillover alert)
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:
- Volume change last hour and current hour (marked by an asterisk
*
).
positive values indicate a rise of the water level (rain), negative values a fall (water usage). - Number of power on, watchdog and brownout resets (only displayed if relevant and indicates hard- or software failure)
- Volume change yesterday and today (indicated by succeeding
*
) - Sensor temperature in °C and calculated speed of sound in m/s
- Travel time of the pulse and calculated distance to the water surface in meters
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:
- Temperature in °C and calculated speed of sound in m/s
- Number of power on, watchdog- and brownout resets (only shown if relevant)
- Traveling time of the pulse in ms and calculated distance from the water surface in meters
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
- System startup
- Active alert output 1
- Active alert output 2
- Hour bell
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:
- 1: Alert output 1 is played always
- 2: Alert output 2 is played always
- 4: Hour bell is played (inside the time span enabled)
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:
- Calibrate: Performs a calibration of the voltage dividers.
The user is asked for the exact values of the according voltages and the controller
calculates correction values for the AD converter.
Normal function of the display is halted during calibration. The backlight will be shut down to keep ripple voltage low on the Unreg supply. Better use a 24 VDC supply from a regulated power supply for exact values.
This command always ends with a display reset. - ClearErrors: Clears all error counters (watchdog and brownout) as well as the error message on the display.
- DCFInv <0|1>: allows changing the polarity of the DCF77 receiver.
0 means non inverting, 1 means inverting. To find the correct setting for your receiver, watch the
blue led. It should show short flashes once a second. If it is mostly on and shows
dark flashes
the setting is wrong. - Debug <...>: sets debugging on or off.
Without parameters debugging is completely disabled. These parameters are allowed
(each separated by spaces):
- sensor: shows received sensor data.
- dcf: shows DCF77 related information. This is pretty
dangerous
since then interrupt controlled routines are called from within an interrupt which might result inhanging up
of the display if the transmit buffer is filled up. Therefore this should only be used if you really need to debug and not for listening just for interest.
- DumpConf: creates a human readable interpretation of the configuration memory.
- FTest: executes a simple factory test.
This command always terminates with a device reset. - GetSensorValues: Displays the sensor data (volume and temperature). This can be used regularly to create graphs or statistic reports.
- Help: prints a list with all available commands together with a short explanation.
- Reset: is only useful for debugging purposes and simply causes a watchdog reset.
- SetBright <Brightness>: sets the brightness of the LCD.
This command does not change the duration of the backlight. It only sets the brightness
while the backlight is on.
You can give relative a change by adding a sign to the number (e.g. +10, -10).
Without a sign, the value is taken absolute. The value ranges from 0 (off) to
255 (maximum brightness).
Factory default is 255 (maximum brightness).
The decision for permanent or acute backlight currently can only be selected via the key. It will also be permanent executing a write command. - SetCistern <type> <depth>
<area/diameter> <capacity> [<length>]:
Defines the dimensions of the cistern.
type defines the shape:- const: The cistern has constant surface area (e.g. a standing cylinder or a cube).
- horiz: The cistern is a horizontal (lying) cylinder.
- sphere: The cistern is a sphere.
area/diameter is the size of the surface area in square meters for typeconst
or the diameter of the lying cylinder or the sphere.
capacity is the maximum volume (when the cistern is filled up to the spillover). It is used to calculate the percent value for analog display as well as for the bargraph display on the LCD.
length is only important for the lying cylinder and can be omitted for other types.
Please keep in mind that cisterns of type horiz and sphere might be problematic. Reflections from the bottom walls may arrive earlier than those from the water surface so low levels might not be correctly measured. I consider these geometries as not suited for ultrasonic measuring. - SetContr <Contrast>: sets the contrast level of the LCD.
You can give a relative change by adding a sign to the number (e.g. +10, -10).
Without a sign, the value is taken absolute. The value ranges from 0 to
255.
If the display is black, raise the value. If it is bright (without readable text), reduce it.
The factory default is 25 what guarantees readable text at room temperature. - SetDisplay <Type>: Sets the type of the display used.
Type can be 4x20, 2x16 or analog.
Originally I wanted to use the display type as a constant being fixed at compile
time. This would save space in flash memory. But as the controller has immense reserves
I implemented it as a configurable variable. So you can choose the display
without having to recompile the sources.
The advantage for production is clear: you have only one firmware version fitting for all display types. - SetPTime <seconds>: sets the time for periodic display cycling. Default is 4 s. So in normal operation the screen changes every four seconds. This is an uint_8 so the maximum value is 255 s.
- SetPTimek <seconds>: sets the time a keypress 'freezes' the page. After that, periodic display cycling is started again. Default is 60 s. So if you press the key to display a certain page, it will be displayed for 60 s before normal screen stepping is resumed. This is an uint_8 so the maximum value is 255 s.
- SetSignal <number> <low> <high>: sets the thresholds for an alert output. The output becomes active if the volume is smaller than low or larger than high liters. Number may be 1 or 2.
- SetSpontaneous <liters>: if <liters> is not 0,
changes in volume will be reported spontaneously if greater than <liters>.
Setting it to
0
disables spontaneous messages.
Attention: if you activate it and do not have a permanent device attached to the serial line (bluetooth!) this may lead tohang up
the device if you have RTS/CTS handshake active! - SetTime <hh:mm>: sets the system time (hard). If DCF77 can be received, it will be corrected with the next valid telegram. When setting the system time time the hard way, secondly, minutely or hourly events may get lost.
- SoundEnable <hourfrom> <hourto> [<soundmask>]: Audible alerts are only played from hourfrom to hourto to ensure a silent night. The range is from 0 to 24. Tones are only played if the current hour is even or more than hourfrom and less than hourto. soundmask allows special treatments. For details see Sound. soundmask is 0 unless you specify another value.
- Status: prints a list of all display sensors, i.e. the values of all voltages and the temperature inside the display case. The temperature is not the room temperature but the temperature inside the display case. It can be used to adjust display contrast (not implemented for now).
- Update: starts a firmware update of the sensor.
Normal operation is halted. The display awaits an Intel HEX file containing the sensor firmware
and updates it. After that, a system reset is executed.
If a line is received that does not confirm with the Intel HEX format (e.g. a line that does not
start with a colon, even an empty line) the command is terminated.
This command always ends in a device reset.
It is only available if the sources have been compiled withWITH_UPDATE
(in display.h). Read here about the reasons why this flag exists. - UseRts: Sets if RTS/CTS handshake should be used.
specify 0 for no and 1 for yes. This command only exists if
USE_RTS
is defined in the sources! - Write: Stores the content of the configuration memory into NVM (non volatile memory) so it will become permanent. You should do this after any changes of the configuration. Unsaved changes will get lost after a device reset.
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:
- Green shows the time the controller is sleeping in the main loop i.e. how many computing power still remains. If the green LED becomes dark, the computing time of the controller is mainly used by other tasks.
- Red is on while the controller is executing the ADC interrupt
- Yellow is on during the Timer 0 interrupt
- Blue is a software copy of the DCF77 receiver signal and may help you arranging the antenna.
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:
- The controller has enough power to do double arithmetic in real time
- Double values still work if they become negative on places I did not think of.
- Double values still work if they become unexpectedly big, especially in intermediate results. And there are much less portions of source code you would have to adopt. Think of something like a/b*c. Using integer arithmetic, the result might be 0 if b and c are big!
- Absolute accuracy is not necessary, i.e. simplified 1+1=1.9999973 is absolutely o.k.
- The ESA lost a multi million dollar rocket because of an integer overflow. The cost of keeping these values as double would have been next to zero.
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:
- You have to to computations in interrupt routines. The time necessary may violate your limits (especially with ATmega controllers where an interrupt cannot be interrupted by higher priority interrupts). But do you really have to do so?
- Your application is critical to power consumption. Double calculations
are more
expensive
than integer calculations. If your system has to operate 10 years with a single lithium cell you may have to use integers. - You have to process streams at high data rate (i.e. audio or video streams). This may become too expensive in double precision for a high volume production.
- You have to keep large amounts of data in memory. Integer numbers are smaller than double numbers. Although it may be better to calculate them in double precision.
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