AD-Wandler Umrechnung

Gast #3177227
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
Gast #3177245
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...
Gast #3177247
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
Gast #3177456
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.
Angehängte Dateien:
Gast #3177543
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
#3177671
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
Gast #3177681
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.
#3177691
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.
#3177702
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.
Gast #3177964
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.
Angehängte Dateien:
#3178237
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..
.
Angehängte Dateien:
Gast #3178409
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?
Angehängte Dateien:
Gast #3178881
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?
Angehängte Dateien:
#3181518
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 ...
#3181552
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.
#3181557
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 :-)
#3181569
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.

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren