drivepro82
08.11.2008, 09:36
Hallo!
Ich habe auf einem Mega16 mit dem RN-Control Board unter Bascom eine Drehzahlmessung (und Drehgradientenmessung) programmiert (s.u.). Das Programm funktioniert auch soweit. Das einzige Problem ist, dass wenn man den Reset-Taster betätigt, während eine Frequenz am Interrupt anliegt, viel zu große Werte raus kommen, und zwar immer die gleichen, bei der jeweiligen Frequenz. Das geschieht nicht, wenn man Reset betätigt während keine Frequenz anliegt. Nach dem Starten des Programms kann dann die Frequenz verändert werden, was auch richtig angezeigt wird. Teilweise tritt dieser Fehler auch einfach so auf, bei höheren Frequenzen. Und dann kommt man nicht mehr auf einen vernünftigen Wert zurück, ohne die Ferquenz auf Null zu fahren und dann Reset zu drücken.
Sollte der Controller bei einem Reset das Programm nicht von ganz vorne starten?? Wenn das so wäre müsste auch bei anliegender Frequenz ein richtiger Wert angezeigt werden, oder??
Hat jemand ne Idee, wo der Fehler liegen könnte?
Hier mein Programm:
'################################################# ##
'LVA_Drehzahlmessung.BAS
'Diese Programm ermittelt über die Signale einer Lichtschranke
'die Drehzahl am Motorenprüfstand 1 des LVA an der Fachhochschule Köln.
'Die ermittelte Drehzahl und der Drehzahlgradient werden an D/A-Wandler gegeben,
'die eine analoge Spannung ausgeben, für die Weiterverarbeitung in der folgenden
'Regelungselektronik.
'Autor: Christian Hungenberg
'################################################# ######
$regfile = "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 16000000 'Angabe der Quarzfrequenz
$baud = 9600
Config Int0 = Falling 'Der Interrupt wird bei fallendem Flankensignal aktiviert
Config Timer1 = Timer , Prescale = 256 'Timer 1 (16-bit Timer)
Config Spi = Soft , Din = Pinc.5 , Dout = Portc.1 , Ss = None , Clock = Portc.0 'Konfiguration der Software SPI
Config Portc.2 = Output 'Ausgang für CS1
Config Portc.3 = Output 'Ausgang für CS2
Portc.2 = 1 'CS1 auf High
Portc.3 = 1 'CS2 auf High
Dim Pointer As Byte 'zeigt dei aktuelle Speicherstelle für die Impulse an
Dim Array(24) As Byte '24 Speicherstellen für Impulse
Dim Impulszaehler As Long 'Zaehlt die Impulse der Lichtschranke waehrend 10ms (dies ist die Timerzeit)
Dim Impulse As Long 'in dieser Variablen werden die gezaehlten Impulse für die Berechnung gespeichert
Dim Drehzahl_alt As Single 'zur Berechnung des Gradienten speichtert diese Variable den vorangegangenen Drehzahlwert
Dim Drehzahl_neu As Single 'Drehzahl in 1/min, als Dezimalwert
Dim Umdpm1 As Byte
Dim Umdpm2 As Byte
Dim Umdrehungenprominute As Word At Umdpm1 Overlay 'enthaelt den aktuellen Drehzahlwert in 1/min, als ganzzaligen Wert fuer DAC
Dim Drehgradient As Single 'für die Berechnung des Gradienten als Dezimalwert
Dim Grad1 As Byte
Dim Grad2 As Byte
Dim Gradient As Word At Grad1 Overlay 'enthaelt den Drehzahlgradienten in U/s2, als gangzzahligen Wert fuer DAC
Dim I As Integer
Dim Syncro As Byte 'synchronisiert die Ausgabe mit der Berechnung
Pointer = 1 'Pointer zeigt auf die erste Speicherstelle
Impulszaehler = 0
Impulse = 0
Drehzahl_neu = 0
Syncro = 0
On Int0 Irq0 'bei fallenden Flanken wird der Interrupt ausgeloest und ruft Irq0 auf
Enable Int0
On Timer1 Timer_irq 'beim Ueberlaufen des Timers wird die Routine Timer_irq aufgerufen
Enable Timer1
Enable Interrupts
Do
If Syncro = 1 Then
Drehzahl_neu = Impulse * 2.5 'Berechnung der Drehzahl: Imp/(BZ*100)*60 Imp=1; BZ=0,24
Drehgradient = Drehzahl_neu - Drehzahl_alt 'Berechnung der Drehzahländerung für Gradienten
Drehgradient = Drehgradient * 10 'Gradient = Drehzahländerung * Kerwert der Zeiteinheit (1/0,01s)
Drehzahl_alt = Drehzahl_neu 'Speichern der neuen Drehzahl als alte fuer naechste Berechnung der Drehzahlaenderung
Drehzahl_neu = Drehzahl_neu * 0.4096 'Umrechnung von Drehzahl 0...10.000 auf Binaerzahl 0...4096 (10.000/4096)^-1
Umdrehungenprominute = Round(drehzahl_neu)
Portc.2 = 0 'CS1 auf LOW
Spiinit
Spiout Umdpm2 , 1 ' Bit 15 - BIT 8
Spiout Umdpm1 , 1 ' Bit 7 - BIT 0
Portc.2 = 1 'CS1 auf High
If Drehgradient > 0 Then
Drehgradient = Drehgradient * 2.048 'Umrechnung von Drehzahlgradient 0...2.000 auf Binärzahl 0...4095 (2.000/4096)^-1
Gradient = Round(drehgradient)
Else
Gradient = 0
End If
Portc.3 = 0 'CS1 auf LOW
Spiinit
Spiout Grad2 , 1 ' Bit 15 - BIT 8
Spiout Grad1 , 1 ' Bit 7 - BIT 0
Portc.3 = 1 'CS1 auf High
'Print Impulse
'Print Impulszaehler
'Print Drehzahl_neu
Syncro = 0
End If
Loop
End
Irq0: 'Pro Impuls (Markierung auf Scheibe) ein Aufruf
Incr Impulszaehler
Return
Timer_irq: 'wird beim Ablauf der Berechnungszeit aufgerufen
Impulse = Impulse + Impulszaehler 'addiert die Impulse der neuen 10ms
Impulse = Impulse - Array(pointer) 'subtrahiert die Impulse der 10ms-Zeiteiheit vor 240ms
Array(pointer) = Impulszaehler 'speichert die Impulse der aktuellen 10ms-Zeiteinheit in den aktuellen Speicherplatz
Impulszaehler = 0 'resetet den Impulszaehler
If Pointer = 24 Then 'hier wird der Pointer um den Wert "1" hoch gesetzt, nach 24 fängt er von vorne an
Pointer = 1
Else
Incr Pointer
End If
Timer1 = 64911 'laed den timer vor, dies definiert die Timerzeit
Incr Syncro 'fuer die Sychronisierung der Ausgabe mit der Berechnung
Return
Ich habe auf einem Mega16 mit dem RN-Control Board unter Bascom eine Drehzahlmessung (und Drehgradientenmessung) programmiert (s.u.). Das Programm funktioniert auch soweit. Das einzige Problem ist, dass wenn man den Reset-Taster betätigt, während eine Frequenz am Interrupt anliegt, viel zu große Werte raus kommen, und zwar immer die gleichen, bei der jeweiligen Frequenz. Das geschieht nicht, wenn man Reset betätigt während keine Frequenz anliegt. Nach dem Starten des Programms kann dann die Frequenz verändert werden, was auch richtig angezeigt wird. Teilweise tritt dieser Fehler auch einfach so auf, bei höheren Frequenzen. Und dann kommt man nicht mehr auf einen vernünftigen Wert zurück, ohne die Ferquenz auf Null zu fahren und dann Reset zu drücken.
Sollte der Controller bei einem Reset das Programm nicht von ganz vorne starten?? Wenn das so wäre müsste auch bei anliegender Frequenz ein richtiger Wert angezeigt werden, oder??
Hat jemand ne Idee, wo der Fehler liegen könnte?
Hier mein Programm:
'################################################# ##
'LVA_Drehzahlmessung.BAS
'Diese Programm ermittelt über die Signale einer Lichtschranke
'die Drehzahl am Motorenprüfstand 1 des LVA an der Fachhochschule Köln.
'Die ermittelte Drehzahl und der Drehzahlgradient werden an D/A-Wandler gegeben,
'die eine analoge Spannung ausgeben, für die Weiterverarbeitung in der folgenden
'Regelungselektronik.
'Autor: Christian Hungenberg
'################################################# ######
$regfile = "m32def.dat"
$framesize = 32
$swstack = 32
$hwstack = 32
$crystal = 16000000 'Angabe der Quarzfrequenz
$baud = 9600
Config Int0 = Falling 'Der Interrupt wird bei fallendem Flankensignal aktiviert
Config Timer1 = Timer , Prescale = 256 'Timer 1 (16-bit Timer)
Config Spi = Soft , Din = Pinc.5 , Dout = Portc.1 , Ss = None , Clock = Portc.0 'Konfiguration der Software SPI
Config Portc.2 = Output 'Ausgang für CS1
Config Portc.3 = Output 'Ausgang für CS2
Portc.2 = 1 'CS1 auf High
Portc.3 = 1 'CS2 auf High
Dim Pointer As Byte 'zeigt dei aktuelle Speicherstelle für die Impulse an
Dim Array(24) As Byte '24 Speicherstellen für Impulse
Dim Impulszaehler As Long 'Zaehlt die Impulse der Lichtschranke waehrend 10ms (dies ist die Timerzeit)
Dim Impulse As Long 'in dieser Variablen werden die gezaehlten Impulse für die Berechnung gespeichert
Dim Drehzahl_alt As Single 'zur Berechnung des Gradienten speichtert diese Variable den vorangegangenen Drehzahlwert
Dim Drehzahl_neu As Single 'Drehzahl in 1/min, als Dezimalwert
Dim Umdpm1 As Byte
Dim Umdpm2 As Byte
Dim Umdrehungenprominute As Word At Umdpm1 Overlay 'enthaelt den aktuellen Drehzahlwert in 1/min, als ganzzaligen Wert fuer DAC
Dim Drehgradient As Single 'für die Berechnung des Gradienten als Dezimalwert
Dim Grad1 As Byte
Dim Grad2 As Byte
Dim Gradient As Word At Grad1 Overlay 'enthaelt den Drehzahlgradienten in U/s2, als gangzzahligen Wert fuer DAC
Dim I As Integer
Dim Syncro As Byte 'synchronisiert die Ausgabe mit der Berechnung
Pointer = 1 'Pointer zeigt auf die erste Speicherstelle
Impulszaehler = 0
Impulse = 0
Drehzahl_neu = 0
Syncro = 0
On Int0 Irq0 'bei fallenden Flanken wird der Interrupt ausgeloest und ruft Irq0 auf
Enable Int0
On Timer1 Timer_irq 'beim Ueberlaufen des Timers wird die Routine Timer_irq aufgerufen
Enable Timer1
Enable Interrupts
Do
If Syncro = 1 Then
Drehzahl_neu = Impulse * 2.5 'Berechnung der Drehzahl: Imp/(BZ*100)*60 Imp=1; BZ=0,24
Drehgradient = Drehzahl_neu - Drehzahl_alt 'Berechnung der Drehzahländerung für Gradienten
Drehgradient = Drehgradient * 10 'Gradient = Drehzahländerung * Kerwert der Zeiteinheit (1/0,01s)
Drehzahl_alt = Drehzahl_neu 'Speichern der neuen Drehzahl als alte fuer naechste Berechnung der Drehzahlaenderung
Drehzahl_neu = Drehzahl_neu * 0.4096 'Umrechnung von Drehzahl 0...10.000 auf Binaerzahl 0...4096 (10.000/4096)^-1
Umdrehungenprominute = Round(drehzahl_neu)
Portc.2 = 0 'CS1 auf LOW
Spiinit
Spiout Umdpm2 , 1 ' Bit 15 - BIT 8
Spiout Umdpm1 , 1 ' Bit 7 - BIT 0
Portc.2 = 1 'CS1 auf High
If Drehgradient > 0 Then
Drehgradient = Drehgradient * 2.048 'Umrechnung von Drehzahlgradient 0...2.000 auf Binärzahl 0...4095 (2.000/4096)^-1
Gradient = Round(drehgradient)
Else
Gradient = 0
End If
Portc.3 = 0 'CS1 auf LOW
Spiinit
Spiout Grad2 , 1 ' Bit 15 - BIT 8
Spiout Grad1 , 1 ' Bit 7 - BIT 0
Portc.3 = 1 'CS1 auf High
'Print Impulse
'Print Impulszaehler
'Print Drehzahl_neu
Syncro = 0
End If
Loop
End
Irq0: 'Pro Impuls (Markierung auf Scheibe) ein Aufruf
Incr Impulszaehler
Return
Timer_irq: 'wird beim Ablauf der Berechnungszeit aufgerufen
Impulse = Impulse + Impulszaehler 'addiert die Impulse der neuen 10ms
Impulse = Impulse - Array(pointer) 'subtrahiert die Impulse der 10ms-Zeiteiheit vor 240ms
Array(pointer) = Impulszaehler 'speichert die Impulse der aktuellen 10ms-Zeiteinheit in den aktuellen Speicherplatz
Impulszaehler = 0 'resetet den Impulszaehler
If Pointer = 24 Then 'hier wird der Pointer um den Wert "1" hoch gesetzt, nach 24 fängt er von vorne an
Pointer = 1
Else
Incr Pointer
End If
Timer1 = 64911 'laed den timer vor, dies definiert die Timerzeit
Incr Syncro 'fuer die Sychronisierung der Ausgabe mit der Berechnung
Return