mikrocontroller.net

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


Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
*mal Johnny's Voodoo-Püppchen suchen geht...

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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_ka...

Autor: hereinspaziert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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ß..

Autor: Rahul, der Trollige (Gast)
Datum:

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

LOL

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>ADC_einlesen_LCD_ausgeben.zip

Wieso ziped man eine Text-Datei?

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hast du hier schon mal reingeschaut?

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

Autor: Steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: hereinspaziert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Werner (Gast)
Datum:

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

Autor: Steffen (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>bevor ich anscheinend doofe Fragen stelle

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

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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!

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an
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)...

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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ß......

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Anscheinend ist deine Neugier doch recht groß......

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

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
johnny.m wrote:
> Dann gib im sprintf-Aufruf eine minimale Ausgabebreite für x an
>
> 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)...

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

Autor: hereinspaziert (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul, der Trollige (Gast)
Datum:

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

Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: hereinspaziert (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
oh, stimmt 0,4ms

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
so, der Code funktioniert......

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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?!

Autor: Werner (Gast)
Datum:

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

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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;

}

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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"


Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Falk (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
hier die zip-datei g

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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...........

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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).....

Autor: Rahul, der Trollige (Gast)
Datum:

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

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
ja, so!

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

Autor: Rahul, der Trollige (Gast)
Datum:

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

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

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

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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.....

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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';

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
hast du in die anlage geschaut? da ist das so!

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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>hast du in die anlage geschaut? da ist das so!
nee...

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
klar ist das dort so....

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!)

Autor: Philip Kottmann (praktikant)
Datum:

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

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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?!

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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]);



Autor: johnny.m (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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...

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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)

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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?!?!

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das macht der Compiler durch einen "cast" ganz von alleine.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
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;

  sprintf( buffer, "%ld,%04ld", ausgangswert / 10000, ausgangswert % 10000 );
  lcd_puts( buffer );
}

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.



Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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.....

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wie sieht es denn nun in deinem Programmcode aus?

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht 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".....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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


Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>x_l = ADCL;

Das dürfte das Problem sein...

Autor: Philip Kottmann (praktikant)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
okay, so funktionierts!

danke an alle!!

Autor: Wolfram (Gast)
Datum:

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

der kommt wieder....

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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"....

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>vari = (x_h<<2) | x_l;

LOL

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

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Schau dir mal den Zusammenbau des Gesamtergebnisses
>an.

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

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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?"

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Das wird überhaupt noch lustig

  ADMUX = 0xE0;

ADLAR ist gesetzt.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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!" ;-)

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Rahul, der Trollige (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: Philip Kottmann (praktikant)
Datum:

Bewertung
0 lesenswert
nicht 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

Autor: Wolfram (Gast)
Datum:

Bewertung
0 lesenswert
nicht 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.

Autor: eProfi (Gast)
Datum:
Angehängte Dateien:

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

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.