Forum: Mikrocontroller und Digitale Elektronik AD-Wandler Umrechnung


von Torsten (Gast)


Lesenswert?

Hallo,

ich bin gerade dabei einen AD-Wandler zu programmieren komme aber noch 
nicht so ganz mit der Umrechnung klar.

IC Atmega8

Ich habe die interne Referenzspannung von 2,56V gewählt
Am ADCO 0 habe ich ein einstellbare Spannung von 100 mv bis 400 mv 
anliegen wo ich auswerten möchte.

Habe zwei Schaltstellen eine bei 260 mv und die zweite bei 340 mv.

Kann ich die Umrechnung mit der Formel umrechnen

ADC = Vin * 1024 /Aref = 0,260 *1024 / 2,5 = 106,4

ADC = Vin * 1024 /Aref = 0,340 *1024 / 2,5 = 139,2

stimmt diese Umrechnung? oder gib es eine andere Formel?

kann man auch die zwei werte in einer if frage vergleichen

z.b if (ADC > 0,260mv | < 0,340mv)
oder geht das nicht?

Bin für jede Hilfe und Tipps Dankbar

von Purzel H. (hacky)


Lesenswert?

Das sollte dochalles im Datenblattbeschrieben sein...

von c-hater (Gast)


Lesenswert?

Torsten schrieb:

> ich bin gerade dabei einen AD-Wandler zu programmieren komme aber noch
> nicht so ganz mit der Umrechnung klar.
>
> IC Atmega8
>
> Ich habe die interne Referenzspannung von 2,56V gewählt
> Am ADCO 0 habe ich ein einstellbare Spannung von 100 mv bis 400 mv
> anliegen wo ich auswerten möchte.
>
> Habe zwei Schaltstellen eine bei 260 mv und die zweite bei 340 mv.
>
> Kann ich die Umrechnung mit der Formel umrechnen
>
> ADC = Vin * 1024 /Aref = 0,260 *1024 / 2,5 = 106,4
>
> ADC = Vin * 1024 /Aref = 0,340 *1024 / 2,5 = 139,2
>
> stimmt diese Umrechnung? oder gib es eine andere Formel?

Es gibt eine ganze Menge anderer Formeln. Welche die richtige ist, hängt 
davon ab, wie genau du den AD-Wandler betreibst. Die von dir verwendete 
Formel wäre korrekt für den Fall, daß du das Ding im Single-Ended Modus 
und mit rechts ausgerichteten Ergebnissen betreibst.

> kann man auch die zwei werte in einer if frage vergleichen
>
> z.b if (ADC > 0,260mv | < 0,340mv)

ImPrinzip ja, aber so sicher nicht.

Was du wahrscheinlich wolltest: Wissen ob die Spannung im vorgegebenen 
Bereich ist. Dann mußt du schreiben:

if (ADC > ADCVALUE(0.26) && ADC < ADCVALUE(0.34))

Dazu müßtest du natürlich auch ein passendes Macro namens ADCVALUE 
schreiben, was die Anwendung der passenden Formel darstellt.

Fazit: Lerne am besten erstmal die Sprache, die du verwendest. Ja, es 
ist eine Scheißsprache, aber schließlich zwingt dich ja niemand, sie zu 
verwenden...

von chris (Gast)


Lesenswert?

ja an sich schon aber wenn Aref gleich 2,56V ist sollte man das auch in 
die Gleichung einsetzen...

> Habe zwei Schaltstellen eine bei 260 mv und die zweite bei 340 mv.

> Kann ich die Umrechnung mit der Formel umrechnen

> ADC = Vin * 1024 /Aref = 0,260 *1024 / 2,5 = 106,4

  ADC = Vin * 1024 / Aref = 0,260 * 1024 / 2,56V = 104

von Falk B. (falk)


Lesenswert?


von c-hater (Gast)


Lesenswert?

Falk Brunner schrieb:

> Siehe Festkommaarithmetik

Huch?!

Mir scheint, es geht hier eher um Gleitkommarithmetik zur 
Entwurfszeit...

von Anja (Gast)


Lesenswert?

c-hater schrieb:
> Dazu müßtest du natürlich auch ein passendes Macro namens ADCVALUE
> schreiben,

Makro ist schon richtig. Er will aber "mV"

Ich würde so schreiben:

#define mV * 1024 / 2560

if ((ADCW > (260 mV)) && (ADCW < (340 mV)))
{
   /* all ok */
}

Gruß Anja

von Torsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

erst mal vielen Dank für die schnellen Antworten. Ich habe in der 
zwischen zeit noch ein wenig ausprobiert doch es will einfach nicht.

Ober bin ich nur heute Abend nicht mehr in der Lage die Fehler zu finden 
-;

Wenn ich das Programm Startete dann gehen Port B & D kurz an so wie im 
Programm aber danach reagiert er nicht mehr auf das analoge Signal.
Wenn ich die Werte verändre bringt es auch nichts (außer ich komme unter 
15 aber das ist aber wahrscheinlich die Ungenauigkeit von AD-Wandler)

Habe im Anhang mal den Text.
Ihr könnt ja mal drüber schauen und sagen wo noch Fehler sind bzw. wo 
keine sind.

von Anja (Gast)


Lesenswert?

Torsten schrieb:
> wo noch Fehler sind

  ADCSRA |= (1<<ADSC);      // eine Wandlung "single conversion"

  ADC_result = ADCW;      // ADC-Wert in ADC_result schreiben


Nach Start der Wandlung solltest Du nicht so ungeduldig sein und solange 
Warten bis der ADC auch den Wert gewandelt hat. (siehe Datenblatt).

Gruß Anja

von Uwe (de0508)


Lesenswert?

Guten Morgen,

was mir aufgefallen ist:

1) c.txt Datein laufen bei mir nicht durch Compiler
2) mehrfaches Überschreiben des Rigisters ADCSRA, Stichwort 
Bitmanipulation
1
ADCSRA = (1<<ADPS1) | (1<<ADPS2);  // Frequenzvorteiler 64
2
ADCSRA = (1<<ADIE);
3
ADCSRA = (1<<ADEN);      // ADEN = ADC aktivieren
4
ADCSRA |= (1<<ADSC);

Mach dir mal den Spaß und spiele mit Papier und Bleistift µC und 
berechne bei diesen 4 Zeilen die Ergebnisse.

Bitte hier auch hinschreiben.
Start sei ADCSRA := 0.

Dann ist diese Syntax von Zeile 1 falsch, waaaaas macht der Compiler für 
Ausgaben?
1
Test_PortB |Test_PortD;      // Ausgabeports D & B einschalten
2
_delay_ms(200);
3
PORTB =~0x00;        // Ausgabeprot B auschalten
4
PORTD =~0x00;        // Ausgabeprot D auschalten

von Wolfgang (Gast)


Lesenswert?

Uwe S. schrieb:
> Mach dir mal den Spaß und spiele mit Papier und Bleistift µC und
> berechne bei diesen 4 Zeilen die Ergebnisse.

Heutzutage darf man auch den Simulator der IDE (Atmel Studio, AVR Studio 
oder was auch immer) benutzen, um sich Schritt für Schritt anzusehen, 
was im Prozessor passieren würde.

von Uwe (de0508)


Lesenswert?

Hallo Wolfgang,

ja sicherlich, es ist auch für Anfänger eine brauchbares Mittel.
Mal in so einen AVR µC hinein sehen zu können.

Ich verwende nur kein WinOS und somit keinen Simulator und benötige auch 
keinen..

Es hat für mich eine andere Klarheit die Dinge (Problemlösungen) auf dem 
Papier richtig zu machen, als mit einem Simulator nur die Ergebnisse 
(Ausgaben) zu sehen.

von Wusel D. (stefanfrings_de)


Lesenswert?

Noch etwas cooler ist ein In-Circiuit Debugger (z.B. AVR Dragon). Damit 
kannst Du das Programm anhalten, "in den Chip hinein schauen" und sogar 
Ports und Register ändern.

Wegen der Berechnung: Wann immer es geht, vermeide Fließkomma Zahlen. 
Denn diese werden langam berechnet und erfordern ziemlich viel Programm 
Speicher.

Anstatt 0,260 Volt kann der AVR besser mit 260mV rechnen. Das obige 
Marko "mV" ist eine geniale Lösung für diese Aufgabe, da einfach 
anzuwenden, gut nachvollziehbar und ohne Fließkomma Arithmetik.

Noch besser wird es, wenn Du bei Divisionen und Multiplikationen 
möglichst auf "runde" Zahlen im Sinne des Binärsystem setzt, also 2, 4, 
8, 16, usw.

Denn um eine Zahl durch diese runden Zahlen zu dividieren oder zu 
multiplizieren, muss er ledigleich Bits nach Links oder rechts 
verschieben. Eine Division durch 7 ist erheblich komplexer. Ein Blick in 
den erzeugten Assembler-Code kann diesbezüglich Aufsclussreich sein.

1024/256 = 4 also eine Runde Zahl. Das ist der Idealfall!

Un nun kannst DU Dir denken, warum die Referenzspannung gerade 2,56V ist 
und nicht etwa 2,5 Volt.

von Torsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

habe das Programm etwas verändert.
Wenn ich die Simulation durchlaufen lasse geht es bis auf die Ausgänge 
setzten.
Kann man in der Simulation auch auf den AD-Wandler irgendein Signal 
legen?

Denn wenn ich es wider auf meinem Board mache funktioniert es immer noch 
nicht richtig.

Wenn ich jetzt auf die zweite Schalter Stellung gehe schaltet er mir die 
Schalter Stellung 1 durch.

Stimmt da was in meiner Umrechnung nicht?


Habe jetzt auch die Warte Zeile für den AD-Wandler drin.

von Hmm (Gast)


Lesenswert?

Hänge bitte C-Dateien auch als solche an und nicht mit der Endung 
".txt".
Du sparst Dir die Umbennung und das lässt sich besser anschauen. Danke.

von Torsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

habe das Programm jetzt als C-Datei angehängt

von Uwe (de0508)


Angehängte Dateien:

Lesenswert?

Hallo Torsten,

hier mal eine übersichtlichere und angepasste Version.
Als Beispiel habe ich mal Macros die wie Funktionen aus sehen angelegt 
und zum anderen static Funktionen für das LED setzen.

Schau mal über das Programm und versuche es zu verstehen.

Ich nehme mal an, dass die LED GND geschaltet werden, um "AN" zu sein..
.

von Uwe (de0508)


Lesenswert?

Sorry,
hier ist noch ein Kopierfehler, nun berichtig:
1
(void) ADCW;

von Torsten (Gast)


Angehängte Dateien:

Lesenswert?

Hallo,

mit dem Programm von Uwe S. habe ich so weit durch geschaut und auch 
verstanden.

Nur habe ich immer noch das Problem das die Schalter Stellung 3 die 
Schalter Stellung 2 durchschaltet
Kurze Erklärung habe einen 3 Stufen schalter
 1 Stufe 142 mv  -> soll nichts passieren
 2 Stufe 228 mv  -> soll die erste if schleife durch schalten
 3 Stufe 312 mv  -> soll die erste if schleife aus und die zweite if 
schleife  schalten.

Berechnung
2 Stufe

ADC = Vin * 1024 / Aref = 0,228 * 1024 / 2,56V = 91,2

3 Stufe

ADC = Vin * 1024 / Aref = 0,312 * 1024 / 2,56V = 124,8

Wo kann jetzt das Problem noch liegen?

von Uwe (de0508)


Lesenswert?

Guten Morgen,

grundlegend sind deine Fehler noch vorhanden.

Warum verwendest Du nicht mein Bsp.?

Ich schreibe dir diese jetzt nicht heraus.

von Michael (Gast)


Lesenswert?

Torsten schrieb:
> Kann man in der Simulation auch auf den AD-Wandler irgendein Signal
> legen?

Ein Analogsignal wird schwierig. Nachdem du das Ergebnis der Wandlung in 
ADC_result übernommen hast, kannst du es aber manipulieren.

von Torsten (Gast)


Angehängte Dateien:

Lesenswert?

Guten Morgen,

@ Uwe S. ich habe dein Bsp. verwendet habe nur aus versehen die Falsche 
Datei angehängt.

Habe bei den if abfragen die Werte auch schon mal Probiert abzuändern es 
bringt zwar etwas aber dann zucken die Led's wie sie wollen, aber es 
müsste doch auch mit den Werten gehen wo in den if schleifen sind, habe 
noch mal nachgemessen die werte am AD-Wanderl stimmen und die 
Umgerechnete Werte auch.

Woran kann es jetzt noch liegen?

von Torsten (Gast)


Lesenswert?

Hallo,

weiß noch einer woran es liegen kann?

von Wusel D. (stefanfrings_de)


Lesenswert?

Vielleicht stimmen die Spannungen nicht, oder die von Dir programmierten 
Schwellwerte sind innerhalb der Toleranz des ADC oder der Referenz.

Wenn eine Spannung ab 213mV irgedn etwas auslösen soll, dann wäre es 
schlecht, den Wert "312mV" zu programmieren. Ich würde eher die Mitte 
zwischen den tatsächlichen Spannungen als Grenzwerte nehmen:

> 1 Stufe 142 mv  -> soll nichts passieren
> 2 Stufe 228 mv  -> soll die erste if schleife durch schalten
> 3 Stufe 312 mv  -> soll die erste if schleife aus und die zweite if

Also demnach etwa so abfragen:

if (spannung <= 100mV) was dann passieren soll, hast Du vergessen, 
festzulegen

else if (spannung > 100mV) dann soll nichts passieren

else if (spannung > 180mV) dann soll die erste if schleife durch 
schalten

else if (spannung > 270mV) dann soll die erste if schleife aus und die 
zweite if ...

von Bernd N (Gast)


Lesenswert?

>> if ((ADC_result >96) && (ADC_result <130))

oder sollte es if ((ADC_result > 96) || (ADC_result < 130)) sein ?

von Karl H. (kbuchegg)


Lesenswert?

Bernd N schrieb:
>>> if ((ADC_result >96) && (ADC_result <130))
>
> oder sollte es if ((ADC_result > 96) || (ADC_result < 130)) sein ?

Nö.
Denn ausnahmslos für jede Zahl von -unendlich bis +unendlich gilt, dass 
sie entweder größer als 96 ODER kleiner als 130 ist. Für manche Zahlen 
gilt sogar beides. Aber eines von beiden gilt immer.
30 ist zwar nicht größer als 96, aber es ist kleiner als 130.
280 ist zwar nicht kleiner als 130, aber es ist größer als 96.

von Karl H. (kbuchegg)


Lesenswert?

Stefan Frings schrieb:

> Also demnach etwa so abfragen:
>
> if (spannung <= 100mV) was dann passieren soll, hast Du vergessen,
> festzulegen
>
> else if (spannung > 100mV) dann soll nichts passieren
>
> else if (spannung > 180mV) dann soll die erste if schleife durch
> schalten
>
> else if (spannung > 270mV) dann soll die erste if schleife aus und die
> zweite if ...

Aber dann bitte die Reihenfolge der Abfragen umdrehen.
Denn 290 ist größer als 100. Und in dem Fall wäre es dann fatal, wenn 
das erste if zuschlägt und .... nichts tut. Die restlichen else-if 
kommen dann gar nicht mehr zum Zug.


Bei solchen Dingen immer probehalber mit ein paar Zahlen im Kopf die 
Abfragen durchgehen. Da verhaut man sich leicht und schnell.

(Zum Thema if-Schleife sag ich jetzt mal nichts :-)

von Karl H. (kbuchegg)


Lesenswert?

> Am ADCO 0 habe ich ein einstellbare Spannung von 100 mv bis
> 400 mv anliegen wo ich auswerten möchte.

Was hast du da verschaltet?
Masseverbindung hast du hergestellt?

Abgesehen davon würde ich das alles mal radikal abspecken.
Anstelle einer Spannung von 100 bis 400mV würde ich da erst mal ein 10k 
Poti als Spannungsteiler zwischen Vcc und GND vom µC schalten und mit 
dem Abgriff auf den ADC0 Pin.

Dann nehm ich Vcc als Referenzspannung im Programm.
ADIE braucht kein Mensch und führt nur zu Fehlern sobald erst mal 
Interrupts aktiviert sind.
Überhaupt würde ich erst mal die Routinen aus dem AVR-GCC-Tutorial 
so wie sie sind, als Basis für den ADC nehmen.
http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial/Analoge_Ein-_und_Ausgabe
Dann fliegt das ganze Gedöhns mit Seitenruder und Blinken und was weiß 
ich noch was, raus. Zieht den Code nur in die Länge und trägt nichts zum 
Testen des ADC bei.

Dann kommt ganz simpler Code. 1 ADC Eingang - 1 AUsgang an dem von mir 
aus 1 LED hängt
1
int main()
2
{
3
  DDRD |= (1<<PD0);
4
5
  ADC_Init();
6
7
  while( 0 ) {
8
    if( ADC_Read( 0 ) > 512 )
9
      PORTD |= (1<<PD0);
10
    else
11
      PORTD &= ~(1<<PD0);
12
  }
13
}


und erst wenn das beim Drehen am Poti die LED korrekt ein/aus macht, 
erst DANN arbeite ich weiter in die Richtung, in die ich eigentlich 
will.

Nicht 5 Schritte auf einmal machen, sondern einen nach dem anderen und 
beim einfachsten anfangen.

von Uwe (de0508)


Lesenswert?

Hallo Karl-Heinz,

ich bin erschreckt, suche ich nach diesem frei erfundenen Begriff hier 
im Forum gibt es von Google 5.520 Ergebnisse.

So ist klar, dass sich Anfänger derer Bezeichnungen bemächtigen, auch 
wenn sie nichts aussagen !

von Torsten (Gast)


Lesenswert?

Hallo,

mein Programm funktioniert nur habe ich nicht die errechnete 
Analog-Werte genommen.
Mit den doppelten Werten funktioniert es.

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.