integer Variable als Kommazahl

Gast #4636510
Lesenswert?

Hallo zusammen.

Ich möchte auf einem GLCD einen Spannungswert anzeigen lassen. Bis 2 
Stellen hinter dem Komma.
Beispiel: 5,74V

Aus der Funktion readADC() bekomme ich eine uint16_t Variable.

Wie kann ich das machen.?

Danke euch.
Angehängte Dateien:
Gast #4636552
Lesenswert?

Rufus Τ. F. schrieb:
> Du könntest Deinen Int in Text umwandeln lassen und das Komma an der
> passenden Stelle in den Text einfügen.
>
> Bestimme also nach dieser Zeile
>
> itoa(result,buffer1,10);
>
> die Länge des erzeugten Strings und verschiebe die letzten beiden
> Zeichen um eines und füge davor ein Komma ein.



wie soll ich die Variable aufsplitten.?

1002 zum Beispiel (10,02)

wenn ich dort ein Komma nach der 10 schreibe, entfällt die 2.Null
Gast #4636553
Lesenswert?

pio schrieb:
> Hallo zusammen.
>
> Ich möchte auf einem GLCD einen Spannungswert anzeigen lassen. Bis 2
> Stellen hinter dem Komma.
> Beispiel: 5,74V
>
> Aus der Funktion readADC() bekomme ich eine uint16_t Variable.
>
> Wie kann ich das machen.?
>
> Danke euch.

Folgendes angenommen:

De kleinste Einheit die dein ADC wandeln kann (LSB Wert) ist 1 mV.

Dann bekommst du in deinem Fall einen (unsigned) Integer Wert 5740.
Diesen Wert dividierst du mit 1000.  Das Resultat (5) wandelst
du nach ASCII und schiebst den WERT in  die 1. Stelle einer
Zeichenkette (auch Array genannt).
Darauffolgend belegst du das Array mit dem "," (0x2c).

Jetzt wird es spannend:

Als nächsten Schritt führst du eine "MODULO" Division durch 1000 durch.
Hier wird der "Rest" (750) als Wert zurückgegeben.

Das geschied folgender maßen:
Es wird die gleiche Division wie oben durchgeführt, jedoch wird das 
Ergebnis "5" mit 1000 multipliziert (5000) und dann vom ursprünglichen 
Wert (5740)
abgezogen und es bleibt 740 übrig.

Nachdem du nur 2 Kommastellen benötigst, dividierst du den Wert einfach 
durch 10.
Die 74 wandelst du einfach in eine 2 stellige Ascii Zeichenfolge um
und  hängst sie nach dem Komma in der Zeichenkette dran.

In einem Kochbuch würde stehen:

Man gibt die Zutaten (Array, ADC Werte, Gewürze und Funktionen)
in einen "C" Topf kocht es richtig auf,
und nach einer Stunde bekommt man eine Zeichenkette perfekt geignet
zum garnieren eines "LCD" Tellers ;-)

Sepp
Gast #4636576
Lesenswert?

pio schrieb:
> das ist richtig. aber wie kann ich die variable so auseinander nehmen.?

einfach stelle 5 auf stelle 6, stelle 4 auf stelle 5. Kann doch nicht so 
schwer sein.

buffer1[7] = 0;
buffer1[6] = buffer1[5];
buffer1[5] = buffer1[4];
buffer1[4] = ',';
Gast #4636580
Lesenswert?

pio schrieb:
> wo genau kommt nun die 5740 her.?
>
> result geht bei mir von 0...1023

Ich sagte ja nur "angenommen"

Du müsstest halt den "LSB" Wert wissen,
(der kleinste werd den der ADC liefert)

dann kann man das Ganze ja nochmals durchexerzieren.


Sepp
#4636592
Lesenswert?

Rufus Τ. F. schrieb:
> Bevor hier mit festen Arrayindices gearbeitet wird, sollte zuerst die
> Länge des Strings überprüft werden.
>
> Denn der kann ja auch durchaus kürzer sein als fünf Zeichen ...

Korrekt. Auch alle Werte < 100 müssen separat behandelt werden, da 
führende Nullen hinzugefügt werden müssen.


Aus deinem Code:
1
result /= 102,3; //10V anzeigen
Dies wird nicht das tun, was du dir erhoffst. Du benutzt hier den 
Kommaoperator und result wird durch 102 geteilt. 102.3 wäre richtig, 
falls du Fliesskommazahlen benutzen willst.

GCC wirft bei diesem Ausdruck auch eine Warnung:
1
warning: right-hand operand of comma expression has no effect [-Wunused-value]
#4636612
Lesenswert?

pio schrieb:
> die Meldung bekomme ich nicht

Schalte -Wall und -Wextra ein.
http://gcc.gnu.org/onlinedocs/gcc/Warning-Options.html


Ich empfehle dir folgendes Vorgehen:
1. Letzte dezimale Ziffer ermitteln (Modulo-Operator).
2. Ziffer in einen String schreiben.
3. Zahl durch 10 teilen.
4. Springe zu 1. wenn Zahl ungleich null ist.

Somit hast du schon mal die Zahl in einen String gewandelt, die Zeichen 
sind jedoch in der falschen Reihenfolge gespeichert:
5. Reihenfolge der Zeichen im String umdrehen.

Wenn du das geschafft hast, erweiterst du deinen Algorithmus so, dass 
der String immer eine Mindestlänge von 3 hat. Du fügst also führende 
Nullen an.

Anschliessend veränderst du deine Funktion wieder, so dass immer an 3. 
Stelle (Index 2) ein Komma eingefügt wird.

Optional: Den Algorithmus so verändern, dass die Anzahl Kommastellen 
parametrierbar ist.

Schreibe dir eine Funktion dazu und teste diese auf deinem PC. Dann ist 
alles schon mal einfacher, da du die ganze Sache mit dem uC und ADC 
erstmal vergessen kannst.
Persönliche Seite #4636638
Lesenswert?

pio schrieb:
> 1,45V
> 10,00V

Das sind die gewünschten Ergebnisse, nicht das, was itoa geliefert hat.

Und was ist, wenn der ADC den Wert 13 liefert?

Dann steht im mit itoa erzeugten String nur "13" drin.

Latschen S. schrieb:
> Mackst du voll krass eine Nüll in letzte Ztelle - und alles ist
> String paletti

Du hast noch nicht mal kapiert, wo das Problem liegt.


Also: Der ADC liefert den Wert 13.

itoa macht daraus den String "13"

Im Speicher sieht das also so aus:

buffer1
[0] = '1'
[1] = '3'
[2] = '\0'
[3] = undefiniert1
[4] = undefiniert2
[5] = undefiniert3
[6] = undefiniert4
[7] = undefiniert5

Peter II schrieb:
> buffer1[7] = 0;
> buffer1[6] = buffer1[5];
> buffer1[5] = buffer1[4];
> buffer1[4] = ',';

Wird das angewendet, sieht das Resultat so aus:

buffer1
[0] = '1'
[1] = '3'
[2] = '\0'
[3] = undefiniert1
[4] = ','
[5] = undefiniert2
[6] = undefiniert3
[7] = '\0'

Das ist vom gewünschten Ergebnis

"0.13"

irgendwie ziemlich weit entfernt, nicht?
(Firma: Vescomp) #4636718
Lesenswert?

pio schrieb:
> das ist richtig. aber wie kann ich die variable so auseinander nehmen.?

Anstatt:
1
    result += ADCW;
2
  }
3
  // ADC wieder deaktivieren
4
  ADCSRA &= ~(1<<ADEN);
5
  
6
  result /= 3;
7
  result /= 102,3; //10V anzeigen
8
  return result;
9
}        
10
}

 Rechne so:
1
    result += ADCW;
2
  }
3
  // ADC wieder deaktivieren
4
  ADCSRA &= ~(1<<ADEN);
5
  
6
  result /= 3;
7
//  result /= 102,3; //10V anzeigen
8
  return result;
9
}

 Und dann in main()
1
 uint8_t Ganz =  result / 400;
2
 uint8_t Dez = (result % 400) >> 2;

 Und dann schreibe formatiert Ganz + "." + formatiert Dez.

 EDIT:
 Formatiert, damit du dein LCD nicht jedesmal löschen musst.
Gast #4636781
Lesenswert?

die methode von Latschen Sepp (lase) funktioniert sehr gut.

allerdings verstehe ich nicht, warum ich bloß bis 2,5V messen kann am 
adc.
ich habe einfach nur ein poti mit 5v am eingang dran.
hat das was mit der Referenzspannung zu tun.? glaube schon. aber wie 
kann ich es anders machen.?

wenn ich die interne referenz ausschalte, was muss ich dann 
hardwaremäßig am AREF Pin machen.?
Gast #4636845
Lesenswert?

W.A. schrieb:
> Da gehört eine Drossel zwischen.

Sorry, das war Bockmist.

Die Drossel gehört zwischen "+" und AVCC (oder wie auch immer der Pin 
bei denem Prozessor heißt). An ARef gehört ein Kondensator gegen Masse 
und üblicherweise sonst gar nichts, zumindest bei einem ATmega. Wenn du 
deine Versorgungsspannung als Referenz verwenden willst, kannst du die 
über die richtige Stellung der Register auswählen.
Gast #4636924
Lesenswert?

1
// ADC Value integer to ASCII
2
void AdcValOut (uint16_t AdcValue)
3
{
4
    uint8_t AdcValArray [5];
5
    uint8_t m = 4;
6

7
    do {
8
        AdcValArray [m] = '0' + AdcValue %10;      // Berechnung der einzelnen Stellen sowie
9
        AdcValue /= 10;                            // Wandlung nach ASCII und abspeichern im
10
    } while (m--);                                 // Array
11
    while (m != 4) {                               // Anzahl der auszugebenden Stellen = 5
12
        lcdPutc (AdcValArray [++m]);               // Integer Wert ausgeben
13
        if (m == 0) lcdPutc ('.');                 // Dezimalpunkt setzen
14
    }
15
}

Aufruf sollte klar sein, wenn du den Wert 12345 übergibst dann sollte 
auf deinem Display 1.2345 zur Anzeige kommen. Wie du das Ganze jetzt auf 
2 oder 3 Stellen hinter dem Komma anpassen mußt findest du bestimmt 
heraus. Ebenso sollte klar sein wie das Komma verschoben werden kann.

Du solltest dir Modulo / ASCII etc. ansehen und dann wenigstens den Code 
verstehen lernen.
(Firma: Vescomp) #4637096
Lesenswert?

Latschen S. schrieb:
> Glauben Sie wirklich dass man mit einen arroganten , abgehobenen Getue
> weiterkommt im Leben? :-(

 Wenn der Ausdruck:
1
 Wahrheit == (Arroganz & abgehoben)
 dann nein.

 Wie man ADC Wert mit 2.56V ARef einfach in Volt umwandelt habe ich
 weiter oben geschrieben.

 Wie man diesen Wert einfach auf einem Display anzeigt hat ihm Bernd N
 gezeigt:
 Bernd N schrieb: void AdcValOut (uint16_t AdcValue)

 Was in deinem Beitrag hier funktionieren soll:
> De kleinste Einheit die dein ADC wandeln kann (LSB Wert) ist 1 mV.
> Dann bekommst du in deinem Fall einen (unsigned) Integer Wert 5740.

 Oder hier:
> Mackst du voll krass eine Nüll in letzte Ztelle - und alles ist
> String paletti ;-)

 ist mir immer noch unklar.
Gast #4637151
Lesenswert?

@Marc Vesely (logarithmus)

So wie es aussieht können Sie "Arroganz" und  "abgehoben"
Ihrem Charakter nicht richtig zuordnen.

Tja dann wolle mir mal gugge was das Archiv so her gib:

Anleitung:

* Hier am Seitenanfang oder -ende auf "Suchen" klicken
* Beiträge ->  -alle-
* Sortierung -> nach Relevanz
* Sucheingabe  -> "Marc Vesely"

Da popt  genau ein Beitrag (RGB LED Sequenzen) von Ihnen hoch.
(der Einzige, mit gerade mal 13 Antworten)

Genau im 4.Beitrag werden Sie dann ausfällig
(den Text erspar ich mir hier)

im 5.Beitrag dann die Antwort (von Didi S.):

Anfang >>

Ups,

jetzt wollte ich Dir doch gerade Schreiben, wie man einfach und
professionell aufregende Sequenzen erzeugen kann. So wie die Profis von
Bühnenshows es machen - doch dann las ich Deinen letzten Beitrag. Sorry,
jetzt habe auch ich keine Lust mehr. .......

Bei Deinem ----------- ---------- ist mir mein Bett nun lieber.

Träum süß!

<< Ende


Sepp

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