Hallo zusammen! Ich habe eine etwas ungewöhnliche Frage, die man eigentlich auch garnicht richtig beantworten kann - es geht mir vielmehr um eine ungefähre Einschätzung von Leuten, die schon länger mit uCs arbeiten und ggf. schonmal ähnliche Projekte realisiert haben. Ich möchte einen Drucksensor bauen mit einem DMS. Als Ausgang soll ein 4-20mA-Signal herauskommen. Das ganze Konstrukt soll 4 7-Segment-Anzeigen haben und über zwei Taster bedienbar sein. Der Mikrocontroller, der mir momentan vorschwebt, ist einer mit 2k FLASH und 128Byte RAM. Ich hätte gerne mal eine Einschätzung, ob mein Vorhaben in so einen Controller passen könnte, oder ob man es gleich vergessen kann. Zum Programm: ------------- ADC einlesen bisschen mitteln zur Messwertberuhigung bisschen Rechnerei (natürlich alles fixed point und ohne Multiplikation / Division) Analogausgabe mittels PWM (Hardware) Anzeige des Messwertes über die 7-Segment-Anzeigen (multiplex über Schieberegister, welche am SPI-Port des uCs hängen) kleines Menü, in welchem Einstellungen über die Tasten gemacht werden können ------------------------------------------------------------------------ -- Ich habe soweit schon fast alles am laufen, bis auf das Menü (hier kommen eigentlich noch ein paar Funktionen zum Verstellen hinzu), sowie eine gute Mittelung für die Messwerte...die fehlt auch noch. Einfach einen Mittelwert über die letzten 8, 16 oder was auch immer ist nicht so schön im Ergebnis, da hätte ich lieber einen gleitenden Mittelwert, aber der schluckt halt Speicher UND DER IST RAR. Momentan belege ich ca. 1300 Byte Daten, da ist noch ein bisschen Platz, aber das RAM ist schon zu 96Byte ausgenutzt. Dann noch 20Byte Flash mit Konstanten. Was meint ihr, ist das einfach zuviel, für so einen kleinen Prozessor? Jetzt nicht von der Leistung :) sondern vom Platz? Würdet ihr für sowas einen größeren nehmen? Ich habe mich für den entschieden, weil er einen 16Bit differentiellen Wandler drin hat, der einiges an Analog-Front-End spart (auch wenn der die vollen 16Bit nicht hergibt). Trotzdem kann ich mit ner einfachen Verstärkerstufe direkt an den ADC gehen. Wäre mal über Erfahrungswerte von Euch erfreut. Ich weiß, dass die Frage so nicht direkt beantwortet werden kann, aber ein paar Meinungen wären toll. Kommt ja immer auf die Qualität der Programmierung an. Gruß
Die 2 K Flash Speicher für das Programm könnte schon knapp werden, so wie es aussieht, steht es da aber gar nicht so schlecht. Die 128 Bytes an RAM sollten eigentlich reichen - es hängt aber sehr davon ab wie viel der µC bzw. Compiler davon für den Stack braucht. Wenn der Speicher für einen echten Gleitenden Mittelwert nicht reicht, kann man auch erst normal mitteln, und dann das gleitend nur noch mit 4 Einträgen machen. Das sollte schon reichen damit man keine so großen Sprünge bekommt. Sonst ist es eher besser erst einen µC mit etwas mehr Flash-Speicher einzuplanen - beim ersten Exemplar kommt es auch 1 EUR mehr eigentlich nicht an. Der RAM Bedarf lässt sich eigentlich relativ gut vorher abschätzen. Bei einem so kleinen Programm, das offensichtlich nicht Zeitkritisch ist, gibt es auch die Möglichkeit erst das Programm zu schreiben, und sich dann erst auf das genaue µC Modell festzulegen - mit einem Compiler ist das oft noch eine kleine Änderung.
Wie hast du bis jetzt Programmiert? Wele sprache? Um welche CPU geht es? In 2k bekommt man schon eine menge rein, das sollte hier bequem reichen. Ein gleitender Mittelwert über 8 Werte kostet doch auch nur 8x8byte ram. flash so gut wir gar nicht. du Rechnest einfach jeden wert/8 und speicherst ihn in einem array mit der größe 8. Den aktuellen wert kannst du duch die summe dieser 8werte ermitteln.
Vielen Dank schonmal für eure schnellen Antworten! Ulrich schrieb: > Die 2 K Flash Speicher für das Programm könnte schon knapp werden, so > wie es aussieht, steht es da aber gar nicht so schlecht. Die 128 Bytes > an RAM sollten eigentlich reichen :-) Irgendwie habe ich es hier genau anders herum vorliegen. Ulrich schrieb: > es hängt aber sehr davon ab wie viel > der µC bzw. Compiler davon für den Stack braucht Was ist denn die beste Variante, um den klein zu halten? Also ich habe z.B. schon bemerkt (ich probiere hier ja schon an etlichem rum), dass allein der Zugriff auf eine Funktion erheblich viel Speicher frisst. Ich hatte z.B. eine io_functions.c, in der ich einen Portpin für den Latch der Schieberegister getoggled habe. Aufgerufen halt durch io_toggle_latch(); In der Funktion stand nichts weiter, als "PORTPIN HIGH; PORTPIN_LOW". Diese beiden Anweisungen habe ich mal direkt an die Stelle gesetzt, wo die Funktion aufgerufen wurde...Speicherplatzersparnis: gut 20Byte. Ulrich schrieb: > Wenn der Speicher für einen echten Gleitenden Mittelwert nicht reicht, > kann man auch erst normal mitteln, und dann das gleitend nur noch mit 4 > Einträgen machen. Stimmt. Werde ich probieren. Ulrich schrieb: > Sonst ist es eher besser erst einen µC mit etwas mehr Flash-Speicher > einzuplanen Klar, sind nur nicht so viele mit 'nem differentiellen ADC vorhanden. War halt praktisch. Ulrich schrieb: > Bei einem so kleinen Programm, das offensichtlich nicht Zeitkritisch > ist, gibt es auch die Möglichkeit erst das Programm zu schreiben, und > sich dann erst auf das genaue µC Modell festzulegen So mache ich es auch, aber wie gesagt, der ADC ;-) Peter II schrieb: > Wie hast du bis jetzt Programmiert? Was genau meinst du damit? Habe zumindest jede Division / Multiplikation vermieden (durch Additionen / Subtraktionen ersetzt), habe keine Fließkommarithmetik drin und vergleiche oft, welche Variante weniger Speicher verbraucht. Peter II schrieb: > Wele sprache? Um welche CPU geht es? C, MSP430F2013, IAR Embedded Workbench Peter II schrieb: > Ein gleitender Mittelwert über 8 Werte kostet doch auch nur 8x8byte ram. > flash so gut wir gar nicht. > > du Rechnest einfach jeden wert/8 und speicherst ihn in einem array mit > der größe 8. Den aktuellen wert kannst du duch die summe dieser 8werte > ermitteln. Auch ein guter Vorschlag, danke. Gruß
> dass allein der Zugriff auf eine Funktion erheblich viel Speicher frisst.
Hast Du mal einen release -Build gemacht? Dann dürfte der Optimierer
so einiges an Code einsparen können, und der von IAR ist so schlecht
nicht.
> Momentan belege ich ca. 1300 Byte Daten, da ist noch ein bisschen > Platz, aber das RAM ist schon zu 96Byte ausgenutzt. Dann noch > 20Byte Flash mit Konstanten. Kommt mir aus dem Bauch heraus trotzdem etwas heftig vor, bei dieser Funktionalität > ADC einlesen > bisschen mitteln zur Messwertberuhigung > bisschen Rechnerei (natürlich alles fixed point und ohne > Multiplikation / Division) > Analogausgabe mittels PWM (Hardware) > Anzeige des Messwertes über die 7-Segment-Anzeigen (multiplex > über Schieberegister, welche am SPI-Port des uCs hängen) Hast du auf Datentypen geachtet? Immer den kleinsten Datentyp nehmen, der gerade noch ausreicht. Nicht dem µC unnötig 16 Bit Arithmetik aufzwingen, wenn es 8 Bit auch tun? > Habe zumindest jede Division / Multiplikation vermieden > (durch Additionen / Subtraktionen ersetzt), Das kann auch kontraproduktiv sein. Multiplikation ist meistens sowieso kein Problem und Division geht eher in die Laufzeit als in die Codegröße.
Karl Heinz Buchegger schrieb: > Nicht dem µC unnötig 16 Bit Arithmetik > aufzwingen, wenn es 8 Bit auch tun? Das ist ein MSP430, für den stellt das kein Mehraufwand dar.
Rufus Τ. Firefly schrieb: > Hast Du mal einen release -Build gemacht? Nein, bis dato nicht. Karl Heinz Buchegger schrieb: > Hast du auf Datentypen geachtet? Schon. An manchen Stellen brauche ich halt mal einen int32 oder ähnliches, damit ich mir Prozente mit zwei Nachkommastellen vor das Komma holen kann, um nicht zuviel Genauigkeit zu verlieren. Dann halt ein paar Berechnungen damit, dann wird die Zahl schonmal größer. Karl Heinz Buchegger schrieb: > Das kann auch kontraproduktiv sein. Multiplikation ist meistens sowieso > kein Problem und Division geht eher in die Laufzeit als in die > Codegröße. Ich habe immer parallel einmal die Multiplikation/Division regulär und dann zum Vergleich mit reiner Addition/Subtraktion - immer war letztere Variante etwas kleiner. Hier mal mein Code zum Multiplizieren/Teilen:
1 | int32_t divide_multiply_number( uint8_t operand, |
2 | int32_t source_number, |
3 | int32_t div_multi ) |
4 | {
|
5 | int32_t div_multi_number = 0; |
6 | uint8_t sign = 0; |
7 | |
8 | if( (source_number == 0) || (div_multi == 0) ) |
9 | {
|
10 | return 0; |
11 | }
|
12 | |
13 | if( source_number < 0 ) |
14 | {
|
15 | sign |= 0x01; |
16 | source_number = ( source_number - (source_number + source_number)); |
17 | }
|
18 | |
19 | if( div_multi < 0 ) |
20 | {
|
21 | sign |= 0x02; |
22 | div_multi = (div_multi - (div_multi + div_multi)); |
23 | }
|
24 | |
25 | if( operand == MULTIPLY ) |
26 | {
|
27 | while( div_multi ) |
28 | {
|
29 | div_multi_number += source_number; |
30 | div_multi--; |
31 | }
|
32 | }
|
33 | else if( operand == DIVIDE ) |
34 | {
|
35 | for( div_multi_number = 0; |
36 | source_number >= div_multi; |
37 | source_number -= div_multi ) |
38 | {
|
39 | div_multi_number++; |
40 | }
|
41 | }
|
42 | |
43 | if( (sign == 1) || (sign == 2) ) |
44 | {
|
45 | return (div_multi_number - (div_multi_number + div_multi_number)); |
46 | }
|
47 | |
48 | return div_multi_number; |
49 | }
|
Wo der Stack halt direkt 26Byte verbraucht, ist wenn ich diese Funktion in sich selber nochmal aufrufe:
1 | // in der main
|
2 | |
3 | ...
|
4 | test = calc_percent_times_hundred_of_adc_span( adc_control.adc_result ); |
5 | ...
|
6 | |
7 | |
8 | // die Funktion "calc_percent_times_hundred_of_adc_span"
|
9 | |
10 | int16_t calc_percent_times_hundred_of_adc_span( uint16_t adc_value ) |
11 | {
|
12 | return divide_multiply_number( DIVIDE, |
13 | (divide_multiply_number( MULTIPLY, |
14 | adc_value - adc_control.adc_lower_value, |
15 | 10000 )), |
16 | adc_control.adc_span ); |
17 | }
|
18 | |
19 | // die ruft halt oben geposteten Code auf, der sich nochmal selber aufruft.
|
Programmiere ich zu umständlich?
Frank Fritzen schrieb: > Rufus Τ. Firefly schrieb: >> Hast Du mal einen release -Build gemacht? > > Nein, bis dato nicht. Dann sind deine Zahlen 'Fantasiezahlen'. Lass den Compiler optimieren und dann sieht man weiter. Vorher hat das keinen Sinn. > Programmiere ich zu umständlich? Für meinen Geschmack: schon.
Frank Fritzen schrieb: > Einfach einen Mittelwert über die letzten 8, 16 oder was auch immer ist > nicht so schön im Ergebnis, da hätte ich lieber einen gleitenden > Mittelwert Und was spricht gegen ein IIR-Filter - braucht kaum Speicher und sieht hübsch aus.
Karl Heinz Buchegger schrieb: > Dann sind deine Zahlen 'Fantasiezahlen'. OK, was muss ich denn ändern wenn ich das ganze auf den uC lade? Optimiert der nicht von selber? Muss gestehen, dass ich nicht weiß, was man dort eintragen muss. Michael A. schrieb: > Und was spricht gegen ein IIR-Filter - braucht kaum Speicher und sieht > hübsch aus. Nichts. Habe jetzt gerade mal danach gegoogelt, sehe nur leider nicht so wirklich, wie das in C am besten umgesetzt wird.
Karl Heinz Buchegger schrieb: > Für meinen Geschmack: schon. Was wäre besser? Meinst du, einfach die Multiplikation / Division machen?
Frank Fritzen schrieb: > Optimiert der nicht von selber? Im Debug-Build wird überhaupt nicht optimiert. Beim Release-Build lässt sich nach Geschwindigkeit und/oder Codegröße optimieren, und es gibt diverse weitere Konfigurationsmöglichkeiten.
Was soll die Sparerei am controller ? 20 cents sparen fuer einen Haufen Probleme ? Nimm doch einen vernuenftigen Controller, zb einen mit 32kb Flash. Ein Mittelwert braucht uebrigens fast keinen Speicherplatz.
Rufus Τ. Firefly schrieb: > Im Debug-Build wird überhaupt nicht optimiert. Beim Release-Build lässt > sich nach Geschwindigkeit und/oder Codegröße optimieren, und es gibt > diverse weitere Konfigurationsmöglichkeiten. OK, das schau ich mir gleich mal an! Bon z'O schrieb: > Was soll die Sparerei am controller ? 20 cents sparen fuer einen Haufen > Probleme ? Nimm doch einen vernuenftigen Controller, zb einen mit 32kb > Flash. Darum geht es nicht. Ich schrieb doch, dass es mir vorrangig um den ADC geht. Hintergrund dazu ist auch noch der Platz auf meiner Platine. Da würde ich auf soviel zusätzliches Zeug verzichten, wie es geht. Und ich versuche ja erstmal, ob es passt. Wenn nicht, dann geht es halt nicht. Aber ich kann ja nicht direkt kapitulieren ;-)
Frank Fritzen schrieb: > OK, das schau ich mir gleich mal an! Mit was für einem Controller hantierst du eigentlich herum? Bei dieser Aufgabe würde ich schlichtweg Assembler nehmen. Und Gleitkomma ist bei 2K Codebereich auch drin. Meine PIC-GK-Lib braucht weniger als ein halbes K, da wären noch 1,5 K frei. Bei deinem uC müßtest du schauen, ob und was für eine GK-Lib du hast / bekommen kannst / dir selber schreiben kannst. Ansonsten zum gleitenden MW: - Ringpuffer machen - alten letzten Wert abziehen - aktuellen Wert addieren - aktuellen Wert an Stelle des alten schreiben. Geht einfach und schnell. W.S.
Frank Fritzen schrieb: > Hier mal mein Code zum Multiplizieren/Teilen: Sowas selber zu schreiben ist quatsch. Die Compilerfunktionen sind so gut optimiert, das kriegst Du selber nie so hin. 96Byte SRAM-Verbrauch klingt schon heftig für diese Aufgabe. Zeig dochmal die ganzen Variablendeklarationen. Auch auf nem 16-Bitter kann es sich lohnen, immer den kleinst möglichen Datentyp zu verwenden. Zumindest die RAM-Last verringert sich dadurch. Ob die 2kB für den MSP reichen, kann ich nicht einschätzen. Auf einem 8051 oder AVR reichen sie bequem. Selbst float wäre dann kein Problem. Die float-Lib braucht etwa 1kB und dann bleiben noch 1kB für die Applikation. Was Gift für die Codegröße ist, ist der gefürchtete Spaghettikode. Wann immer möglich, teile alles in kleine Unterfunktionen auf. Und benutze Schleifen, selbst bei nur 2 Wiederholungen. Habe keine Angst vor dem Stackverbrauch bei Funktionsaufrufen. Beim Optimierungslauf sollte ein guter Compiler automatisch alle nur einmal verwendeten Funktionen inlinen. Frank Fritzen schrieb: > Wo der Stack halt direkt 26Byte verbraucht, ist wenn ich diese Funktion > in sich selber nochmal aufrufe: Rekursionen sollte man generell vermeiden. Sie sehen nur hübsch aus, sind aber ineffektiv. (fast) immer kann man eine Rekursion als Schleife umschreiben. Mit viel Glück erkennt manchmal auch der Compiler, daß eine Rekursion nur eine verkappte Schleife ist und optimiert sie wieder zurück als Schleife. Peter
Frank Fritzen schrieb: > Ich habe immer parallel einmal die Multiplikation/Division regulär und > dann zum Vergleich mit reiner Addition/Subtraktion - immer war letztere > Variante etwas kleiner. Definiere "etwas". Die Einsparung ist auch nur einmalig. Dafür können aber die Aufrufe teurer werden. Der Compiler muß vielleicht mehr Register retten. Bei den Lib-Funktionen weiß er aber genau, welche Register sie benutzen. Auch spart es nochmals, wenn man nur unsigned rechnet. Die ADC-Werte und die Anzeige sind ja in der Regel nur positiv bzw. man addiert erst ganz zum Schluß einen Offset. Peter
So Leute, ich melde mich mal zurück. Vielen Dank für die ganzen Beiträge!!! Ich werde mich zu den einzelnen Anmerkungen noch genauer äußern. Ich habe nur vorerst ein ganz anderes Problem mit meinem Messwert. Den bekomm eich eingfach nicht still. Mal eben zum Setup: Ein DMS-Drucksensor mit, welcher in Ruhelage eine Spannung von 62uV liefert. Bei Vollausschlag liegt er bei 10,05mV. Die Referenzspannung ist ca. 1,2V und kommt von der internen Referenz des MSPs. Die maximale Eingangsspannung des MSPs ist +/- 600mV, also verstärke ich mit einem Instrumentationsverstärker (ohne den Differenzierer) die Spannung auf eben diese 600mV. Der AD-Wandler hat 16Bit für die +/-600mV, also eine theoretische Auflösung von 18,3uV. Diese erreicht der 16Bit S/D-Wandler vom MSP bekanntlich nicht. An den Ausgängen des DMS habe ich noch je einen 1u gegen Masse, also einen Tiefpass an jedem Ausgang. Von da halt auf den Verstärker und dann zum MSP. Soviel zur Hardware. In Software passiert bei mir momentan folgendes: Ich nehme 8 Werte auf und mache daraus erstmal den Mittelwert - dann folgt ein gleitender Mittelwert (werde den IIR-Filter noch ausprobieren!) um dann letztendlich diesen Wert zur Berechnung heranzunehmen. Aus diesem wird dann das Tastverhältnis für die PWM des Analogausgangs gemacht. Dieser Analogausgang ist sehr genau. Wenn ich mir jeweils einen Wert für 4mA und einen für 20mA aufnehme, dann kann daraus jeder beliebige Wert dazwischen berechnet werden und der stimmt auch nahezu aufs uA (da war ich sehr erstaunt). Nur wird der Strom, also die PWM jetzt durch den ADC-Wert bestimmt, dann eiert das ganze massivst um einen guten Wert herum. Das ist für mich grad erstmal das wichtigste Problem, da dies nunmal essentiell ist für das ganze Ding. Momentan ist das ganze noch ein ziemlich fliegender Aufbau - die Kabel der Messzelle sind natürlich auch nicht förderlich und das Steckbrett auch nicht, aber wo sollte ich da als erstes angreifen, um hier einen konstanteren Wert zu erlangen? Gruß und danke!
mit welcher Frequenz arbeitet der PWM und welche updatefrequenz der Messwerte hast du ?
kannst du dir nicht einfach mal die ADC werte per UART an den PC senden und sie dort darstellen. Dann weisst du ob der Input überhaupt sauber ist.
@Frank Fritzen Praktisch haben deine Bauteile Fehler und Ungenauigkeiten; so einfach (auch theoretisch) darf nicht rechnen.
pic schrieb: > mit welcher Frequenz arbeitet der PWM Die PWM-Frequenz liegt bei 320Hz. pic schrieb: > updatefrequenz der > Messwerte Die sind fortlaufend, das läuft alles per Interrupt - nur die Berechnungen sind halt in der main. Ein neuer Wert ist so ca. 2-3mal pro Sekunde fertig. Peter II schrieb: > kannst du dir nicht einfach mal die ADC werte per UART an den PC senden > und sie dort darstellen. Ja, das wär toll, aber dafür habe ich keine Ressourcen (unter anderem Pins am UC) mehr frei. Aber ich weiß ja anhand mehrerer Breaks im Text, dass die Variable mit meinem ADC-Ergebnis schwankt. Wie gesagt, am Stromausgang liegt es nicht, der Wert ist mit einem fixen Timerwert absolut konstand und bewegt sich um keinen uA! Das kommt erst mit der Berechnung durch die ADC-Werte.
Coder schrieb: > Praktisch haben deine Bauteile Fehler und Ungenauigkeiten; so einfach > (auch theoretisch) darf nicht rechnen. Das ist klar, aber ich habe die Sachen ja zusammengesteckt und dann mit denen meine Werte ermittelt.
Peter II schrieb: > kannst du dir nicht einfach mal die ADC werte per UART an den PC senden Der Prozessor hat halt auch keinen Hardware-UART, das müsste auch wieder in Software geschehen. Und meine Pins sind "verbraucht" :-\
Frank Fritzen schrieb: > Ja, das wär toll, aber dafür habe ich keine Ressourcen (unter anderem > Pins am UC) mehr frei. Aber ich weiß ja anhand mehrerer Breaks im Text, > dass die Variable mit meinem ADC-Ergebnis schwankt. aber nicht wieviel zu schwankt. Eventuell sind die werte ja komplett unbrauchbar. Klemm doch das Display mal ab dann hast du genug pins frei. Du braucht doch nur einen zum senden.
Hier mal der analoge Eingang, nur damit wir über dasselbe sprechen.
Frank Fritzen schrieb: > An den Ausgängen des DMS habe ich noch je einen 1u gegen Masse, also > einen Tiefpass an jedem Ausgang. Es heißt nicht C-Glied, sondern RC-Glied und das aus gutem Grund, der R ist notwendig. Hier wirkt nur der R des DMS und der wird nur wenige Ohm betragen, d.h. Deine 1µF sind völlig wirkungslos. Ich würde 100k + 1µF vorschlagen. Und unbedingt Foliekondensatoren nehmen, denn Keramik rauscht stark bei kleinen Spannungen! Peter
Für 4-20mA Schnittstelle kann ich die XTR-Serie empfehlen, wenig Bauteile notwendig, wenig Platz auf der Platte. Feine Teile. XTR115 hab ich bei mir verbaut, bin begeistert. Was den Flashbedarf angeht, Menüs gehn mächtig an den Programmspeicher ... jedes Zeichen ein Byte, da hat man schnell n paar Hundert beisammen.
Fhutdhb Ufzjjuz schrieb: > Für 4-20mA Schnittstelle kann ich die XTR-Serie empfehlen, wenig > Bauteile notwendig, wenig Platz auf der Platte. Feine Teile. Full ACK! Die habe ich auch schon verwendet, aber die haben auch einen stolzen Preis ;-) Und mit nachträglich am Display was einstellen mit Messbereich und so ist da auch nicht mehr so einfach. Da müsstest du trotzdem den Weg über eine Art von DAC gehen.
Fhutdhb Ufzjjuz schrieb: > Was den Flashbedarf angeht, Menüs gehn mächtig an den Programmspeicher > ... jedes Zeichen ein Byte, da hat man schnell n paar Hundert beisammen. Auf 4 * 7Segment kann man keine umfangreichen Menüs darstellen. Peter
Frank Fritzen schrieb: > Fhutdhb Ufzjjuz schrieb: >> Für 4-20mA Schnittstelle kann ich die XTR-Serie empfehlen, wenig >> Bauteile notwendig, wenig Platz auf der Platte. Feine Teile. > > Full ACK! Die habe ich auch schon verwendet, aber die haben auch einen > stolzen Preis ;-) Und mit nachträglich am Display was einstellen mit > Messbereich und so ist da auch nicht mehr so einfach. Da müsstest du > trotzdem den Weg über eine Art von DAC gehen. Bei mir hab ich den 4-20mA Kreis galvanisch entkoppelt um von der Messspannung unabhängig zu werden. Also Optokoppler an die PWM, dann ne kleine MOS Gegentaktstufe, dahinter n Pi-Glied auf den XTR. Hab aber ne UART zur Verfügung wo ich Konfigurationswerte in den µC schreiben kann, z.B. um die Schleife abzugleichen. Mit ner 16-Bit PWM @ 100Hz hab ich da ausreichend Luft von der Auflösung her ... zumindest in meiner Anwendung. Eingangsseitig von der 4-20 kommend hab ich nen Brückengleichrichter spendiert umd das Ding DAU-fest zu machen ... hat sich im Feld auch schon bewährt ;o)
Hallo, man könnte ja auch die ADC-Werte auf der 7-Segmentanzeige in Hex ausgeben lassen. Da sieht man sicher die Größe der Schwankungen. Was ist den jetzt ein "echter" gleitender Durchschnitt? 8, 16 Werte sind nicht genug? Man kann ja auch exponentiell glätten, da braucht es nur den vorherigen geglätten Wert. http://de.wikibooks.org/wiki/Mathematik:_Statistik:_Glättungsverfahren#Exponentielle_Gl.C3.A4ttung Wahrscheinlich ist ein doppelt geglätter Wert angebrachter.
Peter Dannegger schrieb: > Auf 4 * 7Segment kann man keine umfangreichen Menüs darstellen. Das stimmt wohl :-) Da geht nur das nötigste. Fhutdhb Ufzjjuz schrieb: > Bei mir hab ich den 4-20mA Kreis galvanisch entkoppelt um von der > Messspannung unabhängig zu werden. Also Optokoppler an die PWM, dann ne > kleine MOS Gegentaktstufe, dahinter n Pi-Glied auf den XTR. > Hab aber ne UART zur Verfügung wo ich Konfigurationswerte in den µC > schreiben kann, z.B. um die Schleife abzugleichen. Mit ner 16-Bit PWM @ > 100Hz hab ich da ausreichend Luft von der Auflösung her ... zumindest in > meiner Anwendung. Auch ne Variante! Schön! Bin hier nur leider am Bauteile sparen, wo es nur geht. Hab ja eigentlich auch nur das "Problem", die eingangsseitigen Messwerte zu beruhigen. Peter Dannegger schrieb: > Ich würde 100k + 1µF vorschlagen. Macht keinen Unterschied. Wackelt trotzdem. Liegt eher am Wandler, glaube ich (+meinem momentanen Scheiß-Aufbau mit der freien Verdrahtung). Werde jetzt mal den IIR-Filter implementieren. Da habe ich bestimmt noch paar Fragen zu gleich. Die Geschichte mit dem UART werde ich auch mal probieren jetzt, muss ich nur erstmal nen zweiten MSP aufbauen, hab keine Lust, alles auseinanderzureißen. Der Sensor hat übrigens 5k Gesamtwiderstand, also auch rund 5k vor und nach jedem C. Fhutdhb Ufzjjuz schrieb: > ingangsseitig von der 4-20 kommend hab ich nen Brückengleichrichter > spendiert umd das Ding DAU-fest zu machen ... hat sich im Feld auch > schon bewährt ;o) Sicher sinnvoll, hab aber auch schon gehört, dass Techniker, die so Dinger im Werk anschließen, nicht damit klarkommen, wenn nicht hundertprozentig vorgegeben ist, wo + und wo - ist ;-)
Horst Hahn schrieb: > Was ist den jetzt ein "echter" gleitender Durchschnitt? Mein gleitender Durchschnitt ist ist momentan folgender:
1 | uint16_t adc_calc_average_value( uint16_t new_value ) |
2 | {
|
3 | static uint16_t values[AVERAGE_VALUES]; |
4 | static uint8_t position = 0; |
5 | uint8_t counter; |
6 | uint32_t averaged_value = 0; |
7 | |
8 | values[position++] = new_value; |
9 | |
10 | if( position >= AVERAGE_VALUES ) |
11 | {
|
12 | position = 0; |
13 | }
|
14 | |
15 | for( counter = 0; counter < AVERAGE_VALUES; counter++ ) |
16 | {
|
17 | averaged_value += values[counter]; |
18 | }
|
19 | |
20 | averaged_value /= AVERAGE_VALUES; |
21 | |
22 | return averaged_value; |
23 | }
|
Kannst ja mal alles abklemmen und einen Konstanter (oder Batterie per Spannungsteiler) an den AD-Wandler-Eingang anschliessen und mal schauen was da so passiert.
Jetzt mal ne ganz blöde Frage: Das ist doch eigentlich schon ne IIR-Struktur, oder nicht?
Coder schrieb: > allerhöchstens max. ein FIR mit 1 Koeffiz. aber nicht iir OK, und wie komme ich an (berechne ich) die Koeffizienten? Coder schrieb: > Kannst ja mal alles abklemmen und einen Konstanter Das mache ich jetzt.
Frank Fritzen schrieb: > Ein neuer Wert ist so ca. 2-3mal pro > Sekunde fertig. Man muß keinen gleitenden Mittelwert machen. Es reicht die Summe über soviel Meßwerte, bis die Zeit für 2..3 Ausgaben um ist. Z.B. eine Messung alle 1ms (Timerinterrupt) ergibt den Mittelwert über 512 Messungen und eine Ausgaberate von 1/512 = 2 je Sekunde. Man braucht dann nur Speicher für die Summe (32Bit) und nicht alle 512 Messungen. Peter
FIR Koeffizienten zu berechnen, kann ich nicht mehr. Ist zu lange her. Das geht aber z.B. mit SciLab (open source) oder MatLab. Ad-hoc kann ich Dir es aber nicht erklären. Aber Du hast doch eh einen Eingangsfilter? Die Frage, die ich mir Stelle, ist, was für eine Auflösung du erwartest? Ich vermute, von deinen 16-Bit, bleiben effektiv 10-Bit oder weniger über. Das macht sich dann schon sehr deutlich bemerkbar.
Peter Dannegger schrieb: > Es reicht die Summe über > soviel Meßwerte, bis die Zeit für 2..3 Ausgaben um ist. So habe ich es ja im Moment. Mit der Anzahl habe ich ja ein wenig herumexperimentiert. 4,8,16,32,64,128 Peter Dannegger schrieb: > Man braucht dann nur Speicher für die Summe (32Bit) und nicht alle 512 > Messungen. Das ist klar der Vorteil. Coder schrieb: > Die Frage, die ich mir Stelle, ist, was für eine Auflösung du erwartest? > Ich vermute, von deinen 16-Bit, bleiben effektiv 10-Bit oder weniger > über. Das macht sich dann schon sehr deutlich bemerkbar. Naja, die 16Bit nicht, mir geht ja schon 1 Bit verloren, weil sich nahezu alles im positiven Bereich abspielt. Aber so 14 Bit wären schon nicht verkehrt. Hauptsächlich geht es mir ja um den differentiellen Wandler.
@Frank Fritzen Es würde mich interessieren, wie stark die Werte "wackeln"? Z um Anderen gilt: Je höher effektive Auflösung sein soll, desto aufwändiger und anstrengender wird es. IHMO würde ich für höhere Auflösungen einen externen AD-Wandler benutzen, da ich es für unsinn halte einen 16-Bit Wandler in einen uC zu packen. Achja. Versuch während der Wandlung, alles unnötig Digitale auszuschalten --> Schlafmodi.
Kann auch im Layout / Verdrahtung versteckt sein der Bug, möglich das die Masse springt durch Lastwechsel, z.B. von den Strömen der 7-Segment-Anzeige oder dir der Netzbrumm einkoppelt über ne "Antenne"
Deswegen soll er auch mal alles abklemmen und einen "guten" Konstanter anschliessen.
Coder schrieb: > Es würde mich interessieren, wie stark die Werte "wackeln"? Sag ich euch gleich - ich werde mal einen Schleppzeiger einbauen.
Da bin ich mal gespannt. Dein Schleppanzeiger wird bestimmt schön träge sein und mitteln. Wenn Du es trotzdem wackeln siehst...
Sodele: Digitales Zeug noch an: Min: 49447 Max: 49604 Ist jetzt mit festem Spannungsteiler.
Upps, das ist schlecht, das wackelt überschlagsmäßig 3mV in bezug auf deine 1,2V Referenz.
Ohne Mittelung: Min: 49447 Max: 49604 Delta: 157 Letzte 2 Werte gemittelt: Min: 49480 Max: 49607 Delta: 127 Letzte 4 Werte gemittelt: Min: 49483 Max: 49603 Delta: 120 Letzte 32 Werte gemittelt: Min: 49535 Max: 49557 Delta: 22 Letzte 64 Werte gemittelt: Min: 49534 Max: 49562 Delta: 28 Letzte 128 Werte gemittelt: Min: 49542 Max: 49559 Delta: 17
Ergo: Mit 128 geht es, aber jetzt reagiert halt der Ausgang nicht mehr wirklich auf den Eingang ;-)
Schieberegister jetzt aus Letzte 2 Werte gemittelt: Min: 47410 Max: 47551 Delta: 121 (141 mit SR) Letzte 4 Werte gemittelt: Min: 47415 Max: 47536 Delta: 121 (120 mit SR) Letzte 32 Werte gemittelt: Min: 47460 Max: 47486 Delta: 26 (22 mit SR) Also das Schieberegister macht keinen Unterschied. (Es ist noch an, wird aber nicht angesteuert)
Wie sieht es ohne alles aus? Und der Spannungsteiler hat natürlich eine eigene Versorgung, von der Du weisst, dass Sie rauscharm ist?
Coder schrieb: > Und der Spannungsteiler hat natürlich eine > eigene Versorgung, von der Du weisst, dass Sie rauscharm ist? Der Spannungsteiler hat als Versorgung die interne Referenz. Die ist sicher nicht die Beste, aber die soll es später ja auch sein. Mit den 128 Werten geht es ja eigentlich, nur wird alles so langsam. Habe aber aucvh 1024faches Oversampling an.
Nur mal ne Frage zur Ausgangsschaltung für den Strom - gibt es da irgendwelche Kritikpunkte? Funktionieren tut es gut, aber wenn noch jemand nen Vorschlag hat, dann bin ich immer ganz Ohr. Meinem Platzproblem widme ich mich später ;-)
Ok, muss du für dich entscheiden. Dann könntest Du eigentlich nur noch die Schlafmodi probieren.
c9 c10 . Wenn AGND schwankt, und das macht es sicherlich, da PWM sowie die 20mA Schleife auch auf AGND geht, verschiebt es dir die Messung.
Und Deine Versorgungsspannung ist sauber? Schaltregler oder Linearregler, Blockkondensatoren? Schonmal versuch das Ding von ner Batterie laufen zu lassen?
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.