Forum: Mikrocontroller und Digitale Elektronik Abschätzung Codegröße Mikrocontroller


von Frank Fritzen (Gast)


Lesenswert?

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ß

von Ulrich (Gast)


Lesenswert?

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.

von Peter II (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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ß

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

> 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.

von Karl H. (kbuchegg)


Lesenswert?

> 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.

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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?

von Karl H. (kbuchegg)


Lesenswert?

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.

von Michael A. (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Für meinen Geschmack: schon.

Was wäre besser? Meinst du, einfach die Multiplikation / Division 
machen?

von Rufus Τ. F. (rufus) Benutzerseite


Lesenswert?

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.

von Bon z'O (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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 ;-)

von W.S. (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Peter D. (peda)


Lesenswert?

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

von Frank Fritzen (Gast)


Lesenswert?

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!

von pic (Gast)


Lesenswert?

mit welcher Frequenz arbeitet der PWM und welche updatefrequenz der 
Messwerte hast du ?

von Peter II (Gast)


Lesenswert?

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.

von Coder (Gast)


Lesenswert?

@Frank Fritzen
Praktisch haben deine Bauteile Fehler und Ungenauigkeiten; so einfach 
(auch theoretisch) darf nicht rechnen.

von Frank Fritzen (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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" :-\

von Peter II (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Angehängte Dateien:

Lesenswert?

Hier mal der analoge Eingang, nur damit wir über dasselbe sprechen.

von Frank Fritzen (Gast)


Angehängte Dateien:

Lesenswert?

Und das ist mein Stromausgang

von Peter D. (peda)


Lesenswert?

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

von Weingut P. (weinbauer)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Weingut P. (weinbauer)


Lesenswert?

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)

von Horst H. (horha)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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 ;-)

von Frank Fritzen (Gast)


Lesenswert?

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
}

von Coder (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

Jetzt mal ne ganz blöde Frage: Das ist doch eigentlich schon ne 
IIR-Struktur, oder nicht?

von Coder (Gast)


Lesenswert?

allerhöchstens max. ein FIR mit 1 Koeffiz. aber nicht iir

von Frank Fritzen (Gast)


Lesenswert?

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.

von Peter D. (peda)


Lesenswert?

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

von Coder (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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.

von Coder (Gast)


Lesenswert?

@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.

von Weingut P. (weinbauer)


Lesenswert?

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"

von Coder (Gast)


Lesenswert?

Deswegen soll er auch mal alles abklemmen und einen "guten" Konstanter 
anschliessen.

von Frank Fritzen (Gast)


Lesenswert?

Coder schrieb:
> Es würde mich interessieren, wie stark die Werte "wackeln"?

Sag ich euch gleich - ich werde mal einen Schleppzeiger einbauen.

von Coder (Gast)


Lesenswert?

Da bin ich mal gespannt. Dein Schleppanzeiger wird bestimmt schön träge 
sein und mitteln. Wenn Du es trotzdem wackeln siehst...

von Frank Fritzen (Gast)


Lesenswert?

Sodele:

Digitales Zeug noch an:

Min: 49447
Max: 49604

Ist jetzt mit festem Spannungsteiler.

von Coder (Gast)


Lesenswert?

Upps, das ist schlecht, das wackelt überschlagsmäßig 3mV in bezug auf 
deine 1,2V Referenz.

von Frank Fritzen (Gast)


Lesenswert?

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

von Frank Fritzen (Gast)


Lesenswert?

Ergo: Mit 128 geht es, aber jetzt reagiert halt der Ausgang nicht mehr 
wirklich auf den Eingang ;-)

von Frank Fritzen (Gast)


Lesenswert?

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)

von Coder (Gast)


Lesenswert?

Wie sieht es ohne alles aus? Und der Spannungsteiler hat natürlich eine 
eigene Versorgung, von der Du weisst, dass Sie rauscharm ist?

von Frank Fritzen (Gast)


Lesenswert?

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.

von Frank Fritzen (Gast)


Lesenswert?

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 ;-)

von Coder (Gast)


Lesenswert?

Ok, muss du für dich entscheiden. Dann könntest Du eigentlich nur noch 
die Schlafmodi probieren.

von pic (Gast)


Lesenswert?

Nimm die 1µF weg, die könnten dir solche Probleme machen.

von Frank Fritzen (Gast)


Lesenswert?

pic schrieb:
> Nimm die 1µF weg

Welche?

von pic (Gast)


Lesenswert?

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.

von Weingut P. (weinbauer)


Lesenswert?

Und Deine Versorgungsspannung ist sauber?
Schaltregler oder Linearregler, Blockkondensatoren?
Schonmal versuch das Ding von ner Batterie laufen zu lassen?

von Weingut P. (weinbauer)


Lesenswert?

PS: die Refferenzspannung hat auch nen kleinen C?

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
Noch kein Account? Hier anmelden.