Forum: Mikrocontroller und Digitale Elektronik ADC Messwert, Betrag ermitteln


von Maddin (Gast)


Lesenswert?

Hallo Leute

Ich habe einem Signal das positive wie negative Werte annehmen kann (zb. 
Sinus) einen Offset der halben ADC-Referenzspannung gegeben um die 
Wandlung zu ermöglichen. Diesen Offset will ich nun so rausrechnen, dass 
ich jeweils den Betrag des Signals erhalten.

Es liegt ein 10Bit ADC vor. Ich habe dies so gemacht:
1
if (X_messwert<0x1FF) X_messwert = 0x1FF - X_messwert;
2
else X_messwert = X_messwert - 0x1FF;

Mir erscheint dies jedoch recht unelegant. Ich dachte zuerst 
fälschlicherweise man könnte mit dem 2er Komplement rechnen. Gibt es 
eine andere Möglichkeit?

Gruß

Maddin

von Bernd N (Gast)


Lesenswert?

>> der halben ADC-Referenzspannung gegeben...

Welchen Wert suchst du ? positive Halbwelle und dessen Betrag ? /2 wenn 
der Offset so ist, wie du ihn angegeben hast.

von Maddin (Gast)


Lesenswert?

Wenn das Signal größer als 0V ist, also somit ein Spannungswert größer 
der halben Referenzspannung gemessen wird, dann suche ich natürlich 
diesen positiven Anteil.
Ist das Signal negativ, wird ein Spannungswert kleiner der halben 
Referenzspannung gemessen. Gesucht wird in diesem Fall der Betrag des 
negativen Spannungswert, also Offset - gemessener Spannungswert

Was soll da nun noch /2 gerechnet werden?

von Tom (Gast)


Lesenswert?

Was heißt elegant? Aus irgendwelchen Gründen 2 Takte einsparen und das 
Programm (bei der Samplerate eines üblichen AVR-ADCs) um 0.1% 
beschleunigen? Oder lieber lesbar?

Bei Deinem Beispiel brauche ich 10s, um zu verstehen, was passiert. Wie 
schnell ist dieses Beispiel verständlich?
1
int16_t voltage = readADC();
2
voltage -= ADC_OFFSET;
3
int16_t messwert = ABS(voltage);

von Maddin (Gast)


Lesenswert?

Tom schrieb:
> Bei Deinem Beispiel brauche ich 10s, um zu verstehen, was passiert.

Deshalb frage ich.

Tom schrieb:
> int16_t voltage = readADC();
> voltage -= ADC_OFFSET;
> int16_t messwert = ABS(voltage);

Hm ja, das ist nun auch nicht halbes und nichts ganzes. Ich will den 
Betrag ermitteln und du versuchst mir zu helfen in dem du mir eine 
Funktion ABS() anbietest...?

Nun geht es doch darum was ABS macht? Ist es eine C99 Funktion? Dann 
möchte ich darauf verzichten. Mus ich ABS() selbst schreiben? Dann würde 
da auch wieder sowas drinne stehen wie:
1
if(voltage<0) voltage = -voltage;
2
else...

Wenn es dir hier nicht um die Art und Weise der Betragsermittelung geht, 
sondern um die Verwendung von Funktionen um die Übersichtlichket zu 
erhöhen, dann gebe ich dir schon recht. Nur ging es mir in erster Linie 
nicht darum.

Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:
> Tom schrieb:
>> Bei Deinem Beispiel brauche ich 10s, um zu verstehen, was passiert.
>
> Deshalb frage ich.
>
> Tom schrieb:
>> int16_t voltage = readADC();
>> voltage -= ADC_OFFSET;
>> int16_t messwert = ABS(voltage);
>
> Hm ja, das ist nun auch nicht halbes und nichts ganzes. Ich will den
> Betrag ermitteln und du versuchst mir zu helfen in dem du mir eine
> Funktion ABS() anbietest...?

#define ABS(x)  (x) < 0 ? -(x) : (x)

ausserdem gibt es auch noch abs Funktionen in math.h
wenn man sich die nicht selber machen will (was ja auch vernünftig ist)

> Nur ging es mir in erster Linie
> nicht darum.

Sondern?

Pberleg dir einfach mal, was der Compiler wohl aus diesem Konstrukt 
machen wird, bzw. probier es aus (aber Optimizer einschalten).

Das übersetzt sich zu

   16 Bit Subtraktion
   16-Bit Vergleich
   Sprung wenn negativ   ------
   16 Bit Komplement          |
                         <-----



In den meisten Fällen bringt es nichts bis extrem wenig, wenn man 
versucht extrem schlau zu sein. Lesbarer Code optimiert meistens auch 
ziemlich gut.

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> #define ABS(x)  (x) < 0 ? -(x) : (x)

Oh na an sowas hab ich noch garnicht gedacht. Dachtemit defines sollte 
man nur Dinge die vor der Laufzeit feststehen definieren.

Karl heinz Buchegger schrieb:
> ausserdem gibt es auch noch abs Funktionen in math.h

In Anbetracht der Tatsache, dass z.B. sqrt() bei mir 1,6kB frisst (die 
ich nicht habe), lasse ich in Zukunft lieber möglichst Abstand von 
Funktionen die ich nicht selbst geschrieben habe.

Danke euch und Gruß

Maddin

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:

> In Anbetracht der Tatsache, dass z.B. sqrt() bei mir 1,6kB frisst (die
> ich nicht habe),

Nun ja. sqrt ist ja auch nicht so einfach zu berechnen, wie ein 
Absolutwert.

> lasse ich in Zukunft lieber möglichst Abstand von
> Funktionen die ich nicht selbst geschrieben habe.

Wie würdest du eine Funktion schreiben, die einen Absolutwert berechnet? 
Du kannst davon ausgehen, dass diejenigen die deine Standardfunktionen 
geschrieben haben auch keine Trottel waren und man in 30 Jahren gelernt 
hat, wie man eine iabs schreibt

int iabs( int value )
{
  return value > 0 ? value : -value;
}

Ist ja nicht gerade Raketentechnik :-)

Ausserdem muss ich mich korrigieren. Im math.h vom WinAvr ist ghar kein 
iabs oder labs enthalten. Bin wohl schon zu sehr C++ verwöhnt :-)

von Maddin (Gast)


Lesenswert?

Karl heinz Buchegger schrieb:
> dass diejenigen die deine Standardfunktionen
> geschrieben haben auch keine Trottel waren und man in 30 Jahren gelernt
> hat, wie man eine iabs schreibt

Oho, habsch auch net behauptet. Die Verwendung von externen Funktionen 
macht meiner Meinung nach nur Sinn, wenn man genau weiß was diese tun, 
welche Datentypen man ihr übergeben muss, welche man zurück bekommt usw. 
In meinen Fällen hat die Recherche dafür meist länger gedauert als das 
Schreiben einer eigenen Funktion. Außerdem übt das.

Im Beispiel der iabs() is da natürlich nich viel dran. Mein Code war da 
viel komplexer (und unnötig aufwendiger).

von Karl H. (kbuchegg)


Lesenswert?

Maddin schrieb:

> Oho, habsch auch net behauptet. Die Verwendung von externen Funktionen
> macht meiner Meinung nach nur Sinn, wenn man genau weiß was diese tun,
> welche Datentypen man ihr übergeben muss, welche man zurück bekommt usw.

Da hast du recht.
Ich finde, jeder sollte einmal das Repertoire der Standardfunktionen 
programmiert haben (mit Ausnahme der Dinge, die über double gehen). Das 
schult ungemein und die meisten Funktionen sind auch ziemlich primitiv, 
in ähnlichem Komplexitätsgrad wie eben dieses iabs bzw. kaum komplexer 
(ok, malloc/free sind schon aufwändiger)

> In meinen Fällen hat die Recherche dafür meist länger gedauert als das
> Schreiben einer eigenen Funktion. Außerdem übt das.

Nun ja.
Ist halt ein zweischneidiges Schwert. Ich geb dir natürlich recht, dass 
man da Übung bekommt. Auf der anderen Seite ist es für andere im Team 
immer schwieriger wenn einer aus der Reihe tanzt und meint, er müsse 
jeden Pfurz selber als Funktion implementieren. Mann muss dann immer 
umdenken und mehr im Kopf behalten, wenn man Code liest.

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.