Ultrasonic Level Meter Sensor Page in English
Ultrasonic Level Meter Sensor Page in English

Sensor

Sensor Der Sen­sor be­nutzt einen re­lativ klei­nen Con­trol­ler vom Typ ATtiny 2313. Um seine Ka­pa­zi­tät nicht un­nö­tig zu for­dern ist die Firm­ware in Assemb­ler ge­hal­ten (schließlich wollen wir auch das nicht ganz vergessen, oder?). Alle Be­rech­nun­gen wer­den in der An­zeige­einheit durch­ge­führt, die in C program­miert ist. Auch die Ver­sorgungs­span­nung des Sen­sors wird von die­ser fern­ge­schal­tet. En­ergie­ver­brauch ist daher nur am Ran­de ein Thema da er nur so­lange ein­ge­schal­tet ist wie er auch wirk­lich "ar­beiten" muss (in der ak­tuel­len Ver­sion ma­xi­mal 10 s pro Mi­nute).

Das bedeutet aber auch, dass er sich keine Werte im RAM merken kann. Alles was er dauer­haft wissen muss ist folglich im EEPROM abgelegt. Bis zum aktuellen Software­stand muss er sich glücklicher­weise *nichts* merken.

Ultraschallsender

Die Sender-Hardware ist die Stan­dard­schal­tung wie sie in vie­len An­wen­dun­gen ver­wen­det wird. Das Si­gnal in Form von 8 Pe­ri­oden ei­ner 40 kHz-Schwing­ung wird per Soft­ware im Mi­kro­control­ler er­zeugt. Ver­suche ha­ben ge­zeigt, dass das Emp­fangs­sig­nal wäh­rend der ersten 2-3 Pe­ri­oden deut­lich an­steigt (Re­so­nanz des Emp­fänger­kristalls und ver­mut­lich auch des Sen­ders). Mehr als 8 Peri­oden brin­gen je­doch keine we­sent­liche Ver­bes­ser­ung.

Ultraschallempfänger

Die Empfängerschaltung wurde in LTSpice simuliert und unter Berück­sich­ti­gung der Qua­li­tä­ten des ver­wen­de­ten Operations­ver­stär­kers auf ma­xi­ma­le Ver­stär­kung bei 40 kHz optimiert. Jede ein­zelne Peri­ode des emp­fangenen Ultra­schall­si­gnals löst im Con­trol­ler einen In­ter­rupt aus. Die­ser kann da­mit die Lauf­zeit des Im­pul­ses mes­sen und die Ent­fer­nung zur re­flek­tie­ren­den Ober­fläche be­rech­nen.

Schallgeschwindigkeit

Die Schall­geschwindigkeit ist abhängig von der Temperatur nach folgender Formel:
v=v_0*\sqrt{\frac{t}{t_0}}
wobei v0 die Geschwindig­keit bei 0 °C (331.5 m/s) und t0 =273 K ist.
10 °C würden einen Fehler von etwa 2.4% bewirken was etwa 140 l in einer 6000 l-Zisterne bedeutet.
Eine Temperatur­messung in der Zisterne ist damit obli­gatorisch. Aller­dings sollte man sich auch nicht zu viel davon ver­sprechen denn die Temperatur in der Luft­säule ist be­son­ders im Som­mer sehr in­ho­mo­gen. Scheint die Son­ne auf den Zis­ter­nen­deckel er­reicht die Luft­tem­pe­ra­tur im oberen Be­reich locker über 30 °C wäh­rend sie knapp über der Was­ser­ober­fläche nur 15 °C beträgt.

Es hat sich gezeigt, dass da­durch im Tages­verlauf schein­bare Wasser­zuläufe (auch ohne Regen) im Bereich von 30-50 l erfolgen weil sich der Schall in war­mer Luft schnel­ler aus­breitet und dadurch die Ober­fläche für den Sen­sor fer­ner scheint als sie tat­säch­lich ist.

Interes­santer­weise dehnt sich durch die Er­wär­mung auch das Edel­stahl-Befestigungs­seil und senkt da­mit den Sen­sor ein wenig ab, was die­sem Ef­fekt ent­ge­gen­wirkt.

Totzeit

Wenn Ultraschallimpulse ge­sen­det werden, emp­fängt der Sen­sor nicht nur das Echo von der Was­ser­oberfläche son­dern zu­nächst ein­mal Vi­bra­tio­nen, die über das Ge­häuse und die un­mit­telbare Um­ge­bung über­tragen wer­den. Des­halb ist es nö­tig, eine Tot­zeit ein­zu­füh­ren. Vor Ab­lauf die­ser wer­den emp­fangene Si­gnale ver­worfen. Sie kann in Viel­fachen von 256×Timer1-Clocks angegeben werden. Erst Echos nach Ablauf der Totzeit bewirken die Aus­lösung einer Messung. Praktisch bedeutet dies, dass kein Objekt und keine Wasser­ober­fläche gemessen werden kann, die näher als etwa 30 cm am Sensor ist.

Mikrocontroller

Verwendet wurde der ATTINY2313 bei einer Takt­frequenz von 3.6864 MHz. Diese 'krumme' Frequenz erlaubt das fehler­lose Er­zeugen gängiger Baud­raten.
Unnötig hoch soll­te man die Takt­frequenz nicht wäh­len, da EMV-Probleme da­mit wahr­schein­li­cher wer­den und auch der Strom­ver­brauch prak­tisch li­near mit der Takt­frequenz an­steigt.

Die 40 kHz-Schwingung wird rein durch Soft­ware erzeugt. Da beim Senden keine Inter­rupts freigegeben sind ist dies möglich und es ist so ein­facher, eine bestimmte Anzahl von Perioden (8) zu erzeugen. Ein Paket aus 8 Perioden ist 200 µs lang, bei rund 340 m/s Schall­geschwin­digkeit entspricht das 6,8 cm. Eine einzelne Periode und damit die theo­retische Maximal­grenze der Genauig­keit ent­spricht 8,5 mm. Nach dem Senden des Pakets wird Timer 1 ge­star­tet, mit dem die Laufzeit gemessen wird. Da, wie be­reits er­wähnt, das Emp­fangs­signal während der ersten Peri­oden ansteigt kann es pas­sieren, dass mal die erste und mal die zweite oder gar dritte Periode er­kannt wird und das Er­gebnis so sprunghaft um Vielfache von 8.5 mm steigen oder fallen kann. Für den Fall dass immer die gleiche Periode erkannt wird ist die Auf­lösung allerdings sehr hoch (eine Timerperiode entspricht weniger als 0.1 mm) was aber nicht mit Genauigkeit verwechselt werden darf!

Der Empfänger liefert für jede Periode des Pakets eine Flanke, die einen Input-Capture-Inter­rupt auslöst. Der Con­trol­ler hat da­mit einen exakten Zeit­stem­pel jeder ein­zelnen Periode und könnte so sogar Doppler­mes­sungen vor­nehmen, was hier aber nicht nötig ist.

Wenn Timer 1 über­läuft wird die Mes­sung verworfen. Dies wäre bei direktem Systemtakt nach 17,8 ms oder 6 m. Da dies je nach Form und Fassungs­vermögen der Zisterne etwas knapp sein kann (in der 6000 L-Zisterne des Autors hängt der Sensor etwa 2,90 m (also 5,80 m hin und zurück) über dem Boden) messen wir in diesem Fall noch einmal mit clk/8. Wird kein Signal empfangen läuft der Timer also nach weiteren 142 ms ab. Spätestens dann be­kommt die Anzeige­einheit auch die In­for­mation über die Lauf­zeit des Si­gnals.

Temperaturmessung

Da die Schall­ge­schwin­dig­keit temperatur­ab­hängig ist muss auch die Tem­pe­ra­tur gemes­sen wer­den. Das kostet nicht viel, bringt aber, wie wir ge­sehen haben, einen deut­lichen Ge­nauig­keits­gewinn. Der Controller besitzt unglücklicher­weise keinen AD-Wandler so wurde auch dieser in Soft­ware realisiert. Dazu wird Timer 1 als 8-Bit PWM betrieben und das Ausgangs­signal durch einen einfachen RC-Tiefpass gefiltert. Diese Spannung wird vom inte­grierten Komparator mit der über einem NTC verglichen. Das PWM-Signal hat dabei eine feste Frequenz von 14.4 kHz (3.6864 MHz/256).

Ausgehend von einem ent­la­denen Kon­den­sator lautet die For­mel für den Span­nungs­ver­lauf an einem RC-Glied bekannter­maßen:
U(t)=U_0*(1-e^{-\frac{t}{\tau}})
U0 ist dabei die Lade­spannung, τ ist die Zeit­kon­stante also R×C.
Folgende Umformung tut uns dabei gute Dienste da sie sich trivial nach t bzw. τ auflösen lässt:
-\ln(1-\frac{U}{U_0})=\frac{t}{\tau}
Zwei Rand­be­dingungen müssen für die kor­rekte Funk­tion der Mes­sung erfüllt sein:

  1. Die Rest­wel­lig­keit des ge­fil­terten PWM-Si­gnals muss klei­ner sein als ½ LSB
  2. Die Ein­schwing­zeit der ge­fil­ter­ten Span­nung bis auf ½ LSB muss abge­war­tet werden

Restwelligkeit:
Die höchste Rest­wel­lig­keit ist in der Mit­te des Mess­be­reichs, bei 50 % Duty Cycle.
Die Lades­pan­nung ist im einge­schwungenen Zu­stand ½ VCC. Damit die Restwel­ligkeit des Signals unter ½  LSB (U/U0=½/128) bleibt muss die Zeit­kon­stan­te des Fil­ters über 8,87 ms lie­gen (t ist hier eine hal­be Pe­ri­oden­dauer, also 34,7 µs).
Wir wählen Werte von 12 kΩ und 1 µF und damit eine Zeit­kon­stan­te von 12 ms.

Einschwingzeit:
Die höchste Ein­schwingzeit ist zwi­schen den Ex­trema, d.h. von 0 auf 255. Da der höchste Schritt, den wir ab­war­ten müs­sen, je­doch nur von 0 auf 128 ist rech­nen wir nun mit u=127,5 und u0=128. Damit die Span­nung auf we­ni­ger als ½ LSB an den PWM-Sollwert heran­kommt muss das Signal also wenigstens 66,5 ms anstehen. Auch hier wählen wir großzügig 100 ms. Für einen Software-SAR-Wandler mit 8 Bit benötigen wir 8 Messungen und erhalten somit nach etwa 800 ms das genaue Ergebnis.

Wir könnten die Einschwing­zeit für die folgenden Schritte redu­zieren da der Spannungs­hub jeweils nur die Hälfte des vorher­gehenden ist aber das ist hier nicht nötig und auch nicht er­wünscht.

Das war ziem­lich viel Ar­beit und ist min­des­tens 1000 mal lang­samer als ein in­te­grier­ter Har­dware-A/D-Wand­ler aber wie wir spä­ter noch sehen wer­den ist dies nicht un­be­dingt ein Nach­teil.

Eine An­mer­kung zu den Bau­teil­to­le­ran­zen: der ab­so­lu­te Wert des RC-Gliedes ist unkritisch, selbst der Temperatur­koeffizient, da sich die Temperatur im Laufe einer Messung nicht wesent­lich ändert. Entscheidend ist lediglich, dass die gesamte Minus-Toleranz nicht mehr als 26 % (8.87 ms/12 ms) und die Plus-Toleranz nicht mehr als 50 % (100/66,5) beträgt, was mit modernen Konden­satoren und Wider­ständen durchaus einzuhalten ist (etwa mit 20 % C und 5 % R).

Es ist also nicht nötig, besonders hochwertige Widerstände oder Konden­satoren einzusetzen, das bil­ligste was Sie kriegen können ist gut genug (na ja, jeden­falls fast)...

Der Widerstand R15 über dem Heißleiter sollte jedoch ein 1 %-Typ sein, da sein Fehler direkt in die Genauigkeit der Messung eingeht. 1 %-Widerstände sind immer noch billig. Eine noch höhere Präzision geht schnell ins Geld und brächte kaum Verbes­serung da die Toleranz des Heiß­leiters viel größer ist.

Um Ver­fälschungen des Ergeb­nisses durch die Treiber­leistung des Portpins zu ver­ringern legen wir das positive Ende des Widerstand/Heißleiter-Spannungs­teilers nicht an VCC sondern ebenfalls an einen Portpin des selben Ports (andere mögen abweichende Treiber­leistung haben) der während der Messung permanent "1" ist und verwenden für den Wider­stand des RC-Gliedes einen ähnlichen Wert wie für den Vorwider­stand des Heiß­leiters, so dass ähnliche Ströme fließen. Dies hat zusätz­lich den Vorteil, dass wir den Heiß­leiter abschalten können wenn wir ihn nicht benötigen und so nicht nur ein bisschen Strom sparen sondern auch die Eigen­erwärmung des Heißleiters reduzieren. Diese ist zwar bei 2.5 V und 10 kΩ noch kein echtes Problem, beträgt jedoch beispiels­weise bei einem SMD-NTC mit 220 K/W schon mehr als 1/8 °C.

Ich muss gestehen, dieser Teil der Schaltung hat mir am meisten Spaß gemacht. Einfach zu berechnen, einfach zu bauen und funk­tioniert auf Anhieb!

Wenn Sie mal damit spielen möchten, hier eine kleine Simulation für LTSpice. Die Spannung der PWM habe ich hier auf 255 V gesetzt. So kann man direkt das Ergebnis des DA-Wandlers überprüfen. Für die Funktion ist ja der absolute Wert der Spannung uner­heblich.

Gehäuse

Das Gehäuse für den Sensor sollte auf jeden Fall feuchtigkeits­geschützt sein. Ich habe ein Bopla ET-210 verwendet. Temperatur­änderungen und damit die Gefahr der Betauung erfolgen zwar in einer Zisterne nur sehr langsam, können aber durch die geringe Eigen­erwärmung des Sensors nicht völlig ausge­schlossen werden. Insbe­sondere in der kalten Jahres­zeit kühlt der Sensor von oben aus während von unten relativ feucht-warme Luft aufsteigt. Auch die Ein­führung des Kabels sollte deshalb durch eine feuchtigkeits­dichte IP54-Kabeleinführung erfolgen. Ich habe sogar unter die Ultraschall-Sensoren noch Silikon gespritzt um das Ein­dringen von Feuchtig­keit durch die Bohr­löcher zu verhindern und kann dies aufgrund späterer Erfah­rungen nur dringend emp­fehlen! Die Sensoren selbst sind der Feuchtig­keit jedoch schonungslos ausge­liefert. Es gibt auch feuchtigkeits­beständige Ultraschall­sensoren, diese sind jedoch schlecht erhältlich. Bei Befürchtungen in dieser Richtung kann natürlich auch die Unterwasser-Ausführung heran­gezogen werden. Ich habe die Unterwasser-Ausführung nur kurz getestet, es scheint jedoch, dass diese eine erheblich höhere Treiberleistung erfordern. Sie würden jedenfalls nicht ohne Schaltungs­modifikation funktionieren. Hier sind Sie gefragt!

Die Typen UST40R und UST40S haben jedoch mehrere Jahre unbe­schadet über­standen.

Auch geringe Mengen Feuchtigkeit können zusammen mit Verun­reinigungen auf der Leiter­platte (Flussmittel, Hautfett etc.) korrosive und/oder leitfähige Beläge bilden, die früher oder später zum Ausfall führen.

Nach etwa drei Jahren Betrieb riss bei meinem Sensor das Halte­seil, der Sensor fiel in die Zis­terne und saugte sich mit Wasser voll. Deshalb entschied ich mich, den nächsten komplett mit Epoxyd­harz zu vergießen. Eine Schaltung an die man nicht mehr heran­kommt ist besser als eine kaputte Schaltung!

Dafür habe ich Robnor PX804D/BK verwendet. Es sieht aus wie Altöl und ist etwas zähflüssiger als dieses. Man benötigt etwa 200g. Nach der halben Menge etwas Schwenken damit auch die Hohlräume ausgefüllt werden. Zum Schluß mit dem Gerät ein paar mal auf den Tisch klopfen damit die Luftblasen aufsteigen. Ideal wäre natürlich der Verguß im Vakuum aber für unsere Zwecke geht es auch so.

Sensor-Ansteuerung

Der Sensor wird in einem festen Zeit­raster einmal pro Minute ange­steuert.
Dieses Zeitraster stammt aus einer frühen Entwicklungs­phase des Projekts und ist in seinem jetzigen Stand kaum von Vorteil. Da es aber auch nicht von Nachteil ist wurde es einfach bei­behalten...

Sekunde Aktion
0 Reserviert für Boot-Vorgang
Wer Bootzeiten von PCs gewöhnt ist mag eine Sekunde für kurz halten aber Booten beschränkt sich bei der Anzeige auf das Initiali­sieren der beschei­denen Hardware und das Anspringen der Haupt­schleife.
1 Die Stromversorgung wird eingeschaltet. Der Sensor führt daraufhin selbst­tätig asynchron Temperatur- und Laufzeit­messungen durch und sendet die Ergeb­nisse an die Anzeige.
Jede empfangene Laufzeit­messung wird als Füll­stand "live" angezeigt.

Die Anzeige mittelt 10 Laufzeitmessungen (was grob auch etwa 10 Sekunden dauert) und errechnet daraus die Füll­menge der Zisterne. Mit dem Erhalt der 10. Messung schaltet sie die Ver­sorgung wieder ab. Die Anzeige zeigt nun bis zur nächsten Minute den gemit­telten Wert.

Die Abschaltung erfolgt asynchron, sie hängt ab von der tat­sächlich benötigten Zeit für 10 Messungen, die ja von der Lauf­zeit des Signals bzw. schlimmsten­falls vom Timeout derselben abhängt. Die benötigte Zeit liegt bei 'etwa' 10 Sekunden.

15 Die Mittelwerte werden berechnet und auf die Anzeige geschrieben.
59 Letzte Fehlerchecks werden durch­geführt. Wenn die Anzahl der emp­fangenen Laufzeit­messungen nicht genau 10 ist wird der ent­sprechende Fehler angezeigt.
Die Stromversorgung wird abgeschaltet um einen sicheren Reset auszu­lösen.

Dieses Verfahren mag langweilig oder büro­kratisch erscheinen, es verhindert jedoch auf einfache Weise das Zustande­kommen von Race-Conditions und lässt doch Raum für Erweiter­ungen (sofern nicht mehr als 60 Schritte benötigt werden). Der Sensor hat auf jedes Kommando eine knappe Sekunde Zeit und kann sicher sein, nicht gestört zu werden. Zusätzlich ver­schwendet der steuernde Controller keine CPU-Zeit in unnötigen Warte­schleifen auf Ergebnisse. Man könnte dies auch ohne das starre und träge Zeit­raster mit einer State-Machine lösen, diese wäre jedoch unüber­sichtlicher und damit fehler­trächtiger und brächte im konkreten Fall keine Vorteile.

Sensorprotokoll

Der Sensor ist vergleichsweise einfach aufgebaut und führt, abgesehen von der Temperatur-Lookuptable keine Berech­nungen durch. Er kommuniziert grund­sätzlich binär und spontan mit Tele­grammen im 9-Bit-Format.

Ist das 9. Bit "0" handelt es sich um ein Daten­byte, bei "1" um ein Kennbyte wie folgt:

Kennbyte Antwort Datenbytes folgen
0x00 Ende des Datensatzes 0
't' Temperatur in  °C/2. So entspricht z.B. 3510 einer Temperatur von 17.5 °C
Raw-Wert des Software-SAR-Konverters
1
1
'T' Laufzeit des Ultraschall­impulses in Timer1-Clocks
Multiplikator für Timer1 in CPU-Clocks (1 oder 8)
Totzeit in 256×Timer1-Clocks
2
1
1

Nach jedem Datensatz (vor dem 0x00-Byte) wird ein Checksummen-Byte gesendet, das sich aus der Exklusiv-Oder-Verknüp­fung der Daten und des ersten Kenn­bytes errechnet.

Temperaturen größer 63.5 °C werden als 63.5 °C, solche kleiner als -64 als -64 gemeldet. Der auswertbare Temperatur­bereich ist daher von -63.5 °C bis +63 °C. Es bleibt anzumerken, dass die Auf­lösung in der Mitte des Mess­bereichs am größten ist (teilweise besser als 0.5 °C) während am Rande des Mess­bereichs Sprünge von bis zu 5,5 °C/ LSB vorkommen, was bei -64 °C aber keine Rolle mehr spielen dürfte...

Wurde kein Echo empfangen ist die Laufzeit 0.

Der Sensor führt kontinu­ierlich Mes­sungen durch bis die Versorgungs­spannung abgeschaltet wird. Die relativ lange Messzeit von etwa 800 ms des Software-AD-Wandlers für die Temperatur sorgt nebenbei auch dafür, dass alle Ultra­schall-Echos in der Zisterne verklungen sind. Mit einem schnellen Hardware-ADC an Bord müssten wir an dieser Stelle eine Warte­schleife einfügen...

So erweist sich der vermeintliche Nachteil der langsamen AD-Wandlung durch den Software-SAR als nützlich (getreu dem Motto "It's not a bug, it's a feature!")

Programmierung des Sensors

Zur erstmaligen Program­mierung des Sensors mit dem AVRISP ist es erforder­lich dass die Sensor-Versorgung per­manent einge­schaltet ist. Die einfachste Methode dies zu erreichen ist über das Kommando Calibrate. Drücken Sie Return bis die Meldung "Please enter the real Value for Switched Unreg" erscheint. Der Sensor ist an bis sie erneut Return drücken und Sie können ihn ganz normal mit dem AVRISP program­mieren.
Hinweis: das AVRISP bewirkt einen Reset des Sensors einige 100 ms nachdem die Sensor-Versorgung eingeschaltet wird. Ein Update-Kommando wird folglich fehlschlagen solange das AVRISP mit dem Sensor verbunden ist! Es hat mich Stunden gekostet heraus­zufinden, warum das Bootloader-Hello immer zweimal kam...

Fuses

Programming Window Wenn Sie den Sensor pro­gram­mieren reicht es nicht, nur das Sensor­programm selbst zu pro­gram­mieren! Achten Sie auch auf die Fuses. Ins­besondere die Clk/8-Fuse muss de­aktiviert sein da sonst der Sensor nicht mit 3.6864 MHz läuft son­dern nur mit 461 kHz und damit keine Kommuni­kation mit dem Display möglich ist! Ebenso muss die SELFPRGEN-Fuse gesetzt sein sonst ist kein Firmware-Update über den Boot­loader möglich.

Test

Bevor Sie den Sensor ver­giessen, testen Sie un­bedingt die Kommuni­kation mit dem Display. Versuchen Sie auch, ein Update-Kommando. Erst wenn alles Funk­tioniert sollten Sie es riskieren, den Sensor in der Zisterne zu 'versenken' (bitte nicht wört­lich nehmen :-)).

Befestigung

Sensor mountedWenn Ihre Zisterne einen leichten Holz­deckel hat können sie ihn na­tür­lich ein­fach mit Edelstahl­schrauben daran be­festigen. Meine hat einen 50 kg-Beton­deckel und ich würde den Sensor sicher zer­stören wenn er einfach unten fest­geschraubt wäre und ich den Deckel zur Seite wuchte.
Ich habe in den Zisternen­hals vier Edel­stahl-Haken geschraubt, eine Edel­stahl­kette durch sie ge­spannt und den Sensor befestigt. Dazu habe ich auf das Sensor-Gehäuse ein Reststück Lochrasterplatte befestigt (natürlich mit Edel­stahl­schrauben) unter dem ich die Kette gespannt habe. Auf dem Foto ist das Sensor-Kabel noch teilweise außerhalb der Zisterne und damit nicht in seiner entgültigen Lage.