mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik 10bit Wert als Temperatur ausgeben


Autor: Moschder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hallo zusammen,

möchte mit einem ATMEGA 8 eine einfache Temperaturmessung realisieren,
dazu habe ich über einen Messverstärker einen PT100 an den ADC 
angeschlossen.
Dieser liefert mir nun Werte zwischen

0x004  => -20,0°C und
0x3E9  => 70,0°C

diese hex-Werte möchte ich über eine Tabelle den Temperaturen, die
an einem LCD angezeigt werden sollen zuordnen. Dazu habe ich folgenden 
Code
geschrieben:

ADC_into_celsius:



    rcall lcd_clear
    rcall lcd_home

    ldi     zl,low(celsius_werte*2)            ; Z Pointer laden
    ldi     zh,high(celsius_werte*2)

;es wird die erste adresse der Tabelle celsius_werte markiert




  add zl, temp2         ;auszugebende temperatur in Tabelle markieren

        brcc weiter            ;carry bit gesetzt wegen überlauf?
  inc zh

weiter:

  add zh, temp5



    push temp3

  ldi temp3, 6            ;ab markierter stelle 6 zeichen lesen



ADC_into_celsius_sub:

    dec temp3
    tst temp3                ;ist temp3 = 0 ? =>wenn ja wurde 6 mal 
gelesen
   breq ADC_into_celsius_end      ;wenn temp3 null ist anzeige beenden

    lpm     temp1, Z+     ;durch z pointer markierte daten lesen in 
temp1
                        ;schreiben und z pointer um 1 erhöhen



  rcall lcd_data








  rjmp ADC_into_celsius_sub



ADC_into_celsius_end:
  pop temp3




celsius_werte:


.db "-20,00"
....
.db "+70,00"


In temp2 wird das low-byte der analog digital Wandlung
in temp5 das high-byte der analog digital Wandlung übergeben
temp1 ist das register in dem die Daten dem LCD übergeben werden

Nun mein Problem:
An der Anzeige wird mir -12,0 angezeigt.
Rechne ich jedoch den hex wert manuell um müßten 25°C angezeigt werden.
Ich vermute daß an der Stelle der beiden add Befehle was schief geht.
Wo liegt der Fehler?

Gruß
Moschder

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Schau Dir bitte mal in der Befehlssatz-Dokumentation den Befehl adc 
(add with carry) an, v.a. das Codebeispiel.

Was sollen übrigens die riesigen Leerzeilen-Blöcke in dem Code? Meinst 
Du, das lässt sich so besser lesen? Das Gegenteil ist der Fall! Außerdem 
solltest Du Dir die Hinweise zur Formatierung unter den Forenregeln mal 
ansehen. Da steht eine Möglichkeit, wie man AVR-Assembler-Code schön 
formatieren kann...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Da Du an jeder "Stelle" in der Tabelle 6 Zeichen stehen hast, musst Du 
den Adress-Offset (also den Hex-Wert für die Temperatur) aber auch noch 
mit 6 multiplizieren, damit Du auf den Anfang des richtigen Strings 
kommst...

Autor: Johannes M. (johnny-m)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Zur Verdeutlichung mal mit Beispielwerten:
celsius_werte*2       -20,00
celsius_werte*2+6     -19,90
celsius_werte*2+12    -19,80
celsius_werte*2+18    -19,70
celsius_werte*2+24    -19,60
...usw...
celsius_werte*2+5976  +69,50
celsius_werte*2+5982  +69,60
celsius_werte*2+5988  +69,70
celsius_werte*2+5994  +69,80
celsius_werte*2+6000  +69,90
celsius_werte*2+6006  +70,00
Der Offset ist also immer sechs mal der Hex-Wert vom ADC.

Autor: Moschder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
vielen Dank für Deine Antworten,
die Multiplikation mit 6 ist wohl der Schlüssel.
Leider werden die Zahlen dann sehr groß und ich müßte mehrere Register 
verwenden, was bestimmt zu Problemen führt.
Weiß nicht wie ich da ansetzen kann.
Bevor ich mit der Tabelle angefangen habe, habe ich mal versucht die 
Celsius Werte zu berechnen dies hat aber nicht geklappt (kommazahl, 10 
bit, division multipikation)

Autor: Andreas K. (a-k)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Routinen für Multiplikation und Division findet man als Atmel 
Application Note.

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
@ Moschder (Gast)

>die Multiplikation mit 6 ist wohl der Schlüssel.
>Leider werden die Zahlen dann sehr groß und ich müßte mehrere Register
>verwenden, was bestimmt zu Problemen führt.

Nicht wirklich.

>Weiß nicht wie ich da ansetzen kann.

Festkommaarithmetik
AVR-Tutorial: ADC

MfG
Falk

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!

ADC_into_celsius_sub:
push ZL
push ZH               ;nur wenn Z noch woanders benutzt
ldi     zl,low(celsius_werte*2)            ; Z Pointer laden
ldi     zh,high(celsius_werte*2)

add zl,temp2
adc zh,temp5
lsl zl
rol zh                 ;*2
mov temp2,zl
mov temp5,zh           ;*2 merken
lsl zl
rol zh                 ;*4
add zl,temp2
adc zh,temp5           ;zu *4 (*2) addieren =*6
ldi temp2, 6           ;ab markierter stelle 6 zeichen lesen

Ausgeben:
lpm     temp1, Z+      ;durch z pointer markierte daten lesen in temp1

rcall lcd_data         ; ist bestimmt die Ausgabe

dec temp2
brne Ausgabe           ; nicht 0? -> Ausgabe

pop ZH
pop ZL                 ;nur wenn Z woanders noch benutzt
ret

Hoffe ich habe mich nicht vertan.

Viel Erfolg, Uwe

Autor: Uwe (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi!
Und ging's? Vermutlich eher nicht. Und warum?.. weil ganze Adresse *6, 
also nochmal:

ADC_into_celsius_sub:
push ZL
push ZH               ;nur wenn Z noch woanders benutzt

lsl temp2
rol temp5             ;*2
mov zl,temp2
mov zh,temp5,         ;*2 merken
lsl temp2
rol temp5             ;*4
add zl,temp2
adc zh,temp5           ;zu *4 (*2) addieren =*6
ldi     temp2,low(celsius_werte*2)            ; Z Pointer laden
ldi     temp5,high(celsius_werte*2)
add zl,temp2          ;und zu Temp.wert dazu
adc zh,temp5

ldi temp2, 6           ;ab markierter stelle 6 zeichen lesen

Ausgeben:
lpm     temp1, Z+      ;durch z pointer markierte daten lesen in temp1

rcall lcd_data         ; ist bestimmt die Ausgabe

dec temp2
brne Ausgabe           ; nicht 0? -> Ausgabe

pop ZH
pop ZL                 ;nur wenn Z woanders noch benutzt
ret

Hoffe das stimmt jetzt.(ungetestet)
Übrigens: "0x004  => -20,0°C"
und "celsius_werte*2       -20,00"
passt so nicht, da bist du schon bei "celsius_werte*2+24    -19,60"

Viel Erfolg, Uwe

Autor: Moschder (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Uwe und allen anderen besten Dank,
nun funktioniert das Ganze wie gewünscht!

Am A/D Wandler angeschlossen ist ein 4 Draht Messverstärker mit PT100 
dieser ist ohne Potis aufgebaut daher kann ich nicht den vollen Bereich 
von 0 bis 1023 verwenden, da der Verstärker nicht exakt abgleichbar ist. 
Daher der Wert 0x004.
Die Werte bis 0x004 verwende ich als PT100 Kurzschluß Erkennung, sie 
sind mit einem Fehlercode versehen.

Gruß
Moschder

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.