Forum: Mikrocontroller und Digitale Elektronik ADC Ergebnis auf dem Display ausgeben


von Philip K. (praktikant)


Lesenswert?

Hallo!

habe nun meinen ADC zum Laufen gebracht. Das Problem ist jetzt, dass er 
mir anstatt einem vernünftigen Ergebnis (z.B. 3,5V) lediglich die 
ASCII-Zeichen ausgibt.

Das ist der Code:

uint8_t lese_Temperatur(void)
{
     ADMUX = 0xE0;
     ADCSRA = 0x85;      //4MHz:32;

     uint8_t x=0;


    //Start conversion
    ADCSRA |= (1<<ADSC);

    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}

    // get converted value
    x = ADCH;

    // output the higher 8 bits
  return x;
}

Mir ist klar, dass da noch keine Umwandlung von uint8_t zu float gemacht 
wird. Nur wie kann ich das realisieren?!

Habe schon versucht, die Tausender-, Hunderter-, Zehner- und 
Einerstellen separat zu berechnen, er gibt aber trotzdem nichts 
Vernünftiges aus.

Mein Controller: ATmega16
Umgebung: AVR Studio 4 + WinAVR
Display mit HD44780-Controller im 4bit Modus.

Wäre cool, wenn mir der Eine oder Andere von euch helfen könnte....

Gruß

der Praktikant

von johnny.m (Gast)


Lesenswert?

> ...lediglich die ASCII-Zeichen ausgibt.
Dann solltest Du Dich fragen, wo er irgendwelche ASCII-Zeichen hernimmt. 
In dem geposteten Codeschnipsel (Ich glaub ich hab heute schon mal in 
einem anderen Thread gefragt, warum zum Geier immer nur nichtssagende 
Fragmente geschickt werden und keine einigermaßen vollständigen 
Programme...) ist jedenfalls nichts in Sachen ASCII drin...

Wenn Du den Wert auf dem Display darstellen willst, musst Du ihn 
zunächst mal umrechnen. Anschließend kann er dann in einen ASCII-String 
umgewandelt und aufs Display gerotzt werden...

von Rahul, der Trollige (Gast)


Lesenswert?

>uint8_t lese_Temperatur(void)

es heisst: "lies_Temperatur"!

>anstatt einem vernünftigen Ergebnis
Den Dativ ist dem Genitiv sein Tod.

>Wäre cool, wenn mir der Eine oder Andere von euch helfen könnte....

Noch cooler wäre es, wenn du dein komplettes Programm posten würdest.

Was willst du ausgeben? Spannungen? Den ADC-Wert? In welchen 
Zahlen-Darstellung?

von Rahul, der Trollige (Gast)


Lesenswert?

*mal Johnny's Voodoo-Püppchen suchen geht...

von Karl H. (kbuchegg)


Lesenswert?

Während Rahul wieder mit der Puppe spielt
und Johnny sich am Boden windet:

In der Zwischenzeit, soll sich der Original-Poster
mal das hier durchlesen:
http://www.mikrocontroller.net/articles/FAQ#Wie_kann_ich_Zahlen_auf_LCD.2FUART_ausgeben.3F

von hereinspaziert (Gast)


Lesenswert?

Ohne groß mit Floatwerten rechnen zu müssen wären DIV und MODULO deine 
Freunde.

Mit dem DIV könntest du schonmal ganz einfach die Vorkommastelle 
berechnen.
Das mal als kleinen Denkanstoß..

von Rahul, der Trollige (Gast)


Lesenswert?

>Während Rahul wieder mit der Puppe spielt
>und Johnny sich am Boden windet:

LOL

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

so, hier ist das vollständige programm.....obwohl das nicht viel mehr 
ist als der codeschnipsel von vorhin g

von Rahul, der Trollige (Gast)


Lesenswert?

>ADC_einlesen_LCD_ausgeben.zip

Wieso ziped man eine Text-Datei?

von Philip K. (praktikant)


Lesenswert?

Rahul, der Trollige wrote:
>>ADC_einlesen_LCD_ausgeben.zip
>
> Wieso ziped man eine Text-Datei?

Weil es ein ganzes Projekt des AVR Studio 4 ist....

von Karl H. (kbuchegg)


Lesenswert?

Hast du hier schon mal reingeschaut?

http://www.mikrocontroller.net/articles/FAQ#Wie_ka...

von Steffen (Gast)


Lesenswert?

Der Artikel mit der Ausgabe is ja auch sehr clever in der 
Artikelsammlung untergebracht.
Wer kommt denn schon bei FAQ auf LDC/UART Ausgabe.

von hereinspaziert (Gast)


Lesenswert?

Um wenigstens den ADC-Wert als solches auszugeben, ist der Artikel 
durchaus ne Hilfe, aber eine Umrechnung wirst du nicht vermeiden können. 
Es sei denn du verzichtest auf ein gewisses Maß an Genauigkeit und legst 
ne Tabelle an und vergleichst den aktuellen Wert mit den Einträgen in 
der Tabelle.
Dann kann man relativ einfach mit nem switch..case die entsprechenden 
Strings ausgeben.

Aber die Umrechnung finde ich persönlich eleganter.

von Karl H. (kbuchegg)


Lesenswert?

@Steffen

Spielt überhaupt keine Rolle. Wer sowas fragen muss, der
durchsucht weder das Forum noch die Artikelsammlung.
Nein, der frägt einfach. Selbst wenn dieses Thema in
einem anderen Posting 20 Sekunden vorher abgearbeitet wurde
und der Postingtitel schon schreit: 'lies mich, lies mich'.

Selbst wenn man auf der Hauptseite in grossen roten Buchstaben
eine Anleitung für sprintf, ito oder eine händische Lösung
schreiben würde, würde genau diese Frage noch immer mindestens
20 mal die Woche auftauchen.

Du musst schon froh sein, wenn einer das Tutorial alleine
findet.

von Werner (Gast)


Lesenswert?

>Du musst schon froh sein, wenn einer das Tutorial
>alleine findet.
... oder nicht direkt in die Codesammlung postet ;-)

von Steffen (Gast)


Lesenswert?

@KHB
So schlimm??
kann ich mir gar nich vorstellen, ich such auch immer erst ne runde 
durch die Codesammlung und µElektronik bevor ich anscheinend doofe 
Fragen stelle.

Manche wollens einfach aufm Silbertablett serviert bekommen andere 
suchen erstmal so isses halt.

von Rahul, der Trollige (Gast)


Lesenswert?

>würde genau diese Frage noch immer mindestens 20 mal die Woche auftauchen.
Das liegt ja nun leider auch daran, dass die ADCs der AVR sich völlig 
von einander unterscheiden, Display keinem Standard gehorchen und C 
sowieso völlig unterschiedlich ist. Ausserdem sind solche Probleme ja 
auch nie gleich...Es muß doch eine bessere Lösung geben, als die 
Standard-Lösung (oder doch mit t? ;-), irgendwer hat die bestimmt schon, 
rückt sie aber nicht raus - vielleicht wird sie mir ja erzählt, wenn ich 
"Hilfe!" oder "Geht nicht!" in die Betreffzeile schreibe, oder nur 
Codefragmente poste...
Irgendwie bin ich heute etwas genervt...

von Rahul, der Trollige (Gast)


Lesenswert?

>bevor ich anscheinend doofe Fragen stelle

Dafür gehe ich lieber in den Chat. Da kann man dann auch noch so 
"rumblödeln"...

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

So, gut, jetzt weiß ich wenigstens, wie das mit der Umrechnung 
geht....nicht wirlich kompliziert.

Nur hab ich jetzt das Problem, wenn ich mit:

sprintf( Buffer, "%d", x ); //x ist das ADC-Wandlungsergebnis
    lcd_puts( Buffer );

die Daten an das LCD sende und die Zahl wieder kleiner wird, die letzte 
Ziffer trotzdem stehen bleibt. Wenn also mal 120 angezeigt wurde und ich 
zurück auf z.B. 77 drehe steht dann nachher 770 auf dem LCD....

Versuche ich das zu umgehen, indem ich eine for-Schleife als 
Warteschleife mißbrauche, dann die Stellen mit Leerzeichen überschreibe 
und anschließend das richtige Ergebnis darüberschreibe, das LCD 
flackert....

Code der Warteschleife:

lcd_gotoxy(0,1);
lese_Temperatur();
for(i=0; i<1500; i++){};
lcd_gotoxy(0,1);
lcd_puts("   ");


Das gesamte Projekt ist im Anhang!

von johnny.m (Gast)


Lesenswert?

Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an
1
sprintf( Buffer, "%3d", x );
Dann werden immer drei Stellen ausgegeben. Ich würde aber für sowas 
nicht sprintf nehmen, weil ich i.d.R. mit meinen Speicherressourcen ein 
wenig haushalte. Nimm lieber die Transformationsfunktionen aus der 
stdlib.h (in diesem Falle itoa)...

von Philip K. (praktikant)


Lesenswert?

Rahul, der Trollige wrote:
>>würde genau diese Frage noch immer mindestens 20 mal die Woche auftauchen.
> Das liegt ja nun leider auch daran, dass die ADCs der AVR sich völlig
> von einander unterscheiden, Display keinem Standard gehorchen und C
> sowieso völlig unterschiedlich ist. Ausserdem sind solche Probleme ja
> auch nie gleich...Es muß doch eine bessere Lösung geben, als die
> Standard-Lösung (oder doch mit t? ;-), irgendwer hat die bestimmt schon,
> rückt sie aber nicht raus - vielleicht wird sie mir ja erzählt, wenn ich
> "Hilfe!" oder "Geht nicht!" in die Betreffzeile schreibe, oder nur
> Codefragmente poste...
> Irgendwie bin ich heute etwas genervt...

Hm.....dann schau doch gar nicht mehr rein in den Thread? Anscheinend 
ist deine Neugier doch recht groß......

von Rahul, der Trollige (Gast)


Lesenswert?

>Anscheinend ist deine Neugier doch recht groß......

Manchmal habe ich auch einfach nur einen Drang zum Masochismus...

von Philip K. (praktikant)


Lesenswert?

johnny.m wrote:
> Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an
>
1
> sprintf( Buffer, "%3d", x );
2
>
> Dann werden immer drei Stellen ausgegeben. Ich würde aber für sowas
> nicht sprintf nehmen, weil ich i.d.R. mit meinen Speicherressourcen ein
> wenig haushalte. Nimm lieber die Transformationsfunktionen aus der
> stdlib.h (in diesem Falle itoa)...

Okay, danke! Das war die Lösung die ich gesucht habe....

die itoa() habe ich gerade ausprobiert....da ist das gleiche Problem, 
dass die letzten Nulen stehen bleiben und das Ergebnis verfälschen....

von hereinspaziert (Gast)


Lesenswert?

Naja ne UMRECHNUNG ists ja nicht gerade...
Das Flackern liegt wohl an den zu häufigen Updates auf dem Display.
1500 Cycles @ 4MHz sind in etwa 0,4µs. Wenn der C-Compiler schlecht 
optimiert sinds bestimmt aber immer noch nur 1-2µs. Der AD-Wandler 
schafft auch einige Tausend Wandlungen pro Sekunde.
D.h. das Display wird so oft, wie die Display-Routinen es zulassen 
geupdatet. (Ich schätze mal so einige 100mal pro Sekunde - vielleicht n 
bischen oft)

Denk mal über nen Timer nach. Ich denke mal mehr als 1-2 Messwerte pro 
Sekunde kann man eh nicht sinnvoll mit Augen und Verstand erfassen.

von Rahul, der Trollige (Gast)


Lesenswert?

>0,4µs
Dürften eher 0,4ms sein... (1500/4MHz = 375µs =~ 0,4ms)

von johnny.m (Gast)


Lesenswert?

> die itoa() habe ich gerade ausprobiert....da ist das gleiche Problem,
> dass die letzten Nulen stehen bleiben und das Ergebnis verfälschen....
Das ist richtig, weil itoa keinen Ausgabebreite-Parameter hat. Aber es 
ist doch nicht so schwer, den String entsprechend zu manipulieren, dass 
die Breite immer stimmt. Und itoa ist wesentlich ressourcenschonender.

von hereinspaziert (Gast)


Lesenswert?

oh, stimmt 0,4ms

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

so, der Code funktioniert......

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

und der code tut nüscht....

gibt ne warning aus:

double format, float arg (arg3);

Und auf dem Display steht an der Stelle, an der normalerweise meine Zahl 
ausgegeben wird, ein Fragezeichen! Ich kapiers einfach nicht....wo liegt 
da der Hund begraben?!

von Werner (Gast)


Lesenswert?

Tja, der letzte funktionierende Code ist 28.7 KB, der neue 28.8 KB. Was 
wurde geändert?

von Philip K. (praktikant)


Lesenswert?

Werner wrote:
> Tja, der letzte funktionierende Code ist 28.7 KB, der neue 28.8 KB. Was
> wurde geändert?

Dass ich beim 2. eine float-Zahl auf dem Display ausgeben wollte....
Aber sprintf() nimmt keine floats?!?!

Code, der nicht tut:

#include <avr\io.h>


uint8_t lese_Temperatur();
void berechnen_VStrom();
float lese_Absolutdruck(void);
float lese_Differenzdruck(void);

int main (void)
{

while(1)
  {
    lese_Temperatur();
  }
}




void lese_Temperatur(void)
{
  ADMUX = 0xE0;
  ADCSRA = 0x85;      //4MHz:32;

  int x=0;
  double a=0.0;
  char Buffer[20];

    //Start conversion
    ADCSRA |= (1<<ADSC);

    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}

    //get converted value
    x = ADCH;

  a=7.4;
    sprintf(Buffer, "%5.2f", a);
  x = x + 1.0 ; //Dummy-Zeile um Breakpoint zu setzen.

  //return x;

}

von Karl H. (kbuchegg)


Lesenswert?

> Dass ich beim 2. eine float-Zahl auf dem Display ausgeben wollte....
> Aber sprintf() nimmt keine floats?!?!

Alles klar.

Das Problem ist, dass der WinAvr die Floating Point Version
der xprintf() Funktionen nicht einbindet. Da musst du
deine Linkersettings umstellen.

Such mal im gcc Forum nach 'printf float'

Beitrag "ATmega16, WinAVR und float"


von Philip K. (praktikant)


Lesenswert?

Es ist aber doch richtig, wenn ich Dezimalzahlen mit Komma ausgeben 
möchte, dass ich dann wohl den Datentyp float nicht umgehen 
kann....zumindest sagen mir das meine C-Kenntnisse..... Oder sollte ich 
falsch liegen?!

Gruß

der Praktikant

von Falk (Gast)


Lesenswert?

@Philip Kottmann

>Es ist aber doch richtig, wenn ich Dezimalzahlen mit Komma ausgeben
>möchte, dass ich dann wohl den Datentyp float nicht umgehen
>kann....zumindest sagen mir das meine C-Kenntnisse..... Oder sollte ich
>falsch liegen?!

Du liegst falsch. Man kann auch wunderbar mit Integer/Festkomma 
arbeiten. Z.B. nimmt man ein long (32 Bit) und verwendet die oberen 16 
Bit für den Ganzzahl-Anteil und die unteren 16 Bit für die 
Nachkommastellen.

MFG
Falk

von Karl H. (kbuchegg)


Lesenswert?

Du liegst falsch.
Nur weil am Display ein Komma auftaucht, heist das
noch lange nicht, dass da Gleitkommzahlen im Spiel
sind. Es heist nur, dass irgendeine Ausgaberoutine
ein Komma hingepinselt hat.

Wenn du 2487 Meter als Kilometer ausgeben möchtest,
kannst du so vorgehen.

2487 / 1000   macht 2. Also sind das schon mal
2 ganze Kilometer.
Danach pinselst du ein Komma aufs Display
Und dann noch den Nachkommaanteil:
2487 % 1000 macht 487
Das auch noch hingepinselt, und schon steht am Display
2,487

% ist der Restoperator. Also: Wenn man 2487 durch 1000
ganzzahlig dividiert, wieviel Rest bleibt dann.


Pass aber beim Ausgeben auf. Beim Nachkommaanteile dürfen
führende Nullen nicht wegfallen. 2,05 ist was anderes als 2,5

von Philip K. (praktikant)


Lesenswert?

Hier ist nun meine Version der Berechnung des Spannungswertes. 
Eigentlich sollte er die versch. Deszimalstellen korekt berechnen, gibt 
aber auf dem Display immer nur 0,000 aus. Was stimmt bei der Übergabe 
der versch. Werte nicht?

Vielen Dank für eure Hilfe

der Praktikant

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

hier die zip-datei g

von Rahul, der Trollige (Gast)


Lesenswert?

>ADC_einlesen_LCD_ausgeben.zip

Kannst du hier nicht vielleicht einfach nur das .c-File anhängen?
Ich will nicht dein ganzen Projekt haben...

von Philip K. (praktikant)


Lesenswert?

Rahul, der Trollige wrote:
>>ADC_einlesen_LCD_ausgeben.zip
>
> Kannst du hier nicht vielleicht einfach nur das .c-File anhängen?
> Ich will nicht dein ganzen Projekt haben...

Okay, wenn ich das .c-File anhänge motzt gleich der nächste, warum ich 
denn nur code-fetzen poste....deshalb gibts alles...........

von Rahul, der Trollige (Gast)


Lesenswert?

>Okay, wenn ich das .c-File anhänge motzt gleich der nächste, warum ich
>denn nur code-fetzen poste....deshalb gibts alles...........

Dann bin ich raus...

von Wolfram (Gast)


Lesenswert?

>auf dem Display immer nur 0,000


>x = ADCH;
>  faktor = 196;        //19,6mV * 10
>  ausgangswert = x*10;      //x um eine Null erweitert...
>
>  vorkomma = ausgangswert / 100000;
>  zehntel = (ausgangswert%100000)/10000;
>  hundertstel = (zehntel%10000)/1000;
>  tausendstel = (hundertstel%1000)/100;

>x = ADCH;
x ist eine Zahl zwischen 0 und 255
>ausgangswert = x*10;
ausgangswert ist eine Zahl zwischen 0 und 2550
>vorkomma = ausgangswert / 100000;
größte Zahl ausgangswert 2550
vorkomma= 2550 / 100000= 0 bei Integer
>zehntel = (ausgangswert%100000)/10000;
2550%100000=2550 <-was soll das, das ist sinnlos
x%100000=x für x<100000
2550/10000 gibt immer noch 0 für integer
ich denke den Rest kannst du selbst nachvollziehen...

Ein C-Compiler macht das was du sagst, nicht das was du denkst (gesagt 
zu haben)
Wenn du einen Algorithmus entwirfst, sollte er als erstes auf dem Papier 
funktionieren. Anscheinend versuchst du diesen Schritt zu überspringen. 
Das funktioniert nicht! Das zeigst du hier hervorrragend. Du hast kein 
Problem bei der Übergabe, du hast ein Problem mit der Mathematik. Dies 
verhinderst du, wenn du den Algorithmus erstmal auf dem Papier entwirfst 
und überprüfst.
Die folgende Verwendung von sprintf ist extrem umständlich.
Das Lesen eines C- Buches ist durch kein Forum zu ersetzen.

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

Hallo Wolfram!

Hab selbst bemerkt, dass in meiner Rechnung der eine der andere Fehler 
versteckt war....

Mein aktuelles .c-File mit der Rechnung ist im Anhang.... Es gibt aber 
leider bis auf das "," nichts vernünftiges aus.

habe die Libraries von Peter Fleury benutzt (zwecks lcd_puts, etc).....

von Rahul, der Trollige (Gast)


Lesenswert?

Hast du mal einen Wert in "ausgabewert" geschrieben, ohne den ADC zu 
benutzen und dann ausgegeben?

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

ja, so!

gibt nur "||" aus....... aber die Verwendung von lcd_puts() und 
lcd_putc() ist doch in meinem Fall schon richtig?!

von Rahul, der Trollige (Gast)


Lesenswert?

Mach das mal so (für alle "buffer"):
buffer[4] = (ausgangswert/10000) + '0';

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

Und wenn ich es wie in der Anlage direkt in main() einbinde gibt er "5" 
aus...

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

Hab jetzt einmal für alle "buffer" das ganze so geschreiben:

buffer[4] = (ausgangswert/10000) + '0';
buffer[3] = (ausgangswert/10000) + '0';
buffer[2] = (ausgangswert/10000) + '0';
buffer[1] = (ausgangswert/10000) + '0';
buffer[0] = (ausgangswert/10000) + '0';

und nochmal so, wie in der Anlage.

Beides hat nicht wirklich zu einem Ergebnis geführt.....

von Rahul, der Trollige (Gast)


Lesenswert?

>buffer[4] = (ausgangswert/10000) + '0';
>buffer[3] = (ausgangswert/10000) + '0';
>buffer[2] = (ausgangswert/10000) + '0';
>buffer[1] = (ausgangswert/10000) + '0';
>buffer[0] = (ausgangswert/10000) + '0';

Denkst du auch mit?

So gehört das:
  buffer[4] = (ausgangswert/10000) + '0';
  buffer[3] =  ',';
  buffer[2] = ((ausgangswert%10000)/1000) + '0';
  buffer[1] = ((buffer[2]%1000)/100) + '0';
  buffer[0] = ((buffer[1]%100)/10) + '0';

von Philip K. (praktikant)


Lesenswert?

hast du in die anlage geschaut? da ist das so!

mir erschien das auch schwachsinnig. aber ich hab alle möglichkeiten 
durchgemacht...

von Rahul, der Trollige (Gast)


Lesenswert?

>hast du in die anlage geschaut? da ist das so!
nee...

von Philip K. (praktikant)


Lesenswert?

klar ist das dort so....

von Rahul, der Trollige (Gast)


Lesenswert?

>ausgabewert = '45';

Da gibt es das kleine Problem, dass '' einen Char einschliessen und "" 
einen String...

Sowas schon probiert:

buffer[4] = '0';
buffer[3] = ',';
buffer[2] = '0';
buffer[1] = '4';
buffer[0] = '5';

(Nein, ich habe mir nicht alle Postings dieses Thread angeguckt!)

von Philip K. (praktikant)


Lesenswert?

okay, wenn ich das einbinde und über lcd_putc(buffer[1]) versuche die 
'4' auszugeben, dann tut er das.....

von Philip K. (praktikant)


Lesenswert?

also so sieht meine funktion jetzt aus:

void lese_Temperatur(void)
{
  ADMUX = 0xE0;
  ADCSRA = 0x85;      //4MHz:32;

  long int x_h=0, x_l=0, faktor=0, ausgangswert=0;
  char buffer[20];


    //Start conversion
    ADCSRA |= (1<<ADSC);

    // wait until converstion completed
    while (ADCSRA & _BV(ADSC) ) {}

    //get converted value
    x_h = ADCH;
  x_l = ADCL;

  faktor = 196;            //19,6mV * 10
  ausgangswert = faktor * x_h;        //faktor * x_h;

  /*buffer[4] = '0';
  buffer[3] = ',';
  buffer[2] = '0';
  buffer[1] = '4';
  buffer[0] = '5';*/


  buffer[4] = (ausgangswert/10000) + '0';
  buffer[3] =  ',';
  buffer[2] = ((ausgangswert%10000)/1000) + '0';
  buffer[1] = ((buffer[2]%1000)/100) + '0';
  buffer[0] = ((buffer[1]%100)/10) + '0';

  lcd_putc(buffer);
}

Ich multipliziere den Wert zw. 0 und 255 (wert x_h) mit dem Faktor von 
196.

dann versuche ich, die zahl die dabei rauskommt interpretierbar zu 
gestalten. Also 1 Zahl vor dem Komma, die anderen dahinter.
und über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf 
einmal ausgspuckt werden.

oder muss ich nach jeder ausgabe eines buffer-feldes eine stelle 
weiterspringen mit lcd_gotoxy() und dort dann das nächste ergebnis 
hineinschreiben?!

von Rahul, der Trollige (Gast)


Lesenswert?

>dann tut er das.....
Fehler in der Berechnung, oder?

Für sowas baue ich mir dann eine "manuelle" Division:

verglwert = 10000;
i=0;
while (verglwert>10)
{
  buffer[i]='0';
  while(ausgabewert>=verglwert)
  {
   buffer[i]++;
   ausgabewert -= verglwert;
  }
  i++;
  verglwert /=10;
}

lcd_putc(buffer[0]);
lcd_putc(',');
lcd_putc(buffer[1]);
lcd_putc(buffer[2]);
lcd_putc(buffer[3]);



von johnny.m (Gast)


Lesenswert?

> buffer[1] = ((buffer[2]%1000)/100) + '0';
> buffer[0] = ((buffer[1]%100)/10) + '0';
Was soll das "buffer[x]" da in der Rechnung? Da müsste doch wohl 
"ausgangswert%1000" usw. stehen...

von Rahul, der Trollige (Gast)


Lesenswert?

>über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf
>einmal ausgspuckt werden.

Nein, lcd_putc() schreibt nur ein Zeichen aufs Display.
Wenn, dann musst du lcd_puts() benutzen und "buffer" vermutlich um ein 
Zeichen verlängern ('\0'), damit lcd_puts() das Ende des Trings erkennt.

von Wolfram (Gast)


Lesenswert?

>über die ausgabe lcd_putc(buffer) müsste doch der gesamte buffer auf
>einmal ausgspuckt werden
putc ist gewöhnlich zur Ausgabe eines char (eines Zeichens)

von Philip K. (praktikant)


Lesenswert?

Mir gibt irgendwie zu denken, dass meine Variable "faktor" und 
"ausgangswert" als "unsigned long int" definiert sind. Nach der 
Umrechnng sollen sie aber in einem Feld von "char" stehen..... kannd as 
unktionieren?! Irgendwohin müssen ja die 24 Bit Differenz 
verschwinden?!?!

von Rahul, der Trollige (Gast)


Lesenswert?

Das macht der Compiler durch einen "cast" ganz von alleine.

von Karl H. (kbuchegg)


Lesenswert?

1
void lese_Temperatur(void)
2
{
3
  ADMUX = 0xE0;
4
  ADCSRA = 0x85;      //4MHz:32;
5
6
  long int x_h=0, x_l=0, faktor=0, ausgangswert=0;
7
  char buffer[20];
8
9
10
    //Start conversion
11
    ADCSRA |= (1<<ADSC);
12
13
    // wait until converstion completed
14
    while (ADCSRA & _BV(ADSC) ) {}
15
16
    //get converted value
17
    x_h = ADCH;
18
  x_l = ADCL;
19
20
  faktor = 196;            //19,6mV * 10
21
  ausgangswert = faktor * x_h;        //faktor * x_h;
22
23
  sprintf( buffer, "%ld,%04ld", ausgangswert / 10000, ausgangswert % 10000 );
24
  lcd_puts( buffer );
25
}

sprintf ist natürlich eine teure Funktion. Wenn du den
Platz im AVR hast, spielt das keine Rolle. Ansonsten
müsste man dafür einen gleichwertigen Ersatz schreiben.

lcd_putc     .... gibt ein einzelnes Zeichen aus
lcd_puts     .... gibt einen String aus, also eine Abfolge
                  von Zeichen, die mit '\0' abgeschlossen ist.

Ich hab auch nicht kontrolliert ob der ADC Code sinnvoll ist,
sprich: ob in x_h überhaupt was Sinnvolles steht. Wenn der
Code jetzt immer noch 0,0000 hinschreibt, dann liegt es an
deinem ADC Abfrage Code.



von Philip K. (praktikant)


Lesenswert?

> Ich hab auch nicht kontrolliert ob der ADC Code sinnvoll ist,
> sprich: ob in x_h überhaupt was Sinnvolles steht. Wenn der
> Code jetzt immer noch 0,0000 hinschreibt, dann liegt es an
> deinem ADC Abfrage Code.


der ADC gibt auf jeden fall was sinnvolles aus. Das hab ich auch 
abgefragt. die werte bewegen sich so, wie sie sollen zwischen 0 und 255. 
also das passt, da bin ich mir sicher.....

von Rahul, der Trollige (Gast)


Lesenswert?

Wie sieht es denn nun in deinem Programmcode aus?

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

so siehts aus.

er zeigt mir sofort nach dem einschalten den richtigen spannungswert 
an.... aber wenn ich die spannung verändere, dann tut sich nix. schalte 
ich ihn wieder aus und wieder ein steht der richtige spannungswert 
da....
funktioniert also, aber nicht "online".....

von Karl H. (kbuchegg)


Lesenswert?

> er zeigt mir sofort nach dem einschalten den richtigen spannungswert
> an....

Das glaub ich nicht, Tim:


>   buffer[0] = (ausgangswert/10000) +0x30;
>  buffer[1] =  ',';
>  buffer[2] = ((ausgangswert%10000)/1000)+0x30;
>  buffer[3] = ((buffer[2]%1000)/100)+0x30;
>  buffer[4] = ((buffer[3]%100)/10)+0x30;
>  buffer[5] = '\0';

Schau noch mal in die Zeile in der du Buffer[3]
berechnest. Schau noch mal genau hin! Auf Grund
welcher Daten wird Buffer[3] berechnet?
Selbiges für Buffer[4]

> schalte ich ihn wieder aus und wieder ein steht der richtige
> spannungswert da....

Ich denke du hast den ADC Code schon durchgetestet?

Das übliche Problem:
zuerst ADCL auslesen und erst dann ADCH


von Rahul, der Trollige (Gast)


Lesenswert?

>x_l = ADCL;

Das dürfte das Problem sein...

von Philip K. (praktikant)


Angehängte Dateien:

Lesenswert?

okay, so funktionierts!

danke an alle!!

von Wolfram (Gast)


Lesenswert?

>> //get converted value
>>  x_l = ADCL;
>>    x_h = ADCH;
>>  vari = (x_h<<2) | x_l;

der kommt wieder....

von Philip K. (praktikant)


Lesenswert?

hm....nö, bisher tut alles.....lag nur daran, das ich zuerst die 
High-Bits der AD-Wandlung und dann die Low-Bits abgefragt habe..... 
Andersrum (so wie es im Manual steht) gehts problemos auch "online"....

von Rahul, der Trollige (Gast)


Lesenswert?

>>> //get converted value
>>>  x_l = ADCL;
>>>    x_h = ADCH;
>>>  vari = (x_h<<2) | x_l;

>der kommt wieder....

Die Abfragen-Reihenfolge ist dch richtig.
Das ADC(H)-Register wird fürs Beschreiben gesperrt, wenn ADCL gelesen 
wird.
Man kann sich das Auslesen von ADCL auch sparen, wenn ADLAR = 1 ist.

von Karl H. (kbuchegg)


Lesenswert?

Wolfram wrote:
>>> //get converted value
>>>  x_l = ADCL;
>>>    x_h = ADCH;
>>>  vari = (x_h<<2) | x_l;
>
> der kommt wieder....

Yep. Dann warten wir mal wie lange es dauert bis er merkt
dass seine Werte nicht stimmen.

von Karl H. (kbuchegg)


Lesenswert?

Rahul, der Trollige wrote:
>>>> //get converted value
>>>>  x_l = ADCL;
>>>>    x_h = ADCH;
>>>>  vari = (x_h<<2) | x_l;
>
>>der kommt wieder....
>
> Die Abfragen-Reihenfolge ist dch richtig.

Schau dir mal den Zusammenbau des Gesamtergebnisses
an.

Manchmal frag ich mich schon was so toll am einzelnen
Auslesen von 2 8-Bit Registern ist. Der Compiler
könnte das alles ganz von alleine richtig machen.
Nur benutzen muesste mans halt.

von Rahul, der Trollige (Gast)


Lesenswert?

>vari = (x_h<<2) | x_l;

LOL

Warum liest er nicht einfach ADC in eine int-Variable ein?
Also so:
vari = ADC;

von Rahul, der Trollige (Gast)


Lesenswert?

>Schau dir mal den Zusammenbau des Gesamtergebnisses
>an.

Gerade gesehen...(und verbessert...)

von Karl H. (kbuchegg)


Lesenswert?

Was mich viel trauriger stimmt:

Das geht ja jetzt schon eine ganze Weile so. Ich geh
mal davon aus, dass er eine bekannte Spannung am ADC
anliegen hat. Und nicht merkt, dass seine Ausgabe
einen ganz anderen Wert anzeigt.
Also das alte Spiel: Debuggen ohne zunächst mal zu wissen
was eigentlich rauskommen müsste.

von Rahul, der Trollige (Gast)


Lesenswert?

>Debuggen ohne zunächst mal zu wissen, was eigentlich rauskommen müsste.

Dann kommt die Frage "Mein Multimeter spinnt! Mein ADC zeigt diesen Wert 
an, mein Multimeter aber diesen..."

Gegenfrage darauf: "Hast du das Multimeter auf AC oder DC stehen?"

von Karl H. (kbuchegg)


Lesenswert?

Das wird überhaupt noch lustig

  ADMUX = 0xE0;

ADLAR ist gesetzt.

von Rahul, der Trollige (Gast)


Lesenswert?

>Das wird überhaupt noch lustig

>  ADMUX = 0xE0;

Sowas beachte ich inzwischen nicht mehr... (entweder ein "BV" oder 
"1<<").

Da würde dann noch sowas kommen wie "Tausch doch mal die Messspitzen 
gegeneinander aus!" ;-)

von Philip K. (praktikant)


Lesenswert?

Okay Jungs, alles klar.
Hätte mir eigentlich vorher klar sein sollen, dass hier von sozialer 
Kompetenz keine Spur sein wird.
Seht es doch mal so: Wenn ihr nicht gerne helft, dann lasst es einfach 
ganz bleiben. Sowas bringt mich nicht und euch erst recht nicht 
weiter...

In diesem Sinne

von Wolfram (Gast)


Lesenswert?

Also Fehleranalyse:
ADMUX = 0xE0;
left adjust, interne Referenz!
wow, das ist ja ein richtiger Hauptgewinn
>faktor = 196;            //19,6mV * 10
>ausgangswert = faktor * x_h;
faktor dürfte von 5000mV/(8bit) 256 *10 sein
interne Referenz 2,56V
das liefert wohl erstmal doppelt so grosse Werte

dann leftadjust bei
>> //get converted value
>>  x_l = ADCL;
>>    x_h = ADCH;
>>  vari = (x_h<<2) | x_l;

also verknüpfe x_h um 2 nach links geschiftet mit xl
das zerstört bei vari den Wert in den bits 7 und 6 von 0 gezählt.
Damit gibt es eine effektive Auflösung von 2 Bit, darunter kommen die 
zerstörten Bits über den Rest muss man wohl nicht sprechen.

von Rahul, der Trollige (Gast)


Lesenswert?

>Sowas bringt mich nicht und euch erst recht nicht weiter...

Vielleicht nicht weiter, aber Spaß...

>Hätte mir eigentlich vorher klar sein sollen, dass hier von sozialer
>Kompetenz keine Spur sein wird.

Nu hatter uns erwischt.

von Philip K. (praktikant)


Lesenswert?

Wolfram wrote:
> Also Fehleranalyse:
> ADMUX = 0xE0;
> left adjust, interne Referenz!
> wow, das ist ja ein richtiger Hauptgewinn

hä??

>>faktor = 196;            //19,6mV * 10
>>ausgangswert = faktor * x_h;
> faktor dürfte von 5000mV/(8bit) 256 *10 sein

nee, faktor ist die auflösung ~20mV x 10 (damit bei der berechnung das 
Komma rausfällt).

> interne Referenz 2,56V
> das liefert wohl erstmal doppelt so grosse Werte

nein, leifert es nicht. das was ich eingebe, kommt genauso auch bei der 
berechnung raus.

>
> dann leftadjust bei
>>> //get converted value
>>>  x_l = ADCL;
>>>    x_h = ADCH;
>>>  vari = (x_h<<2) | x_l;

das war bullshit, hab ich grade beim nachdenken auch gemerkt. wenn dann 
überhaupt:

x_1 = ADCL;
x_h = ADCH;
vari = (x_h<<8) | x_l;

>
> also verknüpfe x_h um 2 nach links geschiftet mit xl
> das zerstört bei vari den Wert in den bits 7 und 6 von 0 gezählt.
> Damit gibt es eine effektive Auflösung von 2 Bit, darunter kommen die
> zerstörten Bits über den Rest muss man wohl nicht sprechen.
richtig

von Wolfram (Gast)


Lesenswert?

>> faktor dürfte von 5000mV/(8bit) 256 *10 sein
>nee, faktor ist die auflösung ~20mV x 10 (damit bei der berechnung das
>Komma rausfällt).
der Faktor mit dem du arbeitest ist 196 , oder wie du es bezeichnest 
deine Auflösung. 19,6 mV
du arbeitest mit dem ADC in 8Bit (nur ADCH)
8bit =256
256*19,6mV =Fullrange=~5000mV =5V
wo hast du den Faktor her? du arbeitest mit der internen Referenz 2,56V 
laut initialisierung.

>nein, leifert es nicht. das was ich eingebe, kommt genauso auch bei der
>berechnung raus.
ist was du "eingibst" eine Spannung am ADC?

>x_1 = ADCL;
>x_h = ADCH;
>vari = (x_h<<8) | x_l;
ist immer noch falsch
left adjust heisst der ganze Wert in ADC(H/L) ist links anliegend
und es gab auch schon den Hinweis das es bequemer geht, siehe avrlibc 
Doku

du scheinst den gutgemeinten Rat ans Papier zurückzukehren nicht zu 
verstehen.
Du machst eine ganze Menge Fehler, weil du zu schnell ungeordnet 
arbeitest.
Lies das Datenblatt, mach es auf dem Papier und checke es dort erstmal 
durch und dann gehe auf den Mikrocontroller , wenn es nicht klappt 
zurück ans Papier mit der Fehlersuche und erst dann wenn es nicht klappt 
ins Forum. Sonst musst du dich nicht wundern wenn du hier "lustige" 
Kommentare findest.

von eProfi (Gast)


Angehängte Dateien:

Lesenswert?

Hat eingentlich schon mal jemand daran gedacht, die Umrechnung und die 
Zerlegung in einem Schritt zu machen?

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.