Software Page in English
Software Page in English

Software

Der Con­trol­ler läuft mit dem in­ter­nen 8 MHz RC-Os­zil­la­tor. Die Ge­nau­ig­keit ei­nes Quarz­os­zil­la­tors ist hier nicht er­for­der­lich da kei­ne a­syn­chro­nen Schnitt­stel­len (wie RS232) be­nutzt wer­den und auch kei­ne Echt­zeit­uhr re­a­li­siert wer­den muss.

Ein Quarz ist da­her auch auf der Lei­ter­plat­te nicht vor­ge­se­hen.

Programmierung

Den­ken Sie da­r­an, wäh­rend der Pro­gram­mie­rung des Con­trol­lers müs­sen Sie den Tas­ter ge­drückt hal­ten da die Pins dann in Hi-Z wech­seln und die Ver­sor­gung da­mit ab­ge­schal­tet wer­den wür­de. Der ge­drück­te Tas­ter sorgt für ei­ne per­ma­nen­te Ver­sor­gung der Schal­tung wäh­rend der Pro­gram­mie­rung.

Timer Interrupt

Timer 0 wird be­nutzt um wie­der­keh­ren­de Er­eig­nis­se (wie den Mul­ti­plex-Be­trieb des Dis­plays) zu re­a­li­sie­ren. Die In­ter­rupt-Rou­ti­ne wird da­bei 1000 mal pro Se­kun­de auf­ge­ru­fen. Bei 6 Digits macht dies ei­ne Re­fresh-Rate von 166 Hz. Sie er­laubt da­bei ei­ne Hel­lig­keits-Steu­e­rung in drei Schrit­ten. Dazu wird das Dis­play nur in ei­nem bis zu al­len drei von drei Zy­klen ein­ge­schal­tet (oder auch in kei­nem, Dis­play aus.) Da wir hier mit Bat­te­rien ar­bei­ten kann dies ver­wen­det wer­den um Strom zu spa­ren.

Da sich durch das Dim­ming die Re­fresh-Rate ent­spre­chend ver­rin­gert ist es nicht sinn­voll, mehr als drei Stu­fen zu er­mög­li­chen. Dabei ha­ben wir im­mer noch mehr als 55 Hz und da­mit ei­ne flim­mer­freie Dar­stel­lung.

Timer 0 be­treibt auch ei­nen Se­kun­den-Zäh­ler der be­nutzt wird um in den Power-Save oder Stand­by-Mo­dus zu wech­seln oder bei län­ge­rer In­ak­ti­vi­tät ganz ab­zu­schal­ten.

Die­ser ist je­doch nicht Be­stand­teil ei­ner Echt­zeit­uhr! Er wird zu ver­schie­de­nen Ge­le­gen­hei­ten auf 0 ge­setzt, haupt­säch­­lich um Time­outs zu re­a­li­sie­ren.

Bin6toBCD8

Da der AD-Wand­ler ei­nen 24-bit Bi­när­wert lie­fert ist ei­ne Rou­ti­ne nö­tig, die die­sen (nach der Um­rech­nung in kg) in ei­ne (ge­pack­te) BCD-Zahl um­wan­delt. Ge­packt heißt hier, dass in ei­nem Byte zwei Digits ent­hal­ten sind. Die BCD-Zahl passt da­her in ei­nen long-Wert. Das packed BCD kann an­schlie­ßend ganz leicht ins Dis­play-RAM der Sie­ben­seg­ment-An­zei­ge ge­schrie­ben wer­den.

Ich ha­be die­se Rou­ti­ne in As­sem­bler ge­schrie­ben da sie sich hier we­sent­lich ef­fek­ti­fer re­a­li­sie­ren lässt. In C gibt es kein Carry-Flag so dass die Schie­be-Ope­ra­tio­nen we­sent­lich auf­wän­di­ger wä­ren.

Das ge­wähl­te Ver­fah­ren kommt mit 24 Schie­be-Ope­ra­tio­nen, je­weils über al­le 7 Bytes, aus. Vor dem Schie­ben muss für je­des Digit (al­so für je­des Nib­ble des Er­geb­nis­ses) ge­prüft wer­den, ob es grö­ßer als 5 ist. Dann muss 3 ad­diert wer­den. Hier wur­de es so ge­än­dert, dass stets 3 ad­diert wer­den und falls es falsch war, drei wie­der sub­tra­hiert wird. Das er­gibt ei­nen klei­ne­ren Code, da das MSB je­des Nibb­les nur gann ge­setzt ist, wenn es grö­ßer als 5 war. Ist es nicht ge­setzt sub­tra­hie­ren wir die drei wie­der.

Ich hal­te hier al­le Wer­te in Re­gis­tern. Dies be­schleu­nigt die Aus­füh­rung, die be­trächt­lich dau­ern kann. Ich ver­wen­de aus­schließ­lich Re­gis­ter, die im AVR-GCC als vo­gel­frei gel­ten, al­so nicht auf dem Stack ge­si­chert wer­den müs­sen. Falls das auf­ru­fen­de Pro­gramm sie be­nut­zen wür­de, müss­te es selbst für die Si­che­rung vor und die Rück­si­che­rung hin­ter dem Auf­ruf sor­gen.

Wenn Sie ei­nen an­de­ren Com­pi­ler ver­wen­den kann das mög­li­cher­wei­se nicht so funk­tio­nie­ren und Sie müs­sen die Re­gis­ter evtl. vor­her si­chern!

Mei­ne Ver­sion be­nö­tigt al­so kein RAM und kei­nen Stack, lässt sich aber nicht so ein­fach auf grö­ße­re Da­ten­ty­pen er­wei­tern da nicht ge­nug freie Re­gis­ter ver­füg­bar sind.

Na­tür­lich sa­bo­tiert die­se Me­tho­de jeg­li­chen Por­ta­bi­li­täts-Ge­dan­ken. Nicht nur für an­de­re Ar­chi­tek­tu­ren, selbst für an­de­re AVR-De­ri­va­te müss­ten Sie da­r­ü­ber nach­den­ken um die­se Rou­ti­ne zu im­ple­men­tie­ren. Aber brau­chen wir das? Ei­gent­lich nicht! Es muss funk­tio­nie­ren, es muss schnell funk­tio­nie­ren und we­nig Strom ver­brau­chen. Tat­säch­lich ent­wick­le ich in mei­ner Pra­xis ge­ra­de die zehn­te Ver­sion ei­nes Mobile-Mo­dems und die elf­te ist be­reits an­ge­kün­digt. Kein Gerät hält heut­zu­ta­ge län­ger als zwei oder drei Jah­re. Ent­we­der wird ir­gend­ein Bau­teil ab­ge­kün­digt oder die An­for­de­run­gen stei­gen. Das si­chert zwar un­se­re Exis­tenz­grund­la­ge als Ent­wick­ler, macht aber häu­fig auch ein­fach kei­nen Spaß!

Power-Save-Modus

Wenn sich das Ge­wicht nicht we­sent­lich än­dert wird in den Power-Save-Mo­dus ge­wech­selt. Dabei wird das Dis­play schritt­wei­se ab­ge­dun­kelt um Strom zu spa­ren. Die Mes­sung läuft je­doch wei­ter.

Ändert sich das Ge­wicht wird wie­der in den Normal-Mo­dus ge­wech­selt und das Dis­play zeigt das Ge­wicht in vol­ler Hel­lig­keit.

Ändern heißt hier­bei mehr als 5 g Unter­schied zum Ge­wicht vor ei­ner Se­kun­de.

Abschaltung

Bei mehr als vier Mi­nu­ten In­ak­ti­vi­tät schal­tet sich das Gerät selbst ab. Erst da­mit ist die Zu­wie­ge­funk­tion ge­löscht und beim er­neu­ten Ein­schal­ten zeigt die Waa­ge 0 als Start-Ge­wicht an, un­ab­hän­gig da­von was tat­säch­­lich auf­liegt.

Wenn Sie tat­säch­­lich mehr als vier Mi­nu­ten be­nö­ti­gen und wei­ter mes­sen wol­len kön­nen Sie durch ei­nen kur­zen Druck auf den Wä­ge­tel­ler oder dem Tas­ter zum Normal-Mo­dus zu­rück­keh­ren und ha­ben er­neut vier Mi­nu­ten Zeit bis zur Ab­schal­tung.

Wenn kein nen­nens­wer­tes Ge­wicht auf­liegt (±5 g) er­folgt die Ab­schal­tung be­reits nach 15 s. Das dient der Bat­te­rie-Er­spar­nis und kann be­wusst ge­nutzt wer­den in­dem Sie am En­de der Mes­sung die Waa­ge auf Null stel­len.

Kalibrierung

Wird der Tas­ter für min­des­tens 10 s ge­drückt wech­selt die Waa­ge in ei­nen Ka­li­brier-Mo­dus. Das Dis­play zeigt dann CAL.

Nach Los­las­sen des Tas­ters kann der Be­nut­zer ei­nes der vor­de­fi­nier­ten Re­fe­renz­ge­wich­te aus­wäh­len. Durch Tas­ten­druck kann zum nächs­ten pas­sen­den ge­wech­selt wer­den.

Erst wenn län­ger als fünf Se­kun­den kein Tas­ten­druck er­folgt, gilt das ak­tu­ell an­ge­zeig­te Ge­wicht als ge­wählt. Sein Wert blinkt nun für drei Se­kun­den schnell um die Wahl an­zu­zei­gen.

Halten Sie nun die­ses Re­fe­renz­ge­wicht be­reit, wir brau­chen es bald! Wenn Sie sich hier ver­tan ha­ben, tren­nen Sie ein­fach die Strom­ver­sor­gung oder war­ten Sie ei­ne Mi­nu­te bis das Gerät sich selbst ab­schal­tet und nichts wird sich än­dern.

Das Gerät er­war­tet zu­nächst ei­nen lee­ren Wä­ge­tel­ler und zeigt dann don't touch (-touch). Da­rauf­hin wer­den 128 Mes­sun­gen vor­ge­nom­men um den Null­punkt zu er­mit­teln. Die Waa­ge mit­telt da­zu 128 Mes­sun­gen was et­wa 13 s dau­ert.

Ein (he­xa­de­zi­ma­ler) Count-Down-Zäh­ler, der im Wech­sel ein­ge­blen­det wird, gibt ei­nen vi­su­el­len Pro­gress-Bar der Mes­sung.

Das Dis­play zeigt da­nach rEF. Warten Sie bis da­hin. Be­rüh­ren Sie nicht den Wä­ge­tel­ler und ma­chen sie kei­nen un­nö­ti­gen Wind. All dies wür­de die Ka­li­brier-Ge­nau­ig­keit be­ein­träch­ti­gen. Legen Sie dann ein Re­fe­renz-Ge­wicht auf, dass 1 kg, 2 kg, 5 kg oder 10 kg wie­gen kann, wie Sie es vor­her aus­ge­wählt ha­ben. Ideal wä­ren 10 kg da dies ma­xi­ma­le Ge­nau­ig­keit er­ge­ben wür­de.

Auch hier mit­telt die Waa­ge über 128 Mes­sun­gen was wie­der­um et­wa 13 s dau­ert. Be­rüh­ren Sie in die­ser Zeit nicht den Wä­ge­tel­ler und ma­chen Sie kei­nen Wind. Drehen Sie kei­ne Hei­zung auf und öff­nen Sie kein Fens­ter!

Die Waa­ge zeigt das ge­mes­se­ne Ge­wicht an (was na­tür­lich dem tat­säch­­li­chen Re­fe­renz­ge­wicht ent­spre­chen soll­te) und es kann durch Tas­ten­druck ak­zep­tiert wer­den und wird da­mit im EEPROM als Re­fe­renz ge­spei­chert.

Wenn Sie hier­bei ei­nen Feh­ler ma­chen tren­nen Sie ein­fach die Strom­ver­sor­gung oder war­ten Sie ei­ne Mi­nu­te bis das Gerät sich ab­schal­tet und al­les bleibt wie es war und wie­der­ho­len Sie die Pro­ze­dur. Durch Auf­le­gen fal­scher Ge­wich­te kön­nen Sie die Ge­nau­ig­keit bis zur Un­brauch­bar­keit ver­fäl­schen.

Ins­be­son­de­re kann durch ei­ne fal­sche Wahl des Re­fe­renz­ge­wichts (z.B. Sie wäh­len 5 kg, le­gen aber nur 2 kg auf) ei­ne völ­lig un­sin­ni­ge Re­fe­renz ge­spei­chert wer­den.

Wenn Sie das an­ge­zeig­te Ge­wicht be­stä­ti­gen (und nur dann) wird es so­fort als Re­fe­renz im EEPROM ge­spei­chert und ist auch nach ei­nem Neu­start gül­tig.

Wenn an die­ser Stel­le kei­ne Be­stä­ti­gung er­folgt star­tet das Gerät nach ei­ner Mi­nu­te neu und al­les ist wie vor­her.

Umrechnung der Raw-Werte

Um das Ge­wicht aus ei­nem 24-Bit Raw-Wert mit 24-Bit-Ge­nau­ig­keit mit der simp­len For­mel <raw>ab in In­te­ger-Arith­me­tik zu be­­werk­stel­li­gen müs­sen wir min­des­tens mit 48-Bit-Zah­len rech­nen. Die AVR-Bi­blio­thek kennt den Typ int64_t so dass dies auch oh­ne Ver­wen­dung von Fieß­komma-Zah­len ein­fach mög­lich ist.

Auch bei der Ka­li­brie­rung ist es so ein­fach mög­lich, die Kom­po­nen­ten a und b zu be­rech­nen.

In­te­res­sant ist, dass die Be­rech­nung in int64 zwar we­sent­lich klei­ne­ren Code er­zeugt aber mit 285 µs rund drei­mal so lan­ge dau­ert wie die Be­rech­nung in double! Das liegt wohl da­r­an, dass double im AVR-GCC nur 32 Bit breit sind. 24 Bit Ge­nau­ig­keit wä­ren da­mit selbst in double wohl il­lu­so­risch!

Fil­te­rung der Mess­wer­te

Durch das Rau­schen des AD-Wand­lers ist sein Wert nicht di­rekt zur An­zei­ge ge­eig­net.

Zum Testen ha­be ich drei Me­tho­den ei­ner di­gi­ta­len Fil­te­rung im­ple­men­tiert:

Gleitende Mittelwertbildung

GetAVG1 ge­nannt in den Sour­cen. Mein ers­ter An­satz war ei­nen glei­ten­den Mit­tel­wert über die je­weils letz­ten 8 Mes­sun­gen zu bil­den.

Die­se Me­tho­de hat den Vor­teil, dass sich das Er­geb­nis li­ne­ar dem ak­tu­el­len Mess­wert an­nä­hert. Nach­tei­lig ist der ho­he Spei­cher­be­darf, da wir uns die letz­ten acht Mess­wer­te mer­ken müs­sen.

Tat­säch­lich ha­be ich so­gar noch ei­ne er­wei­ter­te Ver­sion re­a­li­siert, die 64 Wer­te mit­telt. Per Dop­pel­klick (al­so zwei Tas­ten­drü­cke in­ner­halb ei­ner Se­kun­de) kann zwi­schen 8 und 64 Wer­ten um­ge­schal­tet wer­den.

Das Dis­play zeigt nach ei­nem Dop­pel­klick kurz H1 oder L0 um den Hoch­auf­lö­sen­den oder schnel­len Mo­dus an­zu­zei­gen.

Der Nach­teil die­ser Me­tho­de ist der ho­he Spei­cher­be­darf. Die glei­ten­de Mit­tel­wert­bil­dung be­nö­tigt et­wa 100 Bytes mehr Flash und 256 Bytes mehr RAM als die nach­fol­gen­de:

IIR-Filter

Die zwei­te Me­tho­de, GetAVG2, be­rech­net das ak­tu­el­le Er­geb­nis le­dig­lich aus dem letz­ten Mess­wert, der um ei­ne Kon­stan­te stär­ker ge­wich­tet wird, und dem ak­tu­el­len Mess­wert, al­so nach der For­mel xi = xi-1 c+x c+1

Dies hat den Vor­teil ei­nes ge­rin­gen Spei­cher­be­darfs, auch für ho­he Wer­te von c, er­kauft mit dem Nach­teil dass sich der Wert nur mit ei­ner e-Funk­tion dem ak­tu­el­len Mess­wert an­nä­hert und da­mit, da wir hier nur mit Ganz­zah­len rech­nen, tat­säch­­lich nie­mals. Er kommt nur auf (c-1) an den Mess­wert he­r­an aber da die­ser rausch­be­haf­tet ist wird auch die­se Gren­ze über­wun­den so­fern das Rau­schen grö­ßer als c ist.

Aller­dings be­wirkt ge­nau die­se e-Funk­tion ein Ver­hal­ten, das dem ei­ner me­cha­ni­schen Waa­ge am nächs­ten kommt: man sieht ziem­lich schnell, wo­hin es geht aber dann wird der Zei­ger lang­sa­mer und bis man den ge­nau­en Wert hat muss man ein we­nig war­ten.

avgFactor

Ist die be­stim­men­de Grö­ße für GetAvg2(). Dies ist der Fak­tor, um den der letz­te Wert hö­her ge­wich­tet wird als der ak­tu­el­le Mess­wert. avgFactor wird we­sent­lich klei­ner sein als histSize beim glei­ten­den Mit­tel­wert da sich der Wert erst nach et­wa 12×avgFactor Mes­sun­gen sta­bi­li­siert.

Auch hier kann per Dop­pel­klick zwi­schen zwei Wer­ten um­ge­schal­tet wer­den, schnell (L0) oder Prä­zi­sion (H1).

Zum Ku­chen­ba­cken reicht LO (das auch nach dem Ein­schal­ten ein­ge­stellt ist) völ­lig aus da es hier­bei nicht auf 10 oder 100 mg an­kommt. Wenn Sie prä­zi­se mes­sen wol­len, schal­ten Sie mit dem Dop­pel­klick um.

FIR-Filter

Der drit­te An­satz war ein FIR SINC-Fil­ter, GetAvg3() ge­nannt. Die end­li­che Im­puls­ant­wort lie­fert auch nach end­li­cher Zeit ein sta­bi­les Si­gnal.

Ich ha­be zu­nächst den Rech­ner von Tom Roelands be­nutzt um die Ko­ef­fi­zi­en­ten zu be­rech­nen. (Cutoff-Fre­quen­cy 2 Hz, Tran­si­tion Band­with 3 Hz, Ham­ming-Fens­ter) und er­hielt ein Fil­ter mit 11 Ko­ef­fi­zi­en­ten.

Aller­dings kam mir des­sen Er­geb­nis su­spekt vor da der ers­te und letz­te Ko­ef­fi­zi­ent 0 war. Nun, ein an­de­rer Rech­ner bei TFilter lie­fer­te mir Er­geb­nis­se bei de­nen das nicht so war!

Ko­ef­fi­zi­en­ten ein­tra­gen ist ja nicht so kom­pli­ziert so ha­ben Sie in mei­nen Sour­cen bei­de Op­tio­nen und kön­nen da­mit ex­pe­ri­men­tie­ren.

Die Gret­chen­fra­ge: rei­chen 32 Bit für die Be­rech­nung? Nun, nicht prin­zi­pi­ell! Wenn al­le Ko­ef­fi­zi­en­ten 127 wä­ren und al­le 24-bit-Wer­te 8388607 de­fi­ni­tiv nicht. Aber die Ko­ef­fi­zi­en­ten sind nicht al­le 127. Sie sind Kon­stan­ten so­dass wir den ei­nen Mul­ti­pli­ka­tor ken­nen.

Die Sum­me der Ab­so­lut­wer­te ist 335 bzw. 361, so dass selbst bei knapp 6 Mio noch kei­nen Über­lauf er­zie­len wür­den.

Der Wand­ler lie­fert nur et­wa ±2 Mio Counts. Das Fil­ter funk­tio­niert auch mit 6 Mio noch oh­ne Über­lauf so­dass wir hier ge­nug Re­ser­ve ha­ben um die Be­rech­nung mit 32 Bits zu ris­kie­ren.

Die ist mei­ne ers­te Ein­schät­zung, die auch ex­pe­ri­men­tell funk­tio­nier­te. Da das FIR-Fil­ter je­doch kei­ne bes­se­ren Re­sul­ta­te lie­fer­te als das IIR ha­be ich es auch nicht wei­ter ver­folgt. Ich ha­be noch ei­nen FIR-Fil­ter mit 0.1 Hz pro­biert (bei dem TFilter ver­sag­te, je­doch Roelands ein Er­geb­nis brach­te) doch dies ist sub­jek­tiv nicht bes­ser als das ein­fa­che­re IIR-Fil­ter.

Auswahl der Fil­te­rung

Welche Me­tho­de sie be­vor­zu­gen müs­sen sie zur Com­pile-Zeit an­ge­ben in­dem Sie in scale.h USE_GetAvgx de­fi­nie­ren. Ei­ne Aus­wahl zur Lauf­zeit ist nicht vor­ge­se­hen. Ich ha­be mich in mei­nen Sour­cen für das IIR-Fil­ter ent­schie­den, aber es ist ja nur ei­ne Frage der #de­fines.

Bildung des Anzeigewertes

Der HX lie­fert 10 Mess­wer­te pro Se­kun­de. Selbst der ge­fil­ter­te Wert rauscht er­heb­lich und ist da­her nicht di­rekt zur An­zei­ge ge­eig­net. Die letz­ten zwei Digits wür­den nur un­ko­or­di­niert Flim­mern und könn­ten vom Be­nut­zer nicht er­fasst wer­den.

Daher wird nicht je­der er­rech­ne­te Wert di­rekt an­ge­zeigt son­dern wir bil­den er­neut ei­nen Mit­tel­wert über die letz­ten vier ge­fil­ter­ten Wer­te und zei­gen die­sen 2.5 mal pro Se­kun­de an.

Die­se Rate kann gut er­fasst wer­den und der Wert wird da­durch deut­lich ru­hi­ger.