Rechenoperationen // Bibliotheken dafür

Begonnen von picass, 11.05.2022, 18:20:53 CEST

Vorheriges Thema - Nächstes Thema

picass

Nicht wirklich, also die Kommastellen! Im normalen Prog ohne die Mittelwertbildung (MWB) tauchen keine auf. Interessant wäre es höchstens, nach der MWB evtl. eine Art Rundung für die letzte Stelle noch anzufügen. Im Moment ist das Prog noch in der Entwicklungsphase. Am besten teste ich es mal.

Testen muss ich leider auch das noch ungelöste Thema der Divisionen. Für 8 bit Div. ganzer Zahlen habe ich da was Ausreichendes, benötigt werden aber auch 16 bit-Divisionen. Habe gestern nochmal eure Links mit Hinweisen durchgeforstet, und so recht nichts gefunden. Entweder ist das eine Mischung aus - was weiß ich: "C" mit Assembler - oder es sind so stonealte von 1996 und früher, dass die damalige Assemblersprache kaum zu verstehen ist, siehe auch meine Versuche mit der Vorlauge aus dem Buch der beiden König-Doktoren.
Grüße, picass


pic18


picass

Habe mir den Link auf eine der Seiten gespeichert und werde mir das beizeiten zu Gemüte führen. Dabei gefunden hatte ich ein Beispiel, das stammt zwar auch aus dem Jahr 1996, ist jedoch von der Schreibart her gut verständlich. Es gibt da anscheinend Programmierer, die schaffen es, ein gut leserliches Prog zu hinterlassen. Andere scheinen eher darauf aus zu sein, sich selbst als "Experten" raus zu stellen, denken aber nicht im Ansatz daran, da etwas Leserliches zu schaffen.

Hier mal ein kleiner Auszug aus "großer Mathematik", die Division einer 16-bit-Zahl durch 4 für Assembler-Freunde:

- das low-Byte (lB) zweimal nach rechts shiften;
- bit0 und bit1 des high-Bytes (hB) händisch auf bit6 und bit7 des lB übertragen.
  Händisch: Test auf ,,0" und entsprechend die beiden Bits setzen;
- das hB 2x nach re shiften;
- die beiden obersten Bits des hB auf Null setzen.

Grüße, picass

picass

Da gibt es schon Putziges: der PIC mag meine Routine mit der Mittelwertbildung nicht.
Sobald sie eingefügt ist, steigt er nach ca. 6 Sekunden aus, indem er nur noch Nullen zur Anzeige rausgibt. Kommentiert man die Routine raus (durch Semicolon), zeigt er brav alles an, die Skala der zu erwartenden Zahlen rauf und runter. Ist sie wieder drin, zeigt er auch brav die Skala an, auch mit aktiven Veränderungen, aber eben nur in den ersten ca. 6 Sekunden....!
Pro Sec tätigt er - geschätzt am Geflimmer der Anzeige - ca. 10 Messungen. Demgemäß erledigt er gut 50 Messungen, danach führt er ein Eigenleben. >:(
Grüße, picass

pic18

ich würde die Divison durch 2 so schreiben:
MOVLB VAR16; Bank laden

BCF STATUS,C; Carry Bit löschen
RRCF (VAR16)+1,F,BANKED; HI nach rechts schieben mit Carry
RRCF (VAR16),F,BANKED; Lo nach rechts schieben mit Carry

Im Carry bit steht dann die Kommastelle, die weiterverarbeitet werden kann

picass

Das ist dann in welcher Prog-Sprache?
Nix für ungut, das verstehe ich nicht, rsp., es hilft mir nicht. In Assembler gibt es - soweit ich weiß - keine Möglichkeit, einzelne Bits von einem Byte in ein anderes direkt zu schieben. Diese Rotate-Befehle beziehen sich immer nur auf ein einzelnes Byte, das gilt auch für das Carry-Bit.

Diese spezielle Rechenroutine des Dividierens hatte ich mit mehreren Zahlen-Beispielen überprüft, das hatte immer das zu erwartende Ergebnis gebracht. Den Floh erwarte ich woanders: in der Routine steckt auch eine Schleife, vielleicht klappt der Aussprung nicht zuverlässig.
Grüße, picass

pic18

Das ist Assembler,
RRCF Rotate Right f through Carry

schiebt die Bits nach rechts, Bit 0 ins Carry-Bit und Carry-Bit ins Bit 7.
Wenn Du das Carry-Bit löscht und dann das Hi-Byte nach rechts schiebst, dann wird Bit 7 gelöscht und Bit 0  wird ins Carry-Bit geschoben. Wenn Du dann das Lo-Byte nach rechts schiebst, dann wird das Carry-Bit (Bit 0 vom Hi-Byte) ins Bit 7 übernommen, Bit 0 kommt dann ins Carry-Bit.
Das ganze kannst Du mit beliebig vielen Bytes machen. Du mußt nicht irgendwelche Bits extra ins andere Byte übertragen, das geht alles automatisch übers Carry-Bit.

0 -> C -> Hi-Byte -> C -> Lo-Byte -> C

picass

#28
Au man, pic18, da hab' ich echt was gelernt von dir! Hatte die Vorstellung, dass das Carry-Bit (CB) sozusagen ein persönliches ist, welches zu einem individuellen Byte gehört. Dass dieses CB gänzlich unabhängig und ohne Übergang jedwedem anderen Byte zum Nutzen zugeordnet werden kann, stand nicht auf meinem Radar. Danke für die Aufklärung, werde das baldmöglichst ausprobieren.

Baldmöglichst..... :(
Habe mich heute abgequält, den Floh in meiner Routine zur Mittelwertbildung (RzMMB) zu finden. Ich habe ihn gefunden und beseitigt, weiß aber nicht, wie  er heißt und warum er da war. Will sagen, der Fehler ist raus, das Gesamt-Prog - Anzeige einer analogen Spannung auf 4-stelliger-7-Segment-Anzeige läuft nun wieder sauber. Mit der RzMMB war nach 5 Sek Schluss mit Lustig und es wurden nur Nullen angezeigt. Nunmehr alles paletti! Ausgerechnet das Sicherheits-Feature in der Schleife, welches den Ausstieg ermöglichen sollte, falls mit dem Zählen was nicht klappt, war der Fehler. Die Si-Überprüfung habe ich aus der Schleife rausgenommen und davor eingefügt, nun läuft es. Warum das Gleiche in der Schleife zu ungutem Ergebnis führt, ist mir nicht klar. Aber im Moment reicht es mir, den Floh erschlagen zu haben. Warum der da war....., das lasse ich jetzt mal ruhen und gebe mich mit dem Ergebnis zufrieden.
Ach ja: danke für deinen Tipp mit der Relocate-Funktion, pic18.
Grüße, picass

pic18


picass

#30
Ja! :D
Aber nicht das mit dem Mittelwert, das habe ich vorerst aussortiert und durch eine einfache Zeitschleife ersetzt, was die gleiche beruhigende Wirkung hat. Aber es gibt seit heute ein anderes Rechenproblem, und da bin ich im Moment Matsche, weil ich nix verstehen!
Das jetzige Dilemma: in dem Regenerierprojekt werden über den analogen Eingang die Werte eines Spannungsteilers eingelesen. Weil die anfallenden Werte alle nur im Bereich zwischen 1 und 2 Volt liegen, hatte ich den ADC-Wandler angewiesen, auch nur diesen Bereich zu nutzen, wodurch die Auflösung besser wird. Prima, nur unterhalb des Bereiches, also von 0 bis 1 Volt liest der ADC folgerichtig nur Nullen ein. In einer Routine wird durch einfache Subtraktion überprüft, ob eine bestimmter Schwellwert überschritten wird. Und gettz die Überraschung: die Subtraktion des Wertes Null von dem Schwellwert, hier z.B. der Zahl 500 klappt nicht. Also 500 minus 0 ergibt ein negatives Ergebnis laut PIC.

In der Routine ist der Null-Wert in der Variablen adclow und adchigh abgelegt. Die 500 stecken in bitlow und bithigh. Also nun adc in das Wreg und dieses von bit subtrahieren. Im Falle des high-bytes klappt das, aber nicht im völlig gleichartigen  low-byte. Ich werd noch irre, was sehe ich da nicht?
In der zip-datei steckt ein asm-File, das ist lauffähig mit MPASM5.2 für den PIC18F14K22
Grüße, picass

pic18

Ich habe schon lange nichts mehr in Assembler programmiert. Kann sein, das ich einen Denkfehler habe.
Ich würde es so schreiben.
schwell012:
MOVF ADLO,W,BANKED; lade ADLO nach W
SUBWF BITLO,F,BANKED; BITLO = BITLO-W
MOVF ADHI,W,BANKED; lade ADHI nach W
SUBWFB BITHI,F,BANKED; BITHI = BITHI-W-!C
BN negativ; verzweigt wenn Ergebnis negativ ist
BRA positiv_or_gleich; Ergebnis ist positiv oder gleich
hier wird allerdings BIT(Lo,Hi) mit dem Ergebnis überschrieben.

picass

Danke für dein Engagement! :) Auch, wenn es ins Leere läuft! :(
Dein Prog-Schnipsel ist exakt so wie der meinige, nur dass du beim Highbyte noch das Carrabit berücksichtigt hattest. Aber das war - pardon - nicht das Thema.
Tatsächlich ging es darum, dass zwei exakt gleich geschriebene Subtraktionen jeweils von zwei Ein-Byte-Wörtern im einen Fall funktionierte, im anderen Fall jedoch einen  Fehler produzierte, indem fälschlich das Negativ-Flag gesetzt wurde. In plattem Deutsch: zieht man von einer positiven, ganzen Zahl die Zahl Null ab, darf natürlich kein negatives Ergebnis rumkommen.

Um das Dilemma zu verdeutlichen, habe ich aus dem Mini-Prog von gestern die Subtraktion der High-Bytes raus gestrichen und nur diejenige der beiden Low-Bytes drin gelassen. Und wieder wird das N-Flag gesetzt!

Ein mathematisches Wunder ereignet sich! Schaut genau hin, ihr lernt eine absolut neue Mathematik kennen. Vergesst eure Schul-Kenntnisse und der Uni-Abschluss ist auch nichts mehr wert: Null abziehen und schon ist eurer Gehaltskonto fett im Minus!!!
Grüße, picass

picass

#33
Das Problem besteht in der ursprünglichen Version immer noch, also im dem Prog des Beitrages von 19 Uhr, vorgestern.
Das heute eingestellte Prog ist leider dafür misslungen, pardon für die Verwirrung. Aber im Beitrag von gestern (19 Uhr) sind zwei voneinander unabhängige Subraktionen dargestellt, deren Syntax nach meiner Sicht exakt gleich ist. Die eine funktioniert, es wird also kein Negativ-Flag angezeigt, die andere nicht, da gibt es trotz der Subtraktion einer Null ein N-Flag!
Grüße, picass

pic18

Zitat von: picass in 01.09.2022, 11:01:14 CESTDein Prog-Schnipsel ist exakt so wie der meinige, nur dass du beim Highbyte noch das Carrabit berücksichtigt hattest.
Das sehe ich nicht so, ich rechne das Ergebnis aus, während du die beiden jeweiligen Bytes vergleichst. Dann mußt Du zuerst die Hi-Byte vergleichen und anschließend die Lo-Byte. Nicht umgekehrt!
Du vergleichst also zuerst die Hi-Byte, wenn das Ergebnis kleiner ist verzweigst Du, ansonsten vergleichst Du anschließend die Lo-Byte und verzweigst dann entsprechend. Das Negativ - Bit sollte eigentlich nur bei einem negativen Ergebnis gesetzt werden. Du kannst aber auch noch das Zero-Bit testen, das Carry-Bit sollte invers zum N-Bit sein, das kannst Du auch mal testen.

picass

Hab' den Bock gefunden, hat nichts mit der Behandlung von 16 bit-Zahlen, rsp. Ausdrücken zu tun. Passiert bei schlichtester Subtraktion von zwei 8bit-Zahlen:

Solange der Minuend kleiner ist als hex'a1', also dez'161', solange läuft alles korrekt. Sobald aber der Minuend gleich oder größer h'a1' ist, taucht nach der S das N-Flag auf. Wohlgemerkt, das Ergebnis ist richtig, also der Wert der Differenz wird korrekt angegeben, aber bei 180 minus 5 gibts mit dem Ergebnis 175 als Zugabe das N-Flag!
Verstehe wer mag , auf jeden Fall ein Fehler im MPLAB, rsp. dem Assembler.

Weil in meinem Programmteil für die Verzweigung dieses N-Flag abgefragt wurde, lief das Prog aus dem Ruder. Das muss nun also anders gehändelt werden.
Grüße, picass

pic18

ich habe im Moment leider nur den Linux-Rechner. Da kann ich die alte MPLAB nicht laufen lassen. Mit MPLAB-X kenne ich mich mit dem Simulator nicht aus. Verstehen würde ich es bei einem Wert >0x7F

picass

Schau mal auf das Bild und beachte die Gleichzeitigkeit von N- und C-Flag ! >:(
Grüße, picass

picass

#38
Versteht jemand das nachstehend abgebildete Rechenbeispiel? Es handelt sich um Wurzelziehen, hier im Dualsystem:
-------------------------------------------------------------------
Quadratwurzel aus 2 binär
      1. 0  1  1  0  1
    ------------------
   / 10.00 00 00 00 00     1
/\/   1                  + 1
     -----               ----
      1 00                100
         0               +  0
     --------            -----
      1 00 00             1001
        10 01            +   1
     -----------         ------
         1 11 00          10101
         1 01 01         +    1
         ----------      -------
            1 11 00       101100
                  0      +     0
            ----------   --------
            1 11 00 00    1011001
            1 01 10 01          1
            ----------
               1 01 11 Rest
---------------------------------------------------------------------------
Gefunden wurde das hier:https://de.wikipedia.org/wiki/Schriftliches_Wurzelziehen

Letztlich geht es für mich um die Lösungs des Probs, für das Projekt Anzeige der Dieselpartikelfilter-Regeneration einen Weg zu finden, wie man aus den "technischen Zahlen", welche der Analog-Eingang des PIC ermittelt, diejenigen einer "echten" Temperatur ermittelt. Generell gibt es die zwei Wege: eine Tabelle anlegen und/oder via Formel berechnen.

Wahrscheinlich werde ich den Weg über eine Tabelle gehen müssen. In der sind die Temp-Werte in 10-er-Schritten festgelegt. Um nun die Zwischenwerte auch ermitteln zu können, sind ein Haufen Zeugs an Interpolation, Multipl., Division, etc. nötig. Die Formelnutzung (FN) wäre eleganter, würde eine irre Menge an Zeit ersparen, wenn die Vorbereitung der Ermittlung der Tab-Werte - für jeden einzelnen sind per Taschenrechner Umrechnungen nötig - wegfallen könnte. Die FN erfordert aber gegen Ende dieser Berechnung das Ziehen einer Wurzel. Da es um um ganzzahlige Temp-Werte geht, sind Nachkommastellen überflüssig.
Mit Verlaub: wie die "händische" Berechnung im obigen Beispiel funktioniert, hat sich mir nicht dargestellt. :(
Grüße, picass

PICkel

Der 18F14K22 hat einen EEPOM mit 256 Byte. Lege darin eine Tabelle für die Temperaturen an.
Nimm die 8 höherwertigen Bits der ADC-Ausgabe (ADCON2:ADFM=0, ist Vorgabe nach Reset), dann hast Du schon die 256 EEPROM-Adressen und fülle diese mit den dazugehörigen Temperaturwerten.

Je EEPROM-Speicherzelle kannst Du ja nur Werte von 0...255 ablegen, was zu wenig für den gewünschten Temperaturbereich ist.
Du hast also die Wahl:
1.) 256 1-Byte-Werte, die noch mit einem Faktor (2, 3 oder 4) multipliziert werden müssen.
2.) 128 2-Byte-Werte aus je 2 aufeinanderfolgenden Bytes, die damit möglichen 1023°C reichen.

Und: Für diesen Anwendungsfall genügt eine relativ geringe Anzeigegenauigkeit. Selbst Sprünge von 10°C sind in dem Anzeigebereich von mehreren 100°C tolerierbar.

Du hast schon die Formel, also kannst Du z.B. mit EXCEL die Tabellenwerte berechnen.
Andere Möglichkeit: Mit einer "höheren" Programmiersprache ein Prog. schreiben, einen uC damit programmieren und den uC diese Werte berechnen in den EEPROM dieses uC schreiben lassen, diesen Inhalt als hex oder txt wieder auslesen und in Dein Programmiertool einlesen.

(Schreib' doch einmal die Formel hier ins Forum rein, damit man eine Vorstellung bekommt.)

Gruß
PICkel

Schnellantwort

Achtung: In diesem Thema wurde seit 120 Tagen nichts mehr geschrieben.
Wenn Sie nicht absolut sicher sind, dass Sie hier antworten möchten, starten Sie ein neues Thema.

Name:
Tastenkürzel: Alt+S Beitrag schreiben oder Alt+P für Vorschau