Rechenoperationen // Bibliotheken dafür

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

Vorheriges Thema - Nächstes Thema

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

picass

Zitat von: PICkel in 12.12.2022, 14:45:06 CETAndere Möglichkeit: Mit einer "höheren" Programmiersprache ein Prog. schreiben, Gruß
PICkel
Hallo PICkel!
Die Hochsprache....! Sobald ausreichend komplett lauffähige Beispiele in unserem Projekt für PIC-Anfänger auch in Basic vorliegen, werde ich einen neuen Anlauf nehmen.

Die angefragte Formel:
Da befindet sich in einem Datenblatt einer Firma, welche den orig. Haereus-Sensor PT200 zur Herstellung eines realen Sensormoduls verwendet, eine prima Formel, siehe Bild1. Nicht prima ist es, dass diese Formel zur Berechnung des Widerstandswertes dient. In der ist der gewünschte Faktor T für Temperatur gleich zweimal enthalten, einmal davon noch im Quadrat. Beides führt zum Elend und zur Notwendigkeit, die Formel nach T umzustellen nach dem Prinzip einer quadratischen Ergänzung. Auf diesem Weg hatte ich mich verstrampelt und mir daher Hilfe organisiert. Die Auflösung der Formel und das Endprodukt findet sich im Bild2.
Da es - wie du auch festgestellt hattest - in diesem Anwendungsfall mitnichten um genaue Werte geht - eine Abweichung von 10° C wäre nicht schön, aber würde unterm Strich doch nützlich sein, könnte bei dem Handeln der einzelnen Werte durchaus großzügig vorgegangen werden. Es muss sich aber halt in den Assembler reinquetschen lassen.

Genau muss es natürlich nicht, der Weg über die Tabelle wäre ja auch noch da, aber auch aus Gründen der Neugier wäre der Formelweg schon eine tolle Sache.
Grüße, picass

PICkel

Soooo, Du wolltest wissen, wie man so eine Berechnung in ein Programm überführt:
Ich habe mal die Formel sowohl in EXCEL als auch in mikroBASIC nachempfunden.
Die Rechnung wurde für eine Temperatur von 250°C ausgeführt.

Im EXCEL-Sheet steht die Formel in ihrer ganzen Schönheit in Zelle B8 und in D8 ist sie nochmal zum Mitlesen als Text abgelegt. Diesen Formel- Bandwurm will man sich sicher nicht in einem uC-Programm antun, denn soetwas zu debuggen grenzt an Masochismus.
Deshalb wurde die Formelberechnung aufgeteilt: Wert1...Wert4 und das Ergebnis der Wurzel. Siehe auch die EXCEL-Tabelle und Temp_Berechnung1.jpg. Damit wird die Sache übersichtlicher und man kann anhand der Tabelle die vom uC berechneten Werte kontrollieren.
In Temp_Berechnung1.jpg sieht man die berechneten Werte von EXCEL und die vom Debugger angezeigten Werte zum Vergleich. Das Prog. belegt 4198 Byte Speicher.

Eine leichte Verbesserung erhält man, wenn man die konstanten Ausdrücke
R0*alpha, (R0*alpha)^2 und 2*R0*beta vorab berechnet und als Zahlenwerte zuweist. Das Prog belegt dann "nur noch" 4028 Byte.
Die zweite Version ist in Temperatur.mbas vorhanden, aber auskommentiert.

Fazit: 32-Bit-Gleitkommaarithmetik auf 8-Bittern ist ein Speicherfresser und es macht  sicher keinen Spaß, das in ASM zu proggen. Weiterhin übersteigt die Programmgröße das Limit der mikroBASIC-free-Version (2kByte).

 
program Temperatur
' PIC18F14K22

' Declarations section 
dim alpha, beta, R_0, R_t as float   volatile
dim ergebnis as float
dim Temperatur as word
dim Wert1, Wert2, Wert3, Wert4, Wurzel as float volatile

main:
'   Main program 
R_0 = 201.              ' 0°C-Widerstand
R_T = 385.11            ' 250°C-Widerstand

'* erste Möglichkeit mit berechneten Werten:
'* 4198 Byte Programm, 6,93ms @ 8MHz bis NOP
alpha = 0.0038285
beta = -0.000000585
Wert1 = R_0 * alpha     ' 201 * 0.000000585
Wert2 = Wert1*Wert1
Wert3 = 4*R_0*beta*(R_0-R_T)
Wurzel = sqrt(Wert2-Wert3)
Wert4 = 2*R_0*beta

'* zweite Möglichkeit mit vordefinierten Werten:
'* 4028 Byte Programm, 6,64ms @ 8MHz bis NOP
'Wert1 = 0.769529
'Wert2 = 0.592174
'Wert4 = -0.000235
'Wert3 = 2*Wert4*(R_0-R_T)
'Wurzel = sqrt(Wert2-Wert3)
'
ergebnis = (-Wert1+Wurzel)/Wert4
Temperatur = word(ergebnis)
 nop
end.

Temp_Berechnung1.jpg
temperatur.zip

picass

Hallo PIKcel!

Du hast – mal wieder – grundlegende Recherchenarbeit betrieben. Dafür ein herzliches Dankeschön.
Deinen Worten würde  ich entnehmen wollen, das so'n 8-bit-PIC was den Zeitbedarf der Berechnung anbelangt eher nicht ein angesagtes Teil für solche Berechnungen wäre. Die Botschaft höre ich, wenngleich mir das – bitte beachten – in genau diesem einen Anwendungsfall egal wäre: die Änderung der Temperatur im Dieselpartikelfilter von der normalen Betriebstemperatur von irgendwas im Bereich von 180° C bis 250° C auf die Regenerations-Temp von irgendwas oberhalb von 450° C würde mindestens 2 min brauchen. Und die hohe Temp verharrt dann auch für gut 10 Minuten. Die Zeit wäre also kein Prob.

Aber sehr wohl habe ich vernommen, dass solche Formel in Assembler nur für Masochisten bearbeitbar wäre. Nun gut, da möchte ich mich – is klar – ungerne einreihen, also das lassen. Basic kann ich nicht, bleibt nur der Weg über die Tabelle. So gut, so schlecht. Das wird ,ne ziemliche Fleißarbeit, um das positiv zu verbrämen. Nochmal danke für deine aufklärenden Arbeiten.
Grüße, picass

PICkel

#43
Hallo picass,
das Formelungetüm mit Gleitkommazahlen lässt sich vermeiden:
Deinen Ausführungen vom 13.12.22 entnehme ich, dass Du den Wert von Rt schon berechnet hast, sonst würde ja die Formel keinen Sinn machen.
Schaut man das Diagramm an, so sieht man einen fast linearen Zusammenhang zwischen Temperatur und Rt. Geht man der Sache nach, so ergibt sich in guter Näherung folgende Formel:
Temperatur = (Rt-201)/0,71        (Die 201 ist der Widerstand bei 0°C)
Diese Formel hat im Wertebereich von ca. 300°C...600°C einen Fehler von <3%.
Das sollte eigentlich ausreichend genau sein. Schreibt man:
Temperatur = (Rt-201)*100/71 , vermeidet man die Gleitkommaberechnung mit dem Divisorr 0,71 und die Berechnung kann komplett mit Integer-Zahlen stattfinden.
Genauere Werte, vor allem am oberen und unteren Ende des Wertebereichs erhält man natürlich mit einer Tabelle.

Gruß
PICkel
Temp_Berechnung2.jpg



picass

#44
Au man, mit Zahlen hast du es. Mithilfe dieser stark verküzten Formel wäre es in der Tat möglich, zu arbeiten. Die Ergebnisse sind im Bereich von 200° C bis 500° C im Bereich eines Fehlers unter 10° C. Das wäre super. Oberhalb 600° C werden die Abweichungen größer, ab 700° C dann schon erheblich (25° C). Aber eine Anzeige bis 650° C würde für den angestrebten Zweck absolut reichen. Aber....
...aber nu weich ich mal von meinen theoretischen Vorüberlegungen ab und komme zum angetroffenen Fall der Praxis.
Der PIC18F14 liest an einem PORTA-Pin die sich just ergebende Spannung ab, welche abhängig ist von der aktuellen Temperatur im Diesel-Partikel-Filter. Das ist diejenige Spannung, welche am aktuellen Wert des PT200-Messwiderstandes abfällt. Wie das geschaltet ist und was sich da an Spannungen ergeben kann, ist im nachfolgenden Bild dargestellt.
Und das muss umgesetzt werden, im optimalsten Fall in die Anzeige "echter" Temperaturen. Es handelt sich um den Spannungsvereich - vergröbert gesagt - von 1 bis 2 Volt.
Grüße, picass

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:
Verifizierung:
Bitte lassen Sie dieses Feld leer:
Geben Sie die Buchstaben aus dem Bild ein
Buchstaben anhören / Neues Bild laden

Geben Sie die Buchstaben aus dem Bild ein:

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