Hallo,
ich hab mir vor fast 20 Jahren ein Messgerät gebaut, mit dem ich Treppen und ähnliches aufmesse.
Da ist unter anderem ein kleines Modul mit einem Mega16 drin, mit dem ich mittels
eines Encoderschaltkreises (HCTL2020) messe, wie lang ein dünnes Edelstahlseil ausgezogen
ist.
Sehr selten gab es das Problem, das ein sogenannter Unterlauf aufgetreten ist, oder wie nennt
man das Gegenteil vom Überlauf?
Ich hatte mal vor Jahren das Überlaufproblem beseitigt, da es in ganz seltenem Extremfällen
passiert ist, das der 16Bit Zähler des HCTL2020 übergelaufen ist (Zeile 69-72). das habe ich
aber nur mangelhaft programmiert, denn dadurch trat das Unterlaufproblem auf.
Immer dann, wenn sich nach dem Einschalten durch eventuelle mechanische Erschütterungen
die Seiltrommel sich mal gurz um einen winzigen Betrag rückwärts gedreht hatte.
In Zeile 71 müßte der Wert also nicht 0 sondern -32768 sein.
Das Programm ist nicht schön, aber eben auch uralt, seht es mir nach. Diese Unterlaufgeschichte
trat in den vielen Jahren vielleicht 5 Mal auf.
Nun wollte ich das Problem doch beseitigen, denn manchmal fahre ich lange Strecken um mal was aufzumessen
und dann wäre es doch ärgerlich. Außerdem ändere ich sowieso noch eine andere Sache am Gerät.
Das neue Programm habe ich ausgiebig im Simulator getestet und da läuft es eigentlich. Was mir
aufgefallen ist, ich hab ausversehen zweimal den Befehl End eingefügt und außer den notwendigen Änderungen
Enable Interrupts zu den Initialisierungen verschoben.
Das Pogramm wartet, bis der Befehl "1" über die serielle Schnittstelle kommt und sender dann
einen Analogwert (Biegebalken mit Dehnungsmeßstreifen) und den Zählerwert.
Das man das besser mit einem Interrupt lösen kann, ist mit bewußt. ja und Gosub nimmt man auch nicht.
Ich würde jetzt erst mal Einiges ausprobieren aber das ist aufwendig. Ich komm da mechanisch schlecht ran,
und dachte, vielleicht fällt jemand der Fehler sofort ins Auge. Es scheint so, als wenn das Programm
gar nichts, oder null sendet.
Fällt da jemand, außer den Schönheitsfehlern was auf?
Danke!
Gruß Ralf
Originalprogramm:
Alles anzeigen
Meine Verschlimmbesserung:
Alles anzeigen
ich hab mir vor fast 20 Jahren ein Messgerät gebaut, mit dem ich Treppen und ähnliches aufmesse.
Da ist unter anderem ein kleines Modul mit einem Mega16 drin, mit dem ich mittels
eines Encoderschaltkreises (HCTL2020) messe, wie lang ein dünnes Edelstahlseil ausgezogen
ist.
Sehr selten gab es das Problem, das ein sogenannter Unterlauf aufgetreten ist, oder wie nennt
man das Gegenteil vom Überlauf?
Ich hatte mal vor Jahren das Überlaufproblem beseitigt, da es in ganz seltenem Extremfällen
passiert ist, das der 16Bit Zähler des HCTL2020 übergelaufen ist (Zeile 69-72). das habe ich
aber nur mangelhaft programmiert, denn dadurch trat das Unterlaufproblem auf.
Immer dann, wenn sich nach dem Einschalten durch eventuelle mechanische Erschütterungen
die Seiltrommel sich mal gurz um einen winzigen Betrag rückwärts gedreht hatte.
In Zeile 71 müßte der Wert also nicht 0 sondern -32768 sein.
Das Programm ist nicht schön, aber eben auch uralt, seht es mir nach. Diese Unterlaufgeschichte
trat in den vielen Jahren vielleicht 5 Mal auf.
Nun wollte ich das Problem doch beseitigen, denn manchmal fahre ich lange Strecken um mal was aufzumessen
und dann wäre es doch ärgerlich. Außerdem ändere ich sowieso noch eine andere Sache am Gerät.
Das neue Programm habe ich ausgiebig im Simulator getestet und da läuft es eigentlich. Was mir
aufgefallen ist, ich hab ausversehen zweimal den Befehl End eingefügt und außer den notwendigen Änderungen
Enable Interrupts zu den Initialisierungen verschoben.
Das Pogramm wartet, bis der Befehl "1" über die serielle Schnittstelle kommt und sender dann
einen Analogwert (Biegebalken mit Dehnungsmeßstreifen) und den Zählerwert.
Das man das besser mit einem Interrupt lösen kann, ist mit bewußt. ja und Gosub nimmt man auch nicht.
Ich würde jetzt erst mal Einiges ausprobieren aber das ist aufwendig. Ich komm da mechanisch schlecht ran,
und dachte, vielleicht fällt jemand der Fehler sofort ins Auge. Es scheint so, als wenn das Programm
gar nichts, oder null sendet.
Fällt da jemand, außer den Schönheitsfehlern was auf?
Danke!
Gruß Ralf
Originalprogramm:
BASCOM-Quellcode
- $regfile = "m16def.dat" 'Definituonsdatei für Mega16
- $crystal = 16000000 'Quarz: 16 MHz
- $baud = 38400 'Baudrate der UART: 9600 Baud
- Dim Variable As Word
- Dim Lwert As Byte
- Dim Hwert As Byte
- Dim Encoders As Word
- Dim Ueberl As Word
- Dim I As Byte
- Config Portc = Input
- Config Portd.2 = Input 'U/D HCTL
- Config Portd.4 = Output 'Shutdown Pin RS232
- Config Portd.5 = Output 'Reset Pin HCTL2020
- Config Portd.6 = Output 'O/E Pin HCTL2020
- Config Portd.7 = Output 'SEL Pin HCTL2020
- Portd.2 = 1
- Reset Portd.4 'Sender hochohmig
- Set Portd.5 'Pin auf High
- Set Portd.6
- Set Portd.7
- Waitms 10 'Reset HCTL2020
- Reset Portd.5
- Waitms 10
- Set Portd.5
- Waitms 10
- Ueberl = 0
- On Int1 Ueberlauf
- Enable Int1
- Config Int1 = Rising
- Config Adc = Single , Prescaler = 128 , Reference = Internal
- Start Adc 'ADC starten
- Do 'Endlosschleife
- If Usr.rxc = 1 Then 'Wenn Byte empfangen...
- I = Udr 'Byte aus UART auslesen
- If I = "1" Then 'Wenn Kennung stimmt...
- Gosub Senden 'Daten senden
- End If
- End If
- Loop
- End
- Senden:
- Enable Interrupts
- Reset Portd.6 'Output Enable
- Reset Portd.7 'SEL auf Low
- Waitms 1
- Hwert = Pinc 'höherwertiges Byte einlesen
- Set Portd.7 'SEL umschalten
- Waitms 1
- Lwert = Pinc 'niederwertiges Byte einlesen
- Waitms 1
- Set Portd.6 'O/E deaktivieren
- Encoders = Hwert * 256 'Werte zusammensetzen
- Encoders = Encoders + Lwert
- Encoders = Encoders / 2
- Encoders = Encoders + Ueberl
- Variable = Getadc(0) 'AD Wandler auslesen
- Set Portd.4 'RS232 aktivieren
- Waitms 1
- Printbin Encoders ; Variable 'Werte ausgeben
- Waitms 100
- Reset Portd.4 'Sender abschalten
- Return
- Ueberlauf:
- If Pind.2 = 1 Then Ueberl = 32768
- If Pind.2 = 0 Then Ueberl = 0
- Return
Meine Verschlimmbesserung:
BASCOM-Quellcode
- $regfile = "m16def.dat" 'Definituonsdatei für Mega16
- $crystal = 16000000 'Quarz: 16 MHz
- $baud = 38400 'Baudrate der UART: 9600 Baud
- Dim Variable As Word
- Dim Lwert As Byte
- Dim Hwert As Byte
- Dim Encoders As Word
- Dim Ueberl As Long , Ueberl_temp As Long
- Dim I As Byte
- Config Portc = Input
- Config Portd.2 = Input 'U/D HCTL
- Config Portd.4 = Output 'Shutdown Pin RS232
- Config Portd.5 = Output 'Reset Pin HCTL2020
- Config Portd.6 = Output 'O/E Pin HCTL2020
- Config Portd.7 = Output 'SEL Pin HCTL2020
- Portd.2 = 1 'Pullup= EIN
- Reset Portd.4 'Sender hochohmig
- Set Portd.5 'Pin auf High
- Set Portd.6
- Set Portd.7
- Waitms 10 'Reset HCTL2020
- Reset Portd.5
- Waitms 10
- Set Portd.5
- Waitms 10
- Ueberl = 0
- On Int1 Ueberlauf
- Config Int1 = Rising
- Enable Int1
- Enable Interrupts
- Config Adc = Single , Prescaler = 128 , Reference = Internal
- Start Adc 'ADC starten
- Do 'Endlosschleife
- If Usr.rxc = 1 Then 'Wenn Byte empfangen...
- I = Udr 'Byte aus UART auslesen
- If I = "1" Then 'Wenn Kennung stimmt...
- Gosub Senden 'Daten senden
- End If
- End If
- Loop
- End
- Senden:
- Reset Portd.6 'Output Enable
- Reset Portd.7 'SEL auf Low
- Waitms 1
- Hwert = Pinc 'höherwertiges Byte einlesen
- Set Portd.7 'SEL umschalten
- Waitms 1
- Lwert = Pinc 'niederwertiges Byte einlesen
- Waitms 1
- Set Portd.6 'O/E deaktivieren
- Encoders = Hwert * 256 'Werte zusammensetzen
- Encoders = Encoders + Lwert
- Ueberl_temp = Ueberl + Encoders 'Überlauf bzw. unterlauf addieren
- Ueberl_temp = Ueberl_temp / 2 'halbieren (Wertebereich Wordvariable)
- If Ueberl_temp > 65535 Then Ueberl_temp = 65535 'sicherheitshalber Wertebereich begrenzen
- If Ueberl_temp < 0 Then Ueberl_temp = 0
- Encoders = Ueberl_temp 'halbieren (Wertebereich Wordvariable)
- Variable = Getadc(0) 'AD Wandler auslesen
- Set Portd.4 'RS232 aktivieren
- Waitms 1
- Printbin Encoders ; Variable 'Werte ausgeben
- Waitms 100
- Reset Portd.4 'Sender abschalten
- Return
- Ueberlauf:
- If Pind.2 = 1 Then 'Überlauf
- Ueberl = Ueberl + 65536
- Else 'Unterlauf
- Ueberl = Ueberl - 65536
- End If
- Return
- End