Rechenoperationen // Bibliotheken dafür

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

Vorheriges Thema - Nächstes Thema

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

PICkel

#45
Das habe ich befürchtet:
Du hast nicht den Rt, sondern die Spannung an einem Spannungsteiler aus einem Fest- und einem variablen Widerstand zur Verfügung.
Die gemessene Spannung verhält sich stark nichtlinear zur Temperatur.
Nur mal als Bsp. aus Deinen Werten:
0°C: 0,83V
0°C bis 400°C: 1,639V ergibt (1,639-0,83)V/400°C = 0,0020225V/°C
0°C bis 650°C: ergibt: (1,967-0,83)V/650°C = 0,001749V/°C
400°C bis 650°C: 1,967V ergibt (1,967-1,639)V/250°C = 0,001312V/°C

Soviel erstmal zum Thema. Ob sich da etwas lineares draus basteln lässt, werde ich wohl nicht vor Samstag ausprobieren können.

Gruß
PICkel   

pic18

Die Kurve bei einen Temperaturfühler ist nicht linear, man nimmt da Temperaturfenster und nimmt da einen linearen Wert an. So machen es auch ältere Thermostate mit PT100. Hier kann man manchmal die Werte eingeben. Also Temperaturwerte und Faktor dazu.

PICkel

Hallo picass!

Ich habe mir das Ganze nochmal angeschaut.
Folgende Annahmen habe ich aus Deinen bisherigen Posts in Erinnerung:
- Speisespannung 5V (relativ stabil)
- Spannungsreferenzen am ADC des PIC: Vref- = 1V , Vref+ = 2V, also ADC-Messbereich 1V
- Im ADC-Mesbereich kann Rt= 250Ohm (65°C) bis Rt= 666Ohm (673°C) betragen

Der ADC hat bei 1V Messbereich und 10Bit eine Auflösung von ca. 1mV,
was einer Temp- Änderung von ca. 1°C entspricht. Das ist zu fein für diesen Anwendungsfall,
weil die Anzeige bei Änderung der Motorleistung nur am Zappeln wäre.
Deshalb schlage ich vor, nur die oberen 8Bit (ADRESH) des ADC auszuwerten.
Das gibt eine Auflösung von ca. 4mV in 256 Stufen, was einer Temp.-Änderung von ca. je 3°C entspricht.
In der EXCEL-Tabelle habe ich das in 10-er Schritten (40mV) nachgerechnet.

Aus der Spannung am Fühler lässt sich ganz einfach dessen Widerstand berechnen,
siehe Spannungsteiler.jpg.
Es gibt jetzt 4  Möglichkeiten der Temperaturberechnung:
1.) Multiplikation des Messwertes mit einem Faktor, das bringt bei konstantem Faktor Fehler bis zu ca. 50°C, siehe Spalte E in der Tabelle.
    Also muss der Faktor je nach Wertebereich unterschiedlich angesetzt werden.
    Siehe Beitrag von pic18
   
2.) Berechnung nach Deiner Formel, das ist ein ziemlicher Programmieraufwand in ASM 

3.) Berechnung in EXCEL in 4mV-Schritten und übertragen der 256 Werte entweder als Tabelle ins Programm oder händisch in den EEPROM-Editor

4.) Erstellen eines entsprechenden Programms (könnte ich Dir machen) für den PIC
    zum Beschreiben des EEPROM. Es ist dabei nur darauf zu achten,
    dass beim nächsten Brennen der Anzeigesoftware der EEPROM nicht überschrieben wird.
   
Kleines Manko beim 18F14K22: Die 256 * 1Byte EEPROM. Entweder die 256 möglichen Werte mit 3 multiplizieren oder 128 * 2Byte ablegen.   

Gruß
PICkel   
Spannungsteiler.jpg Temp_Berechnung3.jpg Temperatur3.zip     






pic18


https://www.heraeus.com/media/media/hne/datasheets/technical_information/Tabelle_Grundwerte_TK_3770_200_Ohm_DE.pdf

Hier ist die Tabelle vom PT200, warst Du schon hier? ich würde nur den ersten Teil der Formel nehmen
R0*(1 + 3,8285*10-3 * t), anschließend aus der Tabelle die Differenz je nach Temperaturfenster abziehen.

picass

Zitat von: PICkel in 18.12.2022, 19:29:10 CETHallo picass!
Ich habe mir das Ganze nochmal angeschaut.
3.) Berechnung in EXCEL in 4mV-Schritten und übertragen der 256 Werte entweder als Tabelle ins Programm oder händisch in den EEPROM-Editor
4.) Erstellen eines entsprechenden Programms (könnte ich Dir machen) für den PIC
    zum Beschreiben des EEPROM. Es ist dabei nur darauf zu achten,
    dass beim nächsten Brennen der Anzeigesoftware der EEPROM nicht überschrieben wird.
Gruß
PICkel

Hallo PICkel !
Da es in Assembler mit dem Berechnen der Wurzel nichts werden wird, kommt die Version 3 und 4 zum Einsatz. Das ist zumindest technisch für mich einfach, da ich schlicht mein schon seit über 2 Jahren im bewährten Einsazt befindendes Prog für die Öltemperaturanzeige in meinem Wagen nutzen kann.

Da ist an den Anfang des Progs eine Abfrage des Inhaltes einer speziellen EEProm-Zelle vorhanden. Wenn da nichts programmiert war, dann kommt die leere Menge zurück, falls doch, dann die spezielle "Geheimzahl". Wenn die stimmt, dann läuft das Prog normal und zeigt die Öl-Temp an. Wenn die leere Menge kam, dann verzweigt das Prog "nach hinten" und dort steht eine Routine, welche im Programm aufgeführte Werte nacheinander in die EEProm-Zellen füllt. Das funktioniert prächtig und deswegen und aus dem vorgenannten Grund wird das demnächst irgendwann mal so ausgeführt. Bin - wie gesagt - gerade anderweitig unterwegs.

@pic18
Muss mal sehen, ob der Platz im EEProm für alles reicht. Hundert Werte im 16-bit-Format passen rein, dann ist aber auch schon Schluss. Das händische Berechnen wird noch 'n Hammer. Für die Zwischenwerte wird wohl interpoliert werden müssen

Einen herzlichen Dank für eure Bemühungen, ich werde sie memorieren!
Danke und Grüße,  picass


picass

Mal wieder Mathe-Nachhilfestunde!

Was ist das Gegenteil eines Logarithmus?

Anders formuliert geht es um das Ausrechnen dieser Aufgabe:     10 hoch 0,7148

Ergebnis ist 5,1860.... is klar. Aber wie rechnet man das ,,zu Fuß", rsp. zerlegt diese Rechnung in eine alternative Rechenweise, wenn der Computer, genauer das Prog das nicht kann.

Wenn man das erwünschte Ergebnis 5,1840 nimmt und davon den Logarithmus berechnet, erhält man den Exponenten 0,7148. Na prima, jetzt nur die Umkehrung und das wärs dann. Dann könnte die Formel im Fred "Kellerbelüftung" berechnet werden, dies ist die letzte Hürde.

Grüße, picass

picass

#51
Au man, beinahe hätte ich es gehabt.... leider nur beinahe! :(

Habe in einer Anleitung für BASIC die "wissenschaftliche Schreibweise" für z.b. große, rsp. lange Zahlen gefunden, wie z.B.:
2*10², was im BASIC-Dialekt dann eingegeben würde mit "2E10+2" und das liefert dann erfreulicherweise via print-befehl als Ergebnis 200 dez . Jubel, also dann bei dem gewünschten Beispiel:

1*10 hoch 0,7148 im Basic eingeben  "1E10+0.7148" um zu Ergebnis 5,186 zu gelangen. Man gelangt ja auch, leider zu 1 dez ! >:(

Ist die Eingabe von Dezimalzahlen kleiner 1 nicht vorgesehen? Oder muss das in BASIC irgendwie anders eingegeben werden?
5 Schritte vor dem Ziel und noch gestolpert....!
Grüße, picass

PICkel

Hast Du die 185 Seiten Doku nicht genauer durchgesehen?
Die Schreibweise "2E10+2" (oder ähnlich) liefert Dir nur eine vereinfachte Darstellung der Zahlen.
Was Du brauchst, ist eine Potenzfunktion, z.B.: Zahl = pow(10, 0.7148), die Schreibweise des Funktionsnamens richtet sich natürlich nach dem verwendeten Compiler.

Gruß
PICkel 

Peter


picass

#54
Ne, ne: Nicht nur diese Doku kompletto durchgelesen, auch die englisch-sprachige Orig.-Version und zudem noch die für "MicroMite", was im Prinzip das Gleiche für den genannten  32-bit-PIC-Typen darstellt. Auch die Suche im Prog fand nichts außer "power"!

Eine "pow"-Funktion, rsp. irgendwas mit Quadrat gibt es in dieser Sprachversion nicht. In demjenigen Kapitel, in welchem die "wissenschaftliche Notation" aufgeführt ist, gibt es den Hinweis, dass die nur mit Fließkommazahlen funktioniert. Leider ist das ein sehr ungenauer Teil der Wahrheit und bezieht sich nur auf die Zahlen-Komponente vor der Hochzahl, also auf die "4,5" im nachfolgenden Zahlenbeispiel.  print 4,5E+3
Für den Exponenten gilt das Gegenteil: nur Ganzzahlen, also ohne Kommastelle.

Der Hinweis auf die vorige Deklaration als Fließkommazahl läuft aus dem Grunde auch ins Leere. Egal, was man da macht, z.B. den Exponenten in Klammern setzen.., hilft nichts. Es werden nur Ganzzahlen verarbeitet.

Die im Inet findbaren Hinweise auf die Umkehrbarkeit der Funktion - wie oben beschrieben - würden ja zum Ziel führen. Nur sind sie wenig  bis nicht verständlich geschrieben. In den vermeindlichen Ausführungen werden Zahlen und Variablen aus der Luft gegriffen und ohne Erklärung über die Herkunft genutzt. Nicht ein einziges Beispiel ist nachvollziehbar aufgeführt. Da hat mal wieder einer vom anderen bis zur extremen Potenzierung abgeschrieben, alle fanden sich ganz prima, aber keiner war auch nur im Ansatz in der Lage, sich adäquat für den Empfängerkreis auszudrücken.
Grüße, picass

Peter

Merkwürdig sollte aber eigentlich gehen. Dafür muss es doch
Befehle geben. In Mikrobasic sind das nur 2 Zeilen Code.

DIM Zahl as FLOAT
Zahl = pow(10,0.7148)

Das ist alles.

Du kannst es aber auch ohne Komma darstellen und berechnen. Und
zwar so: \( \sqrt[10000]{10^{7148}} \) Aber die Zahl wird dann wahrscheinlich zu
gross um sie zu berechnen.




picass

#56
Bin die Anleitungen noch mal rauf und runter: NIX !
Es gibt keine Funktion zum Potenzieren, auch nicht zur Basis 10. Habe auch in der Suchfunktion alphabetisch gewühlt, nix unter "p".
Auch weitere, wenn auch inzwischen sinnlose - weil sich im Kreis drehende - weitere Versuche: nix, als Exponent werden nur ganze Zahlen akzeptiert. Auch das vorige Festlegen einer Variablen und deren Deklaration als Fließkommazahl - was in dieser Basicversion durch das einfache Anfügen des Ausrufezeichens - "!" - direk an die Variable geschieht und dann diese Variable als Exponent gesetzt: funktioniert prächtig, solange es Ganzzahlen sind, aber sobald ein Komma, rsp. hier ein Punkt auftaucht, ist Schluss mit Lustig.

Das Schreiben als "wissenschaftliche Notation" war ja nur ein Hilfskonstrukt, weil eine Rechenfunktion mit Exponenten nicht existiert, nützt halt nur nichts.
Der Logarithmus zur Basis 10 wird korrekt ausgegeben, nützt nur ebenfalls nichts, ist nur eine Randbemerkung.

Dieses Umschreiben 1000. Wurzel aus 10 hoch sowieso wird auch nichts nützen: es gibt die Funktion des Wurzelziehens, aber die Eingabe von weiteren Zahlen ist nicht vorgesehen... wüsste auch nicht, wie man das händisch rechnen soll. Habe das spaßeshalber mal mit dem Taschenrechner versucht, aber schon der Versuch, die Potenz von 10 hoch 0,45 zu ermitteln, indem die hunderste Wurzel aus 10 hoch 45 errechnet wurde, schlug fehl. Da stimmt auch irgendwas nicht.

Weiß im Moment nicht, ob die Rechnung 10 hoch 0,7148 (als Beispiel) sich irgendwie anders ausführen ließe. Mist, ist die einzige Stelle, welche noch klemmt, sonst könnte ich das Projekt "Kellerentlüftung" wahrscheinlich elegant vom 18F-PIC auf so'n 32-Bitter umswitschen und das Prog wäre ruck-zuck fertig.

Da bin ich extra - nicht nur, aber vor allem - wegen der ungenügenden Rechenfähigkeit der 8-bit-Welt entflohen, nur um im "Hochbereich" auf dieselben Probleme zu stoßen.
Grüße, picass

PICkel

#57
Habe grade gelesen, dass MMBasic kein Compiler sondern ein Interpreter ist, der auf einem wohl schon älteren Befehlssatz aufbaut.

Probiere doch mal:

print exp10(0.7148)
oder vielleicht auch
print 10^0.7148


Peter

Das würde bedeuten das jeder Controller ein Bios
haben muss wo die Befehle interpretiert werden müssen.
Ob das dann für kleinere Prozessoren noch geht da sie ja nicht
soviel Platz haben. Und das ausführen des Programms müsste ja dann
auch länger dauern als wenn man es direkt in einem Compiler eingibt
und das Programm wird dann in eine Sprache übersetzt welcher der
Prozessor kann.

PICkel

@Peter:

Stimmt! Das steht dazu auf mmbasic.com:
"MMBasic is written in ANSI C.  It requires a 32 bit microcontroller and uses about 94KB of program space (flash memory) and as little as 16KB RAM.  It was originally written for the Microchip PIC32 series of microcontrollers but has been ported to the ARM STM32 and Windows/DOS."

Damit sind die minimalen RAM/Flash- Größen absehbar. Ganz abgesehen davon, dass wohl viele Befehle in Textform mehr Speicherplatz benötigen als die entsprechenden ASM-Befehle.
Der Interpreter wird beim Reset gestartet, ähnlich einem Boot-Loader und liest und interpretiert dann den Quelltext.
Und zeitkritische Abläufe muss man dann wohl doch in ASM schreiben, wenngleich die hohe mögliche Taktfrequenz vieles vereinfacht. Wie man aber für eine bestimmte Aufgabe die Anzahl der Prozessortakte bzw. die dafür benötigte Zeit feststellen will, ist mir unklar.

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:
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