Sensor

The sensor uses a relatively small controller, the Atmel ATtiny 2313.
With respect to the tiny resources the sensor firmware is written in
assembler code.
All calculations are made in the display unit which is programmed in C
.
The sensor supply is switched by the display. So energy consumption is
only of little interest since it is only powered on while it has to
do its job (about 10 seconds per minute).
This also means it cannot remember anything in RAM. All it has to remember has to be stored in its EEPROM. Until now, it fortunately has nothing to remember at all.
Ultrasonic Transmitter
The hardware of the sender is a standard circuit as it is used in numerous applications. The signal consisting of 8 periods of a 40 kHz oscillation is produced by software. Experiments showed that the signal amplitude rises during the first 2 or 3 periods (resonant effects of the receiver crystal and probably also the transmitter). More than 8 periods will not significantly improve the result.
Ultrasonic Receiver
The receiver circuit has been simulated in LTspice and has been optimized considering the qualities of the OpAmp we used for a maximum amplification at 40 kHz. Every edge of the ultrasonic signal causes an interrupt. The controller then can calculate the distance to the reflecting surface.
Speed of Sound
The speed of sound depends on temperature according to the following formula:
where v0 is the speed of sound at 0 °C (331.5 m/s)
and t0 equals 273 K.
10 °C generate an error of about 2.4 % what are roughly 140 l in
a 6000 l-cistern.
So measuring the temperature is mandatory.
But you should not expect wonders because the temperature gradient
inside the air column may be rather high, especially in summer.
If the sun is shining on the cover plate the air temperature in the
upper region easily reaches 30 °C while it will hardly reach
15 °C near the water surface.
I experienced 'virtual rain' in the range of 30..50 l just because the speed of sound is higher at higher temperatures and thus the surface seems more far away from the sensor as it really is.
Dead Time
When ultrasonic pulses are transmitted, the sensor not only receives echoes from the water surface but in the first time vibrations transmitted via the housing and the near surrounding of the sensor. It is therefore necessary to introduce a dead time during that incoming signals are ignored. It can be specified in multiples of timer 1 clocks. Only echoes after this time trigger a measurement. In practice this means you cannot measure a water surface that is closer than about 30 cm to the sensor.
Microcontroller
I used the Atmel ATtiny2313 at 3.6864 MHz.
This odd frequency allows error free generation of popular baud rates.
You should not choose the clock frequency too high since EMI problems
become more likely and the power consumption also rises nearly linear.
The 40 kHz-pulse is created in software. Since there are no interrupts enabled then this is safely possible and it is more easy to produce a fixed number of periods (8). A packet of eight periods takes 200 µs. At a speed of sound of approximately 340 m/s this makes 6.8 cm. A single period, what would be the theoretical limit of accuracy, equals 8.5 mm. After sending the packet, timer 1 is started to measure the travelling time. Since the receiver signal amplitude rises in the first two or three periods, sometimes the first period may be recognized and sometimes the second or even the third one. So the result may change in multiples of 8.5 mm. If the same period is recognized all the time, the resolution is very high (a timer period is less than 0.1 mm) but do not mistake this as precision!
The receiver circuit creates an edge for every single period of the signal. So the controller gets an exact time stamp of every single period and could even do doppler measurements what here is not necessary, of course.
If timer 1 overflows, the measurement is discarded. With direct system clock this would happen after 17,8 ms or 6 m. This can be too less, depending of the shape and size of the cistern (in my 6000 L-cistern, the sensor is about 2.90 m (thus 5.80 m forth and back) above the ground) so we start a second measurement with clk/8 then. If nothing is received, the timer will overflow after 142 ms. At last then the display unit gets the result.
Temperature Measurement
Since the speed of sound depends on temperature we have to measure it as well. This is not expensive but significantly improves precision. Unfortunately the controller does not have an ADC so we have to do this in software, too. Timer 1 is set up as 8-bit PWM and the output signal is filtered by a RC low pass. This voltage is compared with the voltage over a NTC. The PWM signal has a constant frequency of 14.4 kHz (3.6864 MHz/256).
The voltage over the capacitor of a RC circuit is determined by
the following formula:
V0 is the charging voltage (i.e. the difference between the voltage over
the capacitor at t=0 and the applied (constant) Voltage, it might also be a discharge
voltage), τ is the time constant
R×C.
τ is the time constant of the RC element, i.e. R×C.
As an aside, I'd like to note how nicely this works with the units: and . So, with R×C, A and V cancel each other out, leaving a time! And time t divided by R×C then results in a dimensionless number whose exponential function we can calculate.
The following transformation serves us well because it can be solved trivially for t or τ:
Two conditions must be fulfilled for the circuit to work:
- The peak-to-peak ripple voltage of the filtered PWM signal must be less than ½ LSB
- The settling time of the filtered voltage down to ½ LSB must be awaited.
Ripple voltage:
The highest ripple voltage is in the center of the range, at a duty cycle
of 50%.
The charging voltage in the steady state is ½ VCC.
For the ripple to remain below ½ LSB (V/V0=½/128)
the time constant of the filter must be more than 8.87 ms (t is half
of a period, 34,7 µs).
We choose values of 12 kΩ and 1 µF and thus
a time constant of 12 ms.
Settling time:
The highest settling time appears between 0 and 255. Since the largest
step we use is only from 0 to 128 we can calculate with V=127.5 and V0=128.
So for the voltage to stay within ½ LSB near the nominal value
of the PWM we have to wait at least 66.5 ms. We generously choose 100 ms.
We need 8 measurements for a software SAR converter so we get the exact result
after 800 ms.
We could reduce the settling time for successive steps since the voltage step is only half of the previous but this is not necessary here and not even desired.
This was quite a lot of work and is at least 1000 times slower than a hardware ADC would be but we will see later that this is not necessarily a disadvantage.
A note about tolerances: the absolute value of the RC circuit is not critical, not even the temperature coefficient is, since the temperature does not significantly change during a measurement. It is only important that the total minus tolerance does not exceed 26% (8.87 ms/12 ms) and the plus tolerance stays below 50% (100/66.5) what can easily be achieved with modern components (e.g. 20 % C and 5 % R).
It is not necessary to use precision resistors or capacitors, the cheapest you can get will fit (well, almost...)
Among my electronic calculators you can meanwhile find a calculator that makes it easy to determine the RC element.
The resistor R15 above the NTC should be a 1% type since its error directly influences the precision of the measurement. 1% resistors are still cheap. Higher precision soon becomes expensive without significantly improving the result since the tolerance of the NTC is much higher.
To reduce the influence of the driving power of the port pin we don't simply connect
the positive end of the resistor/NTC voltage divider to VCC but we use a port
pin of the same port (other ports may have a different driving power) which is
constantly 1
during the measurement and choose similar values for the
resistor over the NTC and the one over the capacitor so we get similar currents flowing.
Additionally this makes it possible to switch off the NTC if we don't need it.
This not only saves a little bit of power, it also reduces the self heating of
the NTC what again improves accuracy. At 2.5 V and 10 k this no
real problem but for a SMD-NTC having 220 K/W after all this
makes more than 1/8 °C.
I must confess, this part of the circuit was most fun for me. Simple to calculate, simple to build and works right straight away!
If you want to play around with it, here a tiny simulation for LTspice. I set the voltage of the PWM to 255 V so you can directly see the result of the DAC. The absolute value of the voltage does not matter for the function.
Housing
The housing for the sensor must be moisture proof. I decided for a Bopla ET-210. Temperature changes inducing the danger of dewing happen only very slowly inside the cistern but it cannot be excluded due to the low self heating of the sensor. Especially in cold seasons the sensor cools down from above whilst from the water surface relatively warm and humid air rises. So the cable feedthrough must be IP54 or better. I even applied silicone underneath the ultrasonic components to prevent humidity to enter through the drill holes. The sensors themselves are exposed to the humidity without mercy. There are moisture proof versions but they are hard to get. If you want, of course, you can try the underwater versions. The types UST40R and UST40S worked for several years in my cistern without problems.
Even small amounts of humidity in combination with dirt on the PCB (flux, skin oil) can cause corrosive and/or conductive coatings that lead to failure sooner or later.
After three years of working, the guy wire failed, the sensor dropped into the cistern and water soaked in. That's why I decided to pot the next version with epoxy. A circuit you can no longer get in touch with is better than one which is completely fucked up!
I decided for Robnor PX804D/BK. It looks like waste oil and is a bit more viscous than this. You will need about 200 g. Shake it a little bit after the first half to fill the hollows and thump it on the table a few times to make bubbles come up. Ideally you'd pot it in vacuum but for our purpose it's ok like this.
If you are considering vacuum potting, I would like to recommend refrigerator compressors. They are cheap (costing nothing from old fridges) and make an acceptable vacuum (down to 0.1 bar). Vacuum experts tend to laugh at this point but the bubbles in our case would shrink to a tenth of their size! Pot it, turn on the vacuum, wait for the bubbles to surface and turn off the vacuum before the resin starts to dry.
Furthermore, they work perfectly to inflate bicycle or car tyres.
Sensor Activation
The sensor power is switched in a fixed time pattern by the display.
This time pattern is a relict of a very early phase of this project and is not really an advantage now. But since it neither is a disadvantage I just kept it...
Second | Action |
0 | Reserved for booting If you are used to boot times of PCs a second may seem short but booting the display simply means initializing the tiny hardware and jumping to the main loop. |
1 | The sensor supply is powered on. The sensor permanently measures
temperature and travelling time and transmits the results to the
display. Every travelling time value received is presented live. The display averages 10 measurements (what approximately takes 10 seconds) and calculates the water volume. When the 10th measurement is received, the sensor is powered off. The display now shows the average value until the next minute. The sensor is switched off asynchronously. The time depends on the time necessary for 10 measurements, which itself depends on the travelling time of the ultrasonic pulse. Worst case would be 10 timeouts. The time is about 10 s. |
15 | The average values are calculated and written to the display. |
59 | Last error checks are done. If the number of measurements received
is not exactly 10, the appropriate error is displayed. The sensor power is switched off to ensure a sensor reset. |
This procedure may seem boring or bureaucratic but it avoids race conditions in a very simple way while leaving space for future extensions (provided that no more than 60 steps are needed). The controller does not waste cpu time in unnecessary wait loops for results. It could also be solved with a state machine but this would be more confusing and prone to software errors and would not be of any advantage in our case.
Sensor Protocol
The sensor is a very simple device and does not perform any calculations besides the temperature lookup table. Communication is always done spontaneously and in binary form with telegrams of 9-bit characters.
If the 9th bit is 0
, it is a data byte, if it is 1
it is a command
byte like this:
Command Byte | Answer | Data Bytes to follow |
0x00 | End of telegram | 0 |
't' | Temperature in °C/2. e.g. 3510 means
17.5 °C Raw-value of the software-SAR-converter |
1 1 |
'T' | Travelling time of the ultrasonic pulse in timer 1 clocks Multiplier for timer 1 in CPU clocks (1 or 8) Dead time in 256×timer1-clocks |
2 1 1 |
After each telegram (just before the 0x00-byte) a checksum byte is sent which calculates as the EOR of all data bytes and the first command byte.
Temperatures higher than 63.5 °C are reported as 63.5 °C, temperatures lower than -64°C as -64°C. The usable temperature range therefore is from -63.5 °C to +63 °C. Note that the maximum resolution is in the middle range (partly better than 0.5 °C) while on the margins of the range steps as large as 5.5 °C/LSB appear, what should not roll a dice at -64 °C...
If no echo has been received, the reported travelling time is 0.
The sensor continues making temperature and time measurements until the supply is switched off. By the way, the relatively long measuring time for the temperature (about 800 ms) of the software SAR converters ensures that all sound reflections in the cistern have died away. Using a fast hardware ADC we had to implement a delay loop here...
So the apparent disadvantage of a slow ADC proves to be useful. It's not a bug, it's a feature!
Initial Sensor Programming
For the initial programming the sensor via AVRISP the power has to be switched on
permanently. The most simple way to achieve this is using the
Calibrate-command.
Just press return until you get the message "Please enter the real Value for Switched Unreg".
The sensor will be powered on until you press return again and you can easily flash
the firmware using the AVRISP.
Note: the AVRISP will reset the sensor a few hundred milliseconds after it
is powered on. So the Update-Command
will fail as long as it is connected to the sensor! It costed me hours to
learn why the boot loader hello always appeared twice...
Fuses
When you program the sensor it is not sufficient to program only the
sensor flash memory. You have also take care of the fuses. Epecially the Clk/8-Fuse
has to be deactivated else the sensor will not run at 3.6864 MHz
but only at 461 kHz and thus no communication with the display would
be possible! The SELFPRGEN-fuse has to be set else a firmware update via
the boot loader would not be possible.
Test
Before you cast the sensor in epoxy you must at least test communication with the display. You should also try an Update-Command. Only if all that works you should consider casting the sensor and placing it in your cistern.
Mounting
If your cistern has a light-weight wooden cover of course you can simply mount it
with stainless steel screws but mine has a 50 kg concrete cover and I surely
would damage the sensor if I putted it aside. So I placed four hooks in the top
of the cistern, tore a stainless steel chain through them and hung the display on
it. Therefore I mounted a waste piece of PCB on the back of the sensor
(with stainless steel screws, of course) and
pulled the chain right through it.
On the photo, the sensor cable is still partly outside and not in its final position.