Forum: Mikrocontroller und Digitale Elektronik Betrag von AD-Wandler auf LCd anzeigen


von Manuel (Gast)


Lesenswert?

Hallo Leute,

ich hab vollgendes Problem Ich muss für meine schule ein Strommessgerät 
entwickeln. Jetzt muss ich den Betrag vom Ad-wandler was an Ain 0 
anliegt auf die Lcd bringen aber in einer Kommazahl. Bedeutet ja der 
Betrag in Ain0 wir durch 256 geteilt und der wert in den Akku 
gespeichert. Dieses muss ich dann nehmen ihn für eine Look uptable 
nehmen und den vorkommaWert suchen, diesen danna uf die lcd bringen. 
Dachach den Wert in eine andere Tabelle nehmen und den Nachkommastellen 
Wert suchen und auf die lcd beringen.
Vorgabe ist ein Messbereich von 0-5V also hab die looUp schon 5:256 und 
dann die werte in die lookups geschrieben. Nund hab und keien idee wie 
ich den rest umsetzten soll

von lowlevel (Gast)


Lesenswert?

Teile uns doch mal mit, auf was für einem Mikrocontroller du arbeitest. 
Dann könnten wir dir vielleicht helfen. Bei einigen µCs gibt es bereits 
Funktionen, die die Funktionalität bereitstellen.

von Karl H. (kbuchegg)


Lesenswert?

> Bedeutet ja der Betrag in Ain0 wir durch 256 geteilt und der
> wert in den Akku gespeichert. Dieses muss ich dann nehmen
> ihn für eine Look uptable nehmen und den vorkommaWert suchen,
> diesen danna uf die lcd bringen.
> Dachach den Wert in eine andere Tabelle nehmen und den
> Nachkommastellen Wert suchen und auf die lcd beringen.

Machs nicht so komplizert.
Mach dir EINE Lookup Tabelle in der du zb das 100-fache des Wertes 
speicherst (als Vorkomma + 2 Nachkommastellen) und während der Ausgabe 
schummelst du vor die letzten beiden auszugebenden Stellen einen 
Dezimalpunkt ein.

Und so wird dann aus 439, die du aus der Tabelle bekommst, auf der 
Anzeige ein "4.39"
(aber aufpassen mit führenden 0-en. Aus 29 muss an der Ausgabe 0.29 
werden, wenn deine Ausgaberoutinen führende 0-en unterdrückt)

von Salvadore (Gast)


Lesenswert?

Wenn in deiner Schule Deutschkurse angeboten werden, solltest du einmal 
einen besuchen.

von Manuel (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> 439

Wie soll ich denn diesen Pinkt dazwischen bekommen?

Haben ein ATMEL 895131A

von Matthias S. (Firma: matzetronics) (mschoeldgen)


Lesenswert?

Manuel schrieb:
> Haben ein ATMEL 895131A

Das ist schön - schade nur, das der gar keinen AD Wandler hat. Und hilft 
auch nicht weiter, wenn du Pinkte einbauen willst. Und ausserdem wissen 
wir ja nicht einmal, in welcher Programmiersprache ihr da rumwurschtelt.
Beitrag "Einheitlicher Umgang mit faulen Schülern etc.?"

von Manuel (Gast)


Lesenswert?

Wie der hat kein Ad-Wandler hab auch den falschen gepostet.

Hier nochmal der neue: Atmel 89C5131A-UM

Hier mal wie wiet ich bisher bin:
Teste noch herum
;-----------------------------------------------------------------------
;Auswahl zwischen Spannungsbereich 0-10V, 0-5V
  mov a,90h  ;Wert von P1.0(90h) in akku
  mov r1,a  ;Akku in r1
  mov a,91h  ;Wert von P1.1(91h) in akku
  mov r2,a  ;Akku in r2


  cjne r1,#1,Auswahl  ;Vergleiche r1 mit Konstanten 1
  lcall Ain0    ;Abfrage Wert an Ain0
  mov DPTR,#tabelle10V1  ;Lookup Tablle einfügen
  movc a,@a+DPTR    ;Wert aus Tabelle 10V1 holen
  mov r4,a
  lcall r4
  lcall Ain0
  mov DPTR,#tabelle10V2
  movc a,@a+DPTR


        lcall dezaus    ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)

Auswahl: cjne r2,#1,Auswahl
  lcall Ain0    ;Abfrage Wert an Ain0
  mov DPTR,#tabelle5V1  ;Lookup Tablle einfügen
  movc a,@a+DPTR    ;Wert aus Tabelle 5V1 holen
  mov r4,a

  mov DPTR,#tabelle5V2

  movc a,@a+DPTR

  lcall dezaus    ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)

von lowlevel (Gast)


Lesenswert?

Na gut,

zumindest scheint es so als ob du dich bemühst. Dann legen wir mal los 
ein bisschen zu helfen. Allerdings möchtest du doch wissen, wie du die 
Ausgabe des '.' oder ',' realisierst. Gerade die Funktion "dezaus" die 
das machen soll fehlt in deinem Beitrag. Bitte nachliefern. Am besten 
den kompletten Code posten.

Gruß lowlevel

von Manuel (Gast)


Lesenswert?

Hier bitte:D

EXTRN Code 
(initLCD,loeschzeile1,loeschzeile2,textzeile1,textzeile2,cursorpos,texta 
us,zifferaus,hexaus,dezaus,Ain0,Aout)


;******************** Programm 
************************************************
  cseg at 0


  mov     sp,#2fh    ;Stackpointer oberhalb Bitadressierbarer Bereich
  lcall  initlcd    ;Display initialisieren

  mov dptr,#Text3
  lcall textzeile1

  mov dptr,#Text1
  lcall textzeile2

start:  ;lcall   loeschzeile1
  ;lcall   loeschzeile2

  mov a,#0


     mov a,#45h    ;Textzeile zwei, Abstand zu 'U'
  lcall cursorpos


;-----------------------------------------------------------------------

  mov a,90h  ;Wert von P1.0(90h) in akku
  mov r1,a  ;Akku in r1
  mov a,91h  ;Wert von P1.1(91h) in akku
  mov r2,a  ;Akku in r2


  cjne r1,#1,Auswahl  ;Vergleiche r1 mit Konstanten 1
  lcall Ain0    ;Abfrage Wert an Ain0
  mov DPTR,#tabelle10V1  ;Lookup Tablle einfügen
  movc a,@a+DPTR    ;Wert aus Tabelle 10V1 holen
  mov p1,a
  lcall dezaus


  mov a,#49h
  lcall cursorpos


  lcall Ain0
  mov DPTR,#tabelle10V2
  movc a,@a+DPTR
    lcall dezaus    ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)

Auswahl: cjne r2,#1,Auswahl
  lcall Ain0    ;Abfrage Wert an Ain0
  mov DPTR,#tabelle5V1  ;Lookup Tablle einfügen
  movc a,@a+DPTR    ;Wert aus Tabelle 5V1 holen
  mov r4,a

  mov DPTR,#tabelle5V2

  movc a,@a+DPTR

  lcall dezaus    ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)




;----------------------------------------------------------------------- 
-----
         lcall Zeit
  sjmp start


;  mov  dptr,#Text1
;  lcall   textzeile1
;  lcall   Zeit
;
;  mov    dptr,#Text2
;  lcall   textzeile2
;  lcall   Zeit
;
;  lcall   loeschzeile1
;  lcall   loeschzeile2
;
;  mov   dptr,#Text3
;  lcall   textzeile1
;  lcall   Zeit
;
;  mov   dptr,#Text4
;  lcall   textzeile2
;  lcall   Zeit
;
;  lcall   loeschzeile2
;  mov   a,#12
;  lcall   dezaus
;  lcall   Zeit
;
;  jmp   start
;
;
;********** Zeitverzögerung 
************************************************************************ 
**

Zeit:    mov  R7, #3
Zeit2:    mov  R6, #255
Zeit1:    mov  R5, #255
Zeit0:    djnz  R5, Zeit0
    djnz  R6, Zeit1
    djnz  R7, Zeit2
    ret


;************************ Texte 
*******************************************************
Text1:  db 'U =    .   V',0
;Text2:  db '  V',0
Text3:  db 'Spannungsmessge.',0
;Text4:  db '  Gymnasium',0
;
;
;**********Lockup Table******

tabelle5V1: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0, 0
            db   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1, 1, 1
            db   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2, 2
            db   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
3, 3, 3, 3, 3, 3, 3, 3, 3
            db   4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4, 4
            db   5



tabelle5V2: db 00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 
27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 
63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 
98
            db   00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 
27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 
63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 
98
            db   00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 
27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 
63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 
98
            db   00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 
27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 
63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 
98
            db   00, 02, 04, 06, 08, 10, 12, 14, 16, 18, 20, 22, 24, 25, 
27, 29, 31, 33, 35, 37, 39, 41, 43, 45, 47, 49, 51, 53, 55, 57, 59, 61, 
63, 65, 67, 69, 71, 73, 75, 76, 78, 80, 82, 84, 86, 88, 90, 92, 94, 96, 
98
            db   00

tabelle10V1: db 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 
0, 0, 0, 0, 0, 0, 0
             db   1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 
1, 1, 1, 1, 1, 1, 1
             db   2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 
2, 2, 2, 2, 2, 2, 2, 2
             db   3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 
3, 3, 3, 3, 3, 3, 3
             db   4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 
4, 4, 4, 4, 4, 4, 4, 4
             db   5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 5, 
5, 5, 5, 5, 5, 5, 5
             db   6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 6, 
6, 6, 6, 6, 6, 6, 6, 6
             db   7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 
7, 7, 7, 7, 7, 7, 7
             db   8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 8, 
8, 8, 8, 8, 8, 8, 8, 8
             db   9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 
9, 9, 9, 9, 9, 9, 9
             db   10

tabelle10V2: db 00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 51, 
55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98
             db   02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 
53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96
             db   00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 
51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98
             db   02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 
53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96
             db   00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 
51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98
             db   02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 
53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96
             db   00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 
51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98
             db   02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 
53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96
             db   00, 04, 08, 12, 16, 20, 24, 27, 31, 35, 39, 43, 47, 
51, 55, 59, 63, 67, 71, 75, 78, 82, 86, 90, 94, 98
             db   02, 06, 10, 14, 18, 22, 25, 29, 33, 37, 41, 45, 49, 
53, 57, 61, 65, 69, 73, 76, 80, 84, 88, 92, 96
             db   00

von Karl H. (kbuchegg)


Lesenswert?

dezaus fehlt immer noch

Aber ich fürchte, selbst mit der Kentnis dieser Funktion wird das 
nichts. Solange du nicht mit 16 Bit Werten hantieren kannst, ist das 
vergebliche Liebesmühe.


Zu deinen Tabellen.
Ich weiß nicht, ob du das schon mal gehört hast. Aber dein µC ist ein 
kleiner Computer! Der kann rechnen! Du kannst natürlich eine Division 
durch eine Tabelle ersetzen. Sinnvoll ist das aber nicht. Sinnvoll wäre 
es, zu lernen, wie man in Assembler eine 16 Bit Division durchführt.

von Manuel (Gast)


Lesenswert?

wo fehlt denn dieser befehl

von Karl H. (kbuchegg)


Lesenswert?

Manuel schrieb:
> wo fehlt denn dieser befehl

nicht 'er fehlt'.

Sondern hier
1
 lcall dezaus    ;Ausgabe Wert ind Dezimal von Ain0 (Ad-Wandler)

wird ein Unterprogramm aufgerufen, welches offenbar die Ausgabe macht. 
Da es aber zu prüfen gilt, ob und wie man da während der Ausgabe einen 
'.' in die Ausgabe an der entsprechenden Stelle einschmuggeln kann, wird 
man sich wohl ansehen müssen, wie denn diese Ausgabefunktion eigentlich 
arbeitet.

Nun versteh ich von deinem µC nicht viel. Was ich aber verstehe ist, 
dass du dich bei deinem ganzen Programm mehr oder weniger auf 8 Bit 
Arithmetik eingeschworen hast. Und solange das so ist, wird das auch 
nichts werden mit dieser vorgschlagenen Strategie. Du musst zumindest 
soweit in deinen Fähigkeiten sein, dass dich 16 Bit Arithmetik 
(Addieren, Subtrahieren, Multiplizieren, Dividieren) nicht vor unlösbare 
Probleme stellt. Wie willst du denn je vernünftig deinen µC zu 
Rechenaufgaben heranziehen, wenn du nicht wenigstens im Zahlenraum 0 bis 
65-tausend problemlos einfache Berechnungen machen kannst? Du kannst 
dich nicht ewig mit 8-Bit Tabellen aus der Affäre ziehen, zumal das dann 
wieder andere Probleme (eben durch den beschränkten Zahlenraum) nach 
sich zieht.

von W.S. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Mach dir EINE Lookup Tabelle

Nein!! Mach dir bitte KEINE Lookup-Tabelle.

O Herr, lass Hirn regnen.

das elendige Thema, daß die Leute in ihrer Beschränktheit immerzu 
glauben, daß ein Ergebnis eines ADC's eine Integerzahl darstellen würde, 
hatten wir doch schon so unsäglich oft. Anschließend kommt immer die 
Frage "Wie kann ich aus den Integerzahlen 0..255 ein Ergebnis 0.0 Volt 
bis 4.999 Volt machen?"

Ich versuch's mal in diskreten Erkenntnis-Stufen:

1. Erkenntnis: Das, was ein ADC ausspuckt, sind Bits - und keine 
Spannungswerte.

2. Erkenntnis: Diese Bits haben üblicherweise (aber nicht immer) eine 
Wertigkeits-Reihenfolge untereinander, also es gibt ein "dickstes" 
sprich höchstwertigstes Bit (das MSB) und die anderen Bits haben einen 
kleineren Wert. Daß das immer ne Zweierpotenz sein muß, ist falsch. Es 
gibt auch BCD-ADC's (die in den Taschen-Multimetern) und es gibt welche, 
die Gray-Code ausspucken.

3. Erkenntnis: Niemand hat gesagt, daß ein bestimmtes Bit einen 
bestimmten Wert (z.B. 1 Volt) hat. Wer es nicht glauben will, der hängt 
vor den ADC einen Spannungsteiler oder ändert die Referenzspannung und 
schon bedeutet das Bit ne andere Eingangsspannung. Wir sehen also, daß 
die Wertigkeiten aller Bits von der Eingangsbeschaltung und der Referenz 
abhängt.

4. Wenn wir aus den Bits, die aus dem ADC kommen, eine ZAHL bilden 
wollen, dann müssen wir den Bits jeweils eine Wertigkeit zuweisen. Wir 
könnten (für das Beispiel aus dem Threadbeginn) z.B. dem MSB den Wert 
0.5 zuweisen, dem nächsten den Wert 0.25, den dritten 0,125 usw.

Alle so zugeordneten Bits bilden dann eine echt gebrochene Zahl von 0 
bis 0.99606299212, die wir großzügig zu 0.996 runden. Was haben wir nun 
davon? Nun, wir multiplizieren später einen Faktor, der unsere Referenz 
und einen Spannungsteiler usw. enthält und schon haben wir unser 
Ergebnis in Volt.

5. Erkenntnis: Wenn ich eine echt gebrochene Zahl mit 10 multipliziere, 
bekomme ich vor dem Dezimalpunkt die erste Stelle und danach den Rest.
Also ich hab 0.3745 und multipliziere:
0.345 * 10 --> 3.745
Nun kann ich den ganzen Teil abtrennen und ausgeben und rechne mit dem 
Rest weiter:
0.745 * 10 --> 7.45
Wieder ganzen Teil abtrennen und mit dem Rest weitermachen:
0.45 * 10 --> 4.5
usw. bis ich genug Stellen habe.

6. ne Nachüberlegung:
Mein o.g. Faktor sei hier 5, weil ich einen ADC hab, der von 0 bis knapp 
5 Volt "geht". (genauer: 5 * 0.99606299212 --> ca. 4.98 Volt)
Ich müßte also 5 * ADCwert rechnen und dann hätte ich schon als erstes 
Ergebnis meinen ganzen Teil, den ich abtrennen kann. Der Rest ist ja 
wieder kleiner als 1 und damit geht die Rechnung so:
1. Schritt: ADC*5, ganzen Teil abtrennen
2. Schritt: Rest*10, ganzen Teil abtrennen
3. Schritt: Rest*10, ganzen Teil abtrennen
das reicht, zu mehr taugen 8 Bit nicht.

7. Was braucht man zum Rechnen?
Nun man kann das Ganze mit nem Integer, also einer 16 Bit Zahl rechnen. 
Die niederwertigen Bits 0..7 stellen unseren gebrochenen Teil dar und 
die höherwertigen Bits den ganzen Teil. Geht auch bequem mit 2 Bytes und 
Beachten des Carry zu rechnen.

8. Wie multipliziert man mit 10, wenn man keinen Befehl dazu hat?
 Zahl* 10  geht auch als ((Zahl << 2) + Zahl) << 1), also 2 Shifts und 
eine Addition.

So. Den konkreten Quellcode schreibt sich unser Manuel nun selbst, 
nachdem er das hier verstanden hat.

W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Karl Heinz Buchegger schrieb:
>> Mach dir EINE Lookup Tabelle
>
> Nein!! Mach dir bitte KEINE Lookup-Tabelle.

Zu diesem Zeitpunkt wusste ich noch nicht, dass seine 
Umrechnungsfunktion eine simple lineare Gleichung ist. Hätte ja auch 
etwas Komplexeres sein können. Damit, dass er eine 
Multiplikation/Division in Form einer Tabelle abbildet, damit hatte ich 
nun wirklich nicht gerechnet.

von Bernhard S. (b_spitzer)


Lesenswert?

Wird wohl eh etwas knapp mit dem Speicher. Was ich bisher von den 
Funktionen gesehen habe würde ich auf ein ganz spezielles Board tippen 
(wird in BaWü an vielen Schulen eingesetzt). Da wird in der Schule dann 
RIDE genutzt das in der kostenlosen Version nur 4k Code erzeugt. 
adda.a51 und lcdhilf.a51 brauchen so 600Bytes, die Tabelle knallt mit 2k 
rein...

Wie wäre es denn, vom Digitalwert (Akku) so oft 51 (1V) abzuziehen, bis 
das Ergebnis negativ wird. Damit ist die Vorkommastelle bekannt. Der 
verbleibende Rest ist eine Zahl zwischen 0 und 50. dafür könnte man dann 
zur Not eine Tabelle anlegen. Wenn man etwas krumm mit Ulsb = 5V /255 
rechnet kommt man auch auf genau 51Bit pro Volt.
Die Ausgabe des Dezimalpunktes erledigt ein
mov a, #'.'
call charaus

In C könnte man das als Zweizeiler schreiben (der dann aber auch die 4k 
vollmüllt)

tschuessle
Bernhard

von Manuel (Gast)


Lesenswert?

>
> 5. Erkenntnis: Wenn ich eine echt gebrochene Zahl mit 10 multipliziere,
> bekomme ich vor dem Dezimalpunkt die erste Stelle und danach den Rest.
> Also ich hab 0.3745 und multipliziere:
> 0.345 * 10 --> 3.745
> Nun kann ich den ganzen Teil abtrennen und ausgeben und rechne mit dem
> Rest weiter:
> 0.745 * 10 --> 7.45
> Wieder ganzen Teil abtrennen und mit dem Rest weitermachen:
> 0.45 * 10 --> 4.5
> usw. bis ich genug Stellen habe.
>
> 6. ne Nachüberlegung:
> Mein o.g. Faktor sei hier 5, weil ich einen ADC hab, der von 0 bis knapp
> 5 Volt "geht". (genauer: 5 * 0.99606299212 --> ca. 4.98 Volt)
> Ich müßte also 5 * ADCwert rechnen und dann hätte ich schon als erstes
> Ergebnis meinen ganzen Teil, den ich abtrennen kann. Der Rest ist ja
> wieder kleiner als 1 und damit geht die Rechnung so:
> 1. Schritt: ADC*5, ganzen Teil abtrennen
> 2. Schritt: Rest*10, ganzen Teil abtrennen
> 3. Schritt: Rest*10, ganzen Teil abtrennen
> das reicht, zu mehr taugen 8 Bit nicht.


ich habe es in gro´Zügen verstanden aber leider keine idee wie ich dies 
in asabler umsetzten soll
wie ichd as trennne hinbekommen soll und alles
Tut mir leid fange gerade an mit dieser sprache und alles umzugehen

von W.S. (Gast)


Lesenswert?

Machen wir's in Assembler:

Also, du hast beispielsweise eine Zahl wie 3.1415 und selbige so in ein 
16 Bit Register (das du z.B. KarlHeinz nennst) gepackt, daß der (dazu 
gedachte) Dezimalpunkt genau zwischen Bit 7 und Bit 8 steht. Dann belegt 
der ganze Teil die Bits 8..15 und der gebrochene Teil die Bits 7..0. 
Wenn dein uC keine 16 Bit Register hat, dann nimmst du eben 2 
Achtbit-Register und benenne sie z.B. KarlHi und KarlLo. Klaro?

Wie kriegst du nun den ganzen Teil zur Ausgabe?
Bei 16 Bit:
- Lade KarlHeinz in ein anderes Register (Otto), also Otto = KarlHeinz;
- dann Otto rechtsverschieben Otto = Otto shiftrechts 8 Bit. Damit 
fliegt der gebrochene teil aus Otto heraus und der Rest ist deine Stelle 
0..9, aus der du nur noch ein Char machen mußt durch Addieren von 48 (= 
30h = '0'), also GibAus(Otto+'0');
- dann schmeiß den ganzen Teil aus Karlheinz heraus:
  KarlHeinz = KarlHeinz AND 255; (255 = FFh = 0000000011111111 binär)

Bei 2x 8 Bit ist es einfacher:
KarlHi ist bereits der ganze Teil, den du mit GibAus(KarlHi+'0') direkt 
ausgeben kannst.
Anschließend schmeißt du den ganzen Teil heraus, indem du KarlHi = 0; 
schreibst, also dieses Register mit 0 lädtst.

Ist doch extrem easy, oder?


W.S.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Machen wir's in Assembler:

Ich denke sein Hauptproblem wird sein, dass er noch keine 16 Bit 
Arithmetikroutinen hat, mit denen er den ADC Wert entsprechend einer 
Formel in den Anzeigewert umrechnen kann. Leider versteh ich von diesem 
Assembler nichts, daher kann ich ihm da auch nicht weiterhelfen, wie man 
diese Dinge da am vernünftigsten aufbaut.

PS: Nettes Namenswahl

von Bernhard S. (b_spitzer)


Lesenswert?

Karl Heinz Buchegger schrieb:
> keine 16 Bit Arithmetikroutinen hat
Das dürfte die meisten (Berufs-)Schüler aber auch deren Lehrer 
überfordern. Daher ist die naheliegende Lösung so wie oben von mir 
beschrieben. Alternativ könnte man nach der mehrfachen Subtraktion noch 
versuchen die 1/10V-Schritte durch Subtraktion zu erledigen, aber das 
geht im 8-Bit-Zahlenraum auch nur ungenau, wenn die Ulsb 19,53mV/Bit 
entspricht.


@Manuel: arbeitest du mit dem Board hier?
http://www.ces.karlsruhe.de/bubbers/index.php/controller
Da gibt es einen Trimmer für Uref. Wenn man jetzt 4,1V (genauer 4,096V) 
einstellt, dann entspricht Ulsb = 16mV/Bit. Damit lässt ich wesentlich 
einfacher rechnen. Noch einfacher ist es bei 2,56V, dann ist Ulsb = 
10mV/Bit und eine Spannung (bis 2,55V) entspricht genau dem Digitalwert 
in 10mV-Schritten. Nachteil ist der reduzierte Eingangsspannungsbereich.

tschuessle
Bernhard

von Karl H. (kbuchegg)


Lesenswert?

Bernhard Spitzer schrieb:
> Karl Heinz Buchegger schrieb:
>> keine 16 Bit Arithmetikroutinen hat
> Das dürfte die meisten (Berufs-)Schüler aber auch deren Lehrer
> überfordern. Daher ist die naheliegende Lösung so wie oben von mir
> beschrieben.

Du verstehst mich nicht, worauf ich hinaus will.
Deine Ausgaberoutine ist ja super. Gut erklärt und auch für ihn 
umsetzbar. Das Problem ist: wo kommt der Wert her, den er ausgeben will.

Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige 
zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.) 
8.8 Fixpunktzahl, die er dann schön ausgeben kann?

von Manuel (Gast)


Lesenswert?

Bernhard Spitzer schrieb:
> @Manuel: arbeitest du mit dem Board hier?
> http://www.ces.karlsruhe.de/bubbers/index.php/controller
> Da gibt es einen Trimmer für Uref. Wenn man jetzt 4,1V (genauer 4,096V)
> einstellt, dann entspricht Ulsb = 16mV/Bit. Damit lässt ich wesentlich
> einfacher rechnen. Noch einfacher ist es bei 2,56V, dann ist Ulsb =
> 10mV/Bit und eine Spannung (bis 2,55V) entspricht genau dem Digitalwert
> in 10mV-Schritten. Nachteil ist der reduzierte Eingangsspannungsbereich.
>
> tschuessle
> Bernhard

Ja, genau mit diesem arbeiten wir.
Welcher Trimmer? Ich muss an das board noch ein spannungsteiler dran 
hängen wiel ich die eingäne bei Ani0 nehme mit 5v und Masse

von Manuel (Gast)


Lesenswert?

Bernhard Spitzer schrieb:
> Wie wäre es denn, vom Digitalwert (Akku) so oft 51 (1V) abzuziehen, bis
> das Ergebnis negativ wird. Damit ist die Vorkommastelle bekannt. Der
> verbleibende Rest ist eine Zahl zwischen 0 und 50. dafür könnte man dann
> zur Not eine Tabelle anlegen. Wenn man etwas krumm mit Ulsb = 5V /255
> rechnet kommt man auch auf genau 51Bit pro Volt.
> Die Ausgabe des Dezimalpunktes erledigt ein
> mov a, #'.'
> call charaus

oki aber wie gebe ich das alles aus. ich habe ja dann die Kommastelle 
0-50Bit entpricht evtl 0.2V wie bekomm ich nun die vorkommastelle?
Wenn ich ein Signal habe mit 168 Würde es ja 3,.. geben Muss ich dann ne 
verzeigung machen, die Abfraget ob der wert größer 51 ist und dann 
wieder abzieht und dann ein register z.b hochzählt?
Würde bedeuten, ich habe r=3 Tablle:25Bit=0,5V
Wie füge ich dies zusammen mit einem Punkt.

von Bernhard S. (b_spitzer)


Lesenswert?

Manuel schrieb:
>> Die Ausgabe des Dezimalpunktes erledigt ein
>> mov a, #'.'
>> call charaus
>
> Würde bedeuten, ich habe r=3 Tablle:25Bit=0,5V
>
> Wie füge ich dies zusammen mit einem Punkt.

Die letzte Frage wurde bereits beantwortet, bevor Du sie gestellt hast. 
Ansonsten stellst Du aus mehreren Variabeln (Speicherstellen von 7Fh 
abwärts eigenen sich da gut) deinen Zahlenwert zusammen.
z.B. Vorkomma EQU 07Fh
Nachkomma_Zehntel EQU 07Eh
Nachkomma_Hundertstel EQU 07Dh
Ausgabe erfoglt dann Ziffernweise mit
mov a, Vorkomma
call charaus
mov a, #'.'
call charaus
mov a, Nachkomma_Zehntel
undsoweiterundsofort...

Nachdem Du Dir Gedanken gemacht hast, wie deine gewünschte physikalische 
Größe (Du willst doch Strom messen - redest aber nur von Spannungen. 
Also wie groß ist der Messwiderstand?) vom Digitalwert abhängt, kannst 
Du (zuerst mal auf Papier) die Formel Phy_Größe = m * Digitalwert + b
aufstellen. Überprüfung mit 2 konkreten Digitalwerten sollte erfolgen.
Da krumme Faktoren und Überläufe in Assembler nicht gut umsetzbar sind, 
rechnest Du Dir die Digitalwerte z.B. für 1A, 2A, 3A usw. aus. Dann 
misst Du den Analogkanal und vergleichst auf die Schwellen. Damit ist 
die Vorkommastelle klar. Wenn also 1A z.B. 51 entspricht, dann so:
1
call ain0 ; im Akku steht jetzt der Digitalwert
2
cjne a,#51,Vergleich2  ; Wenn Akku gleich 51, dann 1.00A
3
mov Vorkomma, #1
4
mov Nachkomma_Zehner, #0  ; und so weiter
5
jmp Anzeigen
6
7
Vergleich2:  ; jetzt das Carry prüfen. Wenn gesetzt ist der Akku unter 51, sonst drüber
8
jc Unter51  
9
Ueber51:     ; 51 abziehen, dann weitere Vergleiche mit den übrigen Werten
10
11
Unter51:
12
mov Vorkomma, #0
13
;Nachkommastellen aus Wertetabellen mit indir. Adressierung auslesen

und das ganze für alle weiteren berechneten Digitalwerte. Ist zwar 
nervig, aber immer das gleiche Schema.


@Karl Heinz: Eigentlich sollte der Lehrer sowas vorher mal im Unterricht 
vorgestellt haben. Für ASM-Anfänger ist sowas eine recht harte Nuss. 
Mehr als das obige will ich aber nicht mehr vorgeben. Erst soll er mal 
eigenen Code posten. (die nächste Frage zum Thema hat er als MA ja schon 
gestellt).

tschuessle
Bernhard

von W.S. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige
> zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.)
> 8.8 Fixpunktzahl, die er dann schön ausgeben kann?

Er berechnet sie überhaupt nicht, sondern setzt den ganzen Teil auf 
Null und lädt den gebrochenen Teil mit dem Ergebnis aus dem ADC. Das ist 
alles.

Irgendwann verzweifle ich an euch allen!!

Also nochmal vom nochmal:

1. Wir lesen den 8 Bit großen (also 1 Byte umfassenden) ADC-Wert aus dem 
ADC aus und laden ihn in ein Register oder eine Speichezelle, die ich 
hier mit KarlLo bezeichne.

2. Wir nehmen irgendwoher ein zweites Register oder eine zweite 
Speicherzelle, die ich hier KarlHi bezeichne. Dort schreiben wir ene 
NULL hinein oder führen einen Löschbefehl aus (je nach verwendetem uC)

Also haben wir jetzt (mal pascalartig ausgedrückt):

var
KarlLo: byte;
KarlHi: byte;
Hilf  : byte;

begin
  KarlLo:= ADC_Resultat;
  KarlHi:= 0;

Das ist der Anfang des Ganzen und der Ausgangspunkt für alles Weitere.
War das SOOO schwer?

jetzt mal ne Stegreif-Version für PIC:
    MOVF   KarlLo,W
    MOVWF  Hilf        ; Hilf:= KarlLo;

    BCF    Carry       ; Carry löschen, damit ne 0 reingeschoben wird
    RLF    Hilf,F      ; 1x links verschieben über Carry
    RLF    KarlHi,F    ; KarlHi:= KarlHi shl 1 und Carry ins LSB

    RLF    Hilf,F      ; Carry sollte 0 sein, da KarlHi=0 war
    RLF    KarlHi,F    ; dito, also alles bisher mal 4

    MOVF   Hilf,W
    ADDWF  KarlLo,F    ; KarlLo:= KarlLo + Hilf;
    BTFSC  Carry
    INCF   KarlHi,F    ; KarlHi:= KarlHi +  Carry aud der Addition
Jetzt haben wir KarlHi.KarlLo mit 5 multipliziert.

    MOVF   KarlHi,W    ; ganzen Teil abtrennen und ausgeben
    ADDLW  '0'
    CALL   GibZeichenAus
    CLRF   KarlHi

Für die nachfolgenden Schritte müssen wir mit 10 multiplizieren, also 
kommt noch dazu
    BCF    Carry
    RLF    KarlLo,F
    RLF    KarlHi,F
und der Rest ist wie bei obigem Multiplizieren mit 5.

SO. Nochmal pascalartig das Ganze:

var
  KarlHeinz: word;

begin
  Karlheinz:= ADC_Resultat;

  { 1. Ziffer }
  KarlHeinz:= Karlheinz * 5;
  GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0'));
  KarlHeinz:= KarlHeinz and 255;

  GibZeichenAus('.');

  { 1. Ziffer }
  KarlHeinz:= Karlheinz * 10;
  GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0'));
  KarlHeinz:= KarlHeinz and 255;

  { 2. Ziffer }
  KarlHeinz:= Karlheinz * 10;
  GibZeichenAus(chr(((Karlheinz shr 8) and 15) or '0'));
  KarlHeinz:= KarlHeinz and 255;


Also Leute, ich bin ja nun längst nicht mehr der Allerjüngste und 
Schnellste im Denken, aber ich sehe mit einigem Erschrecken, wie 
begriffsstutzig ihr jungen Spunde so seid. Lernt doch um Himmelswillen 
zuerst das logische Denken, bevor ihr euch ans Programmieren macht.

Es ist wirklich viel viel wichtiger, logisch und strategisch denken zu 
können, als irgendeine Programmiersprache gelernt oder den Umgang mit 
irgendeiner IDE/Toolchain geübt zu haben. Die obigen Vorschläge, an der 
Refrenz zu drehen, eine Tabelle zu basteln oder sonstwie das eigentliche 
Problem nicht zu lösen sondern zu umschleichen, sind allesamt OBERMURKS, 
der nur daraus rührt, daß die Schreiber eben noch nicht zu denken 
gelernt haben. Deshalb empfehle ich hier mal ein steinaltes Buch, das 
sich zwar auf den ebenso steinalten Z80 bezieht, aber an Aktualität 
nichts eingebüßt hat:

Lampe, B./Jorke, G./Wengel, H., Algorithmen der - Wiley Online Library
(http://www.hood.de/angebot/45547775/lampe-jorke-wengel-algorithmen-der-mikrorechentechnik.htm)

Lest das und lernt damit, Algorithmen zu verstehen und zu begreifen, wie 
man Probleme angeht und löst. Daß im Buch als Hardware der alte Z80 
herangezogen wurde, ist gut, denn das verhindert, daß Unbedarfte das 
Buch lediglich als ein Kochbuch für Copy&Paste ansehen. Stattdessen 
sieht man sich genötigt, den Sinn zu begreifen um die Algorithmen für 
heutige uC zu formulieren.


W.S.

von spess53 (Gast)


Lesenswert?

Hi

>Lampe, B./Jorke, G./Wengel, H., Algorithmen der - Wiley Online Library
>(http://www.hood.de/angebot/45547775/lampe-jorke-we...)

oder den Nachfolger:

http://www.ebay.de/itm/Arithmetische-Algorithmen-Mikrorechentechnik-Jorke-Lampe-Wengel-/250915667113

MfG Spess

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Karl Heinz Buchegger schrieb:
>> Zwischen dem, was er vom ADC bekommt und dem was er auf die Anzeige
>> zaubern will, liegt ein Zwischenschritt. Wie berechnet er sich die (zb.)
>> 8.8 Fixpunktzahl, die er dann schön ausgeben kann?
>
> Er berechnet sie überhaupt nicht, sondern setzt den ganzen Teil auf
> Null und lädt den gebrochenen Teil mit dem Ergebnis aus dem ADC. Das ist
> alles.

Echt?
Und das berechnet dann den Strom durch den Shunt, wenn er die Spannung 
über dem Shunt misst?

von W.S. (Gast)


Lesenswert?

Karl Heinz Buchegger schrieb:
> Echt?

Es ist Sonntag, mieses Nieselwetter und ich war jetzt ne Weile im Garten 
um den elenden Kirschbaum zu verschneiden - ergo, hab momentan keinen 
Gefallen an solchen Bemerkungen. Also, du Moritator, wenn schon, dann 
trag was Nützliches zum Thema bei.

W.S.

von Karl H. (kbuchegg)


Lesenswert?

> Irgendwann verzweifle ich an euch allen!!
> Lernt doch um Himmelswillen zuerst das logische Denken,
> bevor ihr euch ans Programmieren macht.

Vielleicht doch noch mal das Eröffnungsposting lesen, wo die Reise
überhaupt hingehen soll. Die 5V sind nur Zwischenziel. Die endgültige
Reise geht zu einer Strommessung und da bleibt es nicht aus, dass der
Widerstand des Shunts in die Rechnung eingeht.

von W.S. (Gast)


Lesenswert?

Oh, du KarlHeinz,

lies doch mal:

Manuel schrieb:
> Vorgabe ist ein Messbereich von 0-5V also hab die looUp..

Darum drehte sich das Ganze: 0 bis 5 Volt. Über den Shunt und etwaige 
weitere Bauteile vor dem ADC hat er sich nicht ausgelassen. Ist ja auch 
seine Schulaufgabe.

Mir ist schon klar, daß man für andere Meßbereiche auch andere 
Skalierungsfaktoren benötigt. Ich zitiere mich ausnahmsweise mal selber:
W.S. schrieb:
> Wir sehen also, daß
> die Wertigkeiten aller Bits von der Eingangsbeschaltung und der Referenz
> abhängt.

Oder formal Resultat:= HardwareabhängigerFaktor * ADCErgebnis;

Jetzt haben wir das Umwandeln eines ADC-Ergebnisses in einen Text 0.00 
bis 4.99 exemplarisch geübt und zwar ohne irgendwelche Tabellen, die 
bei einem linearen Problem grundsätzlich überflüssig sind. Wer das 
kapiert hat, sollte ab jetzt kein Problem haben, diesen Algorithmus auf 
andere Bereiche umzusetzen. Allerdings ist dazu wenigstens einmal eine 
Multiplikation nötig.

von Karl H. (kbuchegg)


Lesenswert?

W.S. schrieb:
> Oh, du KarlHeinz,
>
> lies doch mal:
>
> Manuel schrieb:
>> Vorgabe ist ein Messbereich von 0-5V also hab die looUp..

>> ich hab vollgendes Problem Ich muss für meine schule
> ein Strommessgerät entwickeln.

!

> Darum drehte sich das Ganze: 0 bis 5 Volt.

Er misst im 5V Bereich seines ADC!
Das heißt aber nicht, dass auf seiner Anzeige zum Schluss ein Wert 
zwischen 0 und 5 stehen soll. Schau dir die Tabellen an, die er bisher 
benutzt hat.

Ich sag ja nicht, dass deine Ausgabefunktion schlecht ist. Überhaupt 
nicht. Aber sie ist nur Teil seiner Lösung. Und ob er in der Lage ist, 
die notwendigen Änderungen da mit einzuarbeiten .... wage ich zu 
bezweifeln.

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.