PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Programm läuft, aber....



BoGe-Ro
15.06.2010, 14:43
Hallo Forum,

Ich benutze einen ATMega 8 um das Ausgangssignal eines UTI von der Firma Smartec auszuwerten, um damit die Widerstände von PT100-Sensoren zu messen und die Temperatur zu gewinnen.

Diese wird dann im ATMega gemittel, sowie der Anstieg berechnet.

Das alles haut wunderbar hin.

ABER:

Ich habe durch Optimierungen, Vereinfachungen und Verbesserungen alte ungenutzte Fragmente im Code, sowie Variablen im Speicher, die einfach überflüssig sind und Speicherplatz belegen, den ich für weitere Mittelwertbildungen gut gebrauchen könnte.

Wenn ich diese nun aber rauslösche oder auskommentiere startet mein ATMega ständig neu, schafft ab und an mal eine Temperaturmessung /-berechnung um dann wieder neu zu starten.


es geht hauptsächlich um die Long-Variable Capture auf &H150
sowie um das Array UTI(..) welches ich letztlich nur noch bis uti(10) benötigen würde.





Nachfolgend mein Quellcode


$regfile = "m8def.dat"
$crystal = 8000000
$baud = 57600
$framesize = 100
$swstack = 100
$hwstack = 100
'$sim



Icp1 Alias Pinb.0 : Config Icp1 = Input : Portb.0 = 1


'################# UTI ################################################## ##
On Capture1 Oncapture 'Pd4
On Ovf1 Onoverflow

Tccr1a = 0 'Kein Compare-Mode
Tccr1b.icnc1 = 0 'NoiseCancel
Tccr1b.ices1 = 1 'steigende Flanke
Tccr1b.cs12 = 0
Tccr1b.cs11 = 0 '001 - kein Prescaler
Tccr1b.cs10 = 1
Enable Interrupts

Dim Capture As Long At &H150

Dim Uti(68) As Long , Uti_sort(6) As Long , Uti_summe(6) As Long
Dim Plaus1 As Word , Plaus2 As Word , Plaus1_string As String * 4 , Plaus2_string As String * 4
Plaus1_string = "0000" : Plaus2_string = "0000"
Dim Durchlauf As Byte : Durchlauf = 0

Dim Werte As Long
Dim Wcapture As Word , Wcapturealt As Word , Wzaehler As Word , Woverflow As Word


Dim Ready As Bit : Ready = 0 'Statusbit Messung
Dim Index As Byte : Index = 1
Dim Index1 As Byte : Index1 = 1
Dim R_ref As Byte : R_ref = 100 'Größe des Referenzwiderstandes
Dim Delta_t As Byte : Delta_t = 8

Declare Function Ohmgrad(t_off1 As Long , T_off2 As Long , T_ref As Long , T_x As Long , R_ref As Byte) As Single

'Werte aus http://www.abmh.de/pt100/#umr
Const A = 3367.8214408825
Const B = 11342221.257667569
Const C = 17235.4360565322

Dim I As Byte : I = 0
Dim J As Byte : J = 0
Dim K As Byte : K = 0



'####################### Temperaturen #####################################
Dim T1 As Single , T1_string As String * 5 , T1_word As Word
Dim T2 As Single , T2_string As String * 5 , T2_word As Word
Dim T1_ringpuffer(32) As Word , T2_ringpuffer(32) As Word

Dim Rp_counter As Byte , Rp_pointer As Byte

Dim 8_werte_mittel_t1 As Long , 16_werte_mittel_t1 As Long , 32_werte_mittel_t1 As Long
Dim 8_werte_mittel_t2 As Long , 16_werte_mittel_t2 As Long , 32_werte_mittel_t2 As Long

Dim 8_werte_mittel_t1_string As String * 4 , 16_werte_mittel_t1_string As String * 4 , 32_werte_mittel_t1_string As String * 4
Dim 8_werte_mittel_t2_string As String * 4 , 16_werte_mittel_t2_string As String * 4 , 32_werte_mittel_t2_string As String * 4

Dim 32_werte_mittel_t1_rp(32) As Long ', 32_werte_mittel_t2_rp(32) As Long

Dim Anstieg_t1 As Integer , Anstieg_t2 As Integer
Dim Anstieg_t1_str As String * 5 , Anstieg_t2_str As String * 5

Dim Help_byte As Byte
Dim Init As Bit : Init = 0
'################################################# #############################


Print : Print "NEUSTART" : Print
Do
Gosub Temperaturen
Incr Durchlauf
'Waitms 500
Loop
End



Temperaturen:
Ready = 0
Index = 0
Timsk.ticie1 = 1 'Input Capture Interrupt enable
Timsk.toie1 = 1 'Overflow Interrupt enable
Do : Loop Until Ready = 1
Timsk.ticie1 = 0 'Input Capture Interrupt disable
Timsk.toie1 = 0 'timer overflow interrupt disable
K = 4 'anzahl ungenutzter Messwerte
For J = 1 To 6 'K+J*I Meswerte
Incr K
Uti_summe(j) = Uti(k)
Next J
Gosub Sortieren
Gosub Rechnen
Return


Onoverflow:
Incr Woverflow
Return


Oncapture:
Wcapture = Capture1

Werte = Woverflow * 65536
Werte = Werte + Wcapture
Werte = Werte - Wcapturealt

Wcapturealt = Wcapture

Uti(index) = Werte
Woverflow = 0
Incr Index
If Index > 10 Then
Index = 1
Ready = 1
End If
Return



Sortieren:
K = 1
For J = 2 To 6
If Uti_summe(k) > Uti_summe(j) Then K = J 'kleinsten Wert finden
Next J
Select Case K
Case 1 : If Uti_summe(6) < Uti_summe(2) Then K = 6
Case 6 : If Uti_summe(5) < Uti_summe(1) Then K = 5
Case Else : If Uti_summe(k - 1) < Uti_summe(k + 1) Then K = K - 1
End Select
For J = 1 To 6
I = J + K
I = I - 1
If I > 6 Then I = I - 6
Uti_sort(j) = Uti_summe(i) 'sortierte Timer-Werte -> uti_sort
Next J
'Gosub Loggen
Return



Loggen:
Print Uti_sort(1) ; Spc(3) ; Uti_sort(2) ; Spc(3) ; Uti_sort(3) ; Spc(3) ; Uti_sort(4) ; Spc(3) ; Uti_sort(5) ; Spc(3) ; Uti_sort(6) '; "," ; T1_string ; "," ; T2_string
Return


Rechnen:
T1 = Ohmgrad(uti_sort(1) , Uti_sort(2) , Uti_sort(3) , Uti_sort(4) , R_ref)
T2 = Ohmgrad(uti_sort(1) , Uti_sort(2) , Uti_sort(3) , Uti_sort(5) , R_ref)
T1 = T1 * 10 : T1_word = T1 : T1_string = Str(t1_word) : T1_string = Format(t1_string , "0000")
T2 = T2 * 10 : T2_word = T2 : T2_string = Str(t2_word) : T2_string = Format(t2_string , "0000")

If Durchlauf > 20 Then
Durchlauf = 100 'Wert egal, nur größer 20
Gosub Plausibilitaet
End If
Gosub Mitteln
'Gosub Anstieg

Print T1_string ; Spc(2) ; 8_werte_mittel_t1_string ; Spc(2) ; 16_werte_mittel_t1_string ; Spc(2) ; 32_werte_mittel_t1_string ; " | ";
Print T2_string ; Spc(2) ; 8_werte_mittel_t2_string ; Spc(2) ; 16_werte_mittel_t2_string ; Spc(2) ; 32_werte_mittel_t2_string ; " | ";
Print Plaus1_string ; Spc(2) ; Plaus2_string ; " | ";
Print Anstieg_t1 '; Spc(2) ; Anstieg_t2

'Print T1_string ; 8_werte_mittel_t1_string ; 16_werte_mittel_t1_string ; 32_werte_mittel_t1_string ;
'Print T2_string ; 8_werte_mittel_t2_string ; 16_werte_mittel_t2_string ; 32_werte_mittel_t2_string ;
'Print Plaus1_string ; Plaus2_string
Return



Function Ohmgrad(t_off1 As Long , T_off2 As Long , T_ref As Long , T_x As Long , R_ref As Single) As Single
Local Zaehler As Long , Nenner As Long , Grad As Single , R As Long , T_off As Long
Local R_single As Single
T_off = T_off1 + T_off2
Zaehler = T_x - T_off :
Nenner = T_ref - T_off
R = Zaehler * R_ref
R_single = R / Nenner
Grad = R_single - R_ref
Grad = Grad * C
Grad = B - Grad
Grad = Sqr(grad)
Grad = A - Grad
Ohmgrad = Grad
End Function



Mitteln:
If Init = 0 Then 'Startwerte
For Rp_counter = 1 To 32
T1_ringpuffer(rp_counter) = T1_word
T2_ringpuffer(rp_counter) = T2_word
32_werte_mittel_t1_rp(rp_counter) = 0
'32_werte_mittel_t2_rp(rp_counter) = 0
Next Rp_counter
Init = 1
End If

Incr Rp_counter : If Rp_counter > 32 Then Rp_counter = 1 'Ringpuffer
T1_ringpuffer(rp_counter) = T1_word
T2_ringpuffer(rp_counter) = T2_word

32_werte_mittel_t1 = 0
32_werte_mittel_t2 = 0
16_werte_mittel_t1 = 0
16_werte_mittel_t2 = 0
8_werte_mittel_t1 = 0
8_werte_mittel_t2 = 0

Rp_pointer = Rp_counter
For Help_byte = 1 To 32
32_werte_mittel_t1 = 32_werte_mittel_t1 + T1_ringpuffer(rp_pointer)
32_werte_mittel_t2 = 32_werte_mittel_t2 + T2_ringpuffer(rp_pointer)
If Help_byte <= 16 Then
16_werte_mittel_t1 = 16_werte_mittel_t1 + T1_ringpuffer(rp_pointer)
16_werte_mittel_t2 = 16_werte_mittel_t2 + T2_ringpuffer(rp_pointer)
End If
If Help_byte <= 8 Then
8_werte_mittel_t1 = 8_werte_mittel_t1 + T1_ringpuffer(rp_pointer)
8_werte_mittel_t2 = 8_werte_mittel_t2 + T2_ringpuffer(rp_pointer)
End If
Rp_pointer = Rp_pointer - 1
If Rp_pointer < 1 Then Rp_pointer = 32
Next Help_byte
Shift 8_werte_mittel_t1 , Right , 3 : 8_werte_mittel_t1_string = Str(8_werte_mittel_t1) : 8_werte_mittel_t1_string = Format(8_werte_mittel_t1_string , "0000")
Shift 8_werte_mittel_t2 , Right , 3 : 8_werte_mittel_t2_string = Str(8_werte_mittel_t2) : 8_werte_mittel_t2_string = Format(8_werte_mittel_t2_string , "0000")
Shift 16_werte_mittel_t1 , Right , 4 : 16_werte_mittel_t1_string = Str(16_werte_mittel_t1) : 16_werte_mittel_t1_string = Format(16_werte_mittel_t1_string , "0000")
Shift 16_werte_mittel_t2 , Right , 4 : 16_werte_mittel_t2_string = Str(16_werte_mittel_t2) : 16_werte_mittel_t2_string = Format(16_werte_mittel_t2_string , "0000")
Shift 32_werte_mittel_t1 , Right , 5 : 32_werte_mittel_t1_string = Str(32_werte_mittel_t1) : 32_werte_mittel_t1_string = Format(32_werte_mittel_t1_string , "0000")
Shift 32_werte_mittel_t2 , Right , 5 : 32_werte_mittel_t2_string = Str(32_werte_mittel_t2) : 32_werte_mittel_t2_string = Format(32_werte_mittel_t2_string , "0000")
32_werte_mittel_t1_rp(rp_counter) = 32_werte_mittel_t1


If Rp_counter <= Delta_t Then Help_byte = Rp_counter + 32 Else Help_byte = Rp_counter
Help_byte = Help_byte - Delta_t

Anstieg_t1 = 32_werte_mittel_t1_rp(rp_counter) - 32_werte_mittel_t1_rp(help_byte)
'Anstieg_t1 = 32_werte_mittel_t2_rp(rp_counter) - 32_werte_mittel_t2_rp(help_byte)
Return



Plausibilitaet:
'Plausibilität prüfen
'mehr als doppelt so große Werte, als auch weniger als halb so kleine Werte
'werden gegen 8-Werte-Mittel ersetzt
Plaus1 = 8_werte_mittel_t1 : Shift Plaus1 , Left , 1
Plaus2 = 8_werte_mittel_t1 : Shift Plaus2 , Right , 1
If T1_word < Plaus2 Or T1_word > Plaus1 Then
Plaus1_string = Str(t1_word)
T1_word = 8_werte_mittel_t1
T1_string = Str(t1_word)
T1_string = Format(t1_string , "0000")
Else
Plaus1_string = "0000"
End If

Plaus1 = 8_werte_mittel_t2 : Shift Plaus1 , Left , 1
Plaus2 = 8_werte_mittel_t2 : Shift Plaus2 , Right , 1
If T2_word < Plaus2 Or T2_word > Plaus1 Then
Plaus2_string = Str(t2_word)
T2_word = 8_werte_mittel_t2
T2_string = Str(t2_word)
T2_string = Format(t2_string , "0000")
Else
Plaus2_string = "0000"
End If
Return

Besserwessi
15.06.2010, 19:06
Die Definition von Capture ist Problematisch, weil eine absolute Adresse für die Variable angegeben wird. Wenn es nur damit geht, spricht das dafür, dass irgendwo eine Stack überläuft, oder ein Array Index zu groß wird.

Mit dem zu großen Array und der Absoluten Adresse wird ggf. dafür gesorgt, das der Überlauf nur einen ungenutzten Bereich betrifft. Das kann dann zwar funktionieren, ist aber alles andere als sauberer Programierstiel.

BoGe-Ro
15.06.2010, 20:39
Leider ist mein Programm sehr unübersichtlich dargestellt...sorry dafür.
Weiterhin wollte auch nichts aus dem Kontext reißen und nur Fragmente anbieten.

Die Variable Capture wurde in einer vorherigen Version genutzt - da mit Overlays auf das hi-word und die unteren bytes.

in der jetzigen Lösung - gemäß dem Roland Walther - Buch lass ich den Timer durchlaufen, und nutze zur Berechnung die wCapture- und wZaehler-Variablen.

Der Teil haut prima hin - entferne ich nun aber die unbenutzte Capture-Variable auf der festen Adresse, startet mein Mikrocontroller laufend neu.
Er kommt dabei unterschiedlich weit, meißt nur bis in die Hauptschleife, vereinzelt wird sie wohl aber komplett durchlaufen, so dass ich sogar eine Ausgabe bekomme, mit abenteuerlichen (negativen, betragsmäßig falschen) Werten.


Die zweite problematische Variable ist die uti(68) (die mit dem smilie).
Ursprünglich war es ein 100er Array, in dem 100 aufeinanderfolgende Capture-Werte abgelegt wurden.
Die Mittelung der Capturewerte war dann nicht mehr notwendig, so dass ich nur noch 10 Werte aufnehme.
Nun brachte das verkleinern des Arrays wiederum genau den Effekt, dass der Controller stets neu startete.

Erst mit späterer Einführung eines weiteren Arrays (32_werte_mittel_t1_rp(32)), ließ der sich genau um die 32-Word-Werte verkleinern, die das neue Array einnahm.
nun will ich noch so einen Puffer für den zweiten Messwert anlegen, gerate damit aber über den SRAM. Ein weiteres verkleinern des unnötig grossen uti(k) fuktioniert aber auch nicht.

Besserwessi
15.06.2010, 23:07
Ich würd man Porbieren die Werte für
$swstack = 100
$hwstack = 100

noch etwas größer zu machen. Die Werte sind schon nicht so klein, aber da werden zum Teil ziehmlich viele Prameter übergegen.