PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : Finde Fehler nicht



hunikuni
01.06.2012, 17:57
Hallo ich habe kleines Bascom Progamm geschrieben und finde den Fehler nicht. Ich habe an ein Baby Orangutanboard einen Hallsensot an Int0 angeschlossen. Nach Minute 1 fängt LED zu leuchten an und schaltet wie gewünscht nach 10 Sensorimpulsen ab. Das LED sollte aber nach Minute 2 wieder anfangen zu leuchten, aber hier liegt das Problem. Bin Anfänger und befürchte ich habe eien Denkfehler. Ausserden ist die Timereistellung auch noch nicht richt , eine Minute dauert mit dieser Einstellung nur ca 30 sec. Aber das ist nicht so wild :confused::confused:



'Bascom Hallsensor test

$regfile = "m328pdef.dat"
$crystal = 20000000 'Quarzfrequenz
$hwstack = 32
$framesize = 64
$swstack = 32



Config Pind.1 = Output



'Timer und der Teiler festlegen 10ms
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer_irq
Const Timervorgabe = 175
Config Int0 = Rising
Enable Int0




Enable Interrupts

Dim Hallimpuls As Integer
Dim Cnt As Byte
Dim Sekunde As Byte
Dim Minute As Byte
Dim Stunde As Byte
Dim Sekunde_last As Byte


Hallimpuls = 0
Stunde = 0
Minute = 0
Sekunde = 0
Enable Timer0



Do




' 1. Minute
If Stunde = 0 And Minute = 1 Then Gosub Led
' 2. Minute
If Stunde = 0 And Minute = 3 Then Gosub Led



Loop



Led:
Hallimpuls = 0
On Int0 Zaehlen
If Hallimpuls = 0 Then
Toggle Portd.1

Do

Idle
Loop Until Hallimpuls = 10
Else

Reset Portd.1
End If
Return





Zaehlen:

Incr Hallimpuls

Return


Timer_irq:
Timer0 = Timervorgabe

Incr Cnt

If Cnt = 50 Then
Portb.6 = 0
End If

If Cnt = 100 Then
Portb.6 = 1

Sekunde = Sekunde + 1
If Sekunde = 60 Then
Sekunde = 0
Minute = Minute + 1
If Minute = 60 Then
Minute = 0
Stunde = Stunde + 1
If Stunde = 24 Then
Stunde = 0
End If
End If
End If
Cnt = 0
End If
Return

Ich hoffe jemand kann mir helfen !!!

Tido
01.06.2012, 18:41
' 1. Minute
If Stunde = 0 And Minute = 1 Then Gosub Led
' 2. Minute
If Stunde = 0 And Minute = 3 Then Gosub Led





Minute = 3 ???

Punkt 2: Ersetz mal:

If Cnt = 100 Then durch If Cnt = 200 Then

hunikuni
01.06.2012, 19:19
Danke für die schnelle Antwort !! cnt auf 200 funktioniert gut. Aber mein Hauptproblem, daß das Led nach 2 Minuten nicht wieder das Leuchten beginnt besteht weiter. !!!

Tido
01.06.2012, 19:29
Du schreibst ja auch if minute = 3 und nicht if minute= 2...

hunikuni
01.06.2012, 19:33
Hab ich auch auf 2 geändert, fängt aber weder nach 2 noch nach 3 Minuten an zu leuchten.

Tido
01.06.2012, 19:42
Das liegt daran, dass dein Programm in der 2. Do-Loop-Schleife hängt.

Erklärung folgt:

Nach deinen 10 Impulsen wird die Sub LED verlassen. Da deine Bedingung "if stunde=0 and minute=1" im nächsten Programmdurchlauf wieder war ist, springt er wieder zu LED.
Dort macht er dir mit "toggle LED" die LED aus und wartet auf 10 Impulse (die die ihm nicht gibst, da du auf minute=2 wartest).

Tido
01.06.2012, 19:58
Versuch mal:


'Bascom Hallsensor test

$regfile = "m328pdef.dat"
$crystal = 20000000 'Quarzfrequenz
$hwstack = 32
$framesize = 64
$swstack = 32



Config Pind.1 = Output



'Timer und der Teiler festlegen 10ms
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer_irq
Const Timervorgabe = 175
Config Int0 = Rising
Enable Int0




Enable Interrupts

Dim Hallimpuls As Integer
Dim Cnt As Byte
Dim Sekunde As Byte
Dim Minute As Byte
Dim Stunde As Byte
Dim Sekunde_last As Byte
Dim Minute_last as Byte


Hallimpuls = 0
Stunde = 0
Minute = 0
Sekunde = 0
Enable Timer0



Do




If Stunde = 0 And Minute <> Minute_last Then Gosub Led



Loop



Led:
Hallimpuls = 0
Portd.1 = 1'LED an
On Int0 Zaehlen


Do

Idle
Loop Until Hallimpuls = 10
Portd.1 = 0'LED aus
minute_last = minute
Return





Zaehlen:

Incr Hallimpuls

Return


Timer_irq:
Timer0 = Timervorgabe

Incr Cnt

If Cnt = 50 Then
Portb.6 = 0
End If

If Cnt = 100 Then
Portb.6 = 1

Sekunde = Sekunde + 1
If Sekunde = 60 Then
Sekunde = 0
Minute = Minute + 1
If Minute = 60 Then
Minute = 0
Stunde = Stunde + 1
If Stunde = 24 Then
Stunde = 0
End If
End If
End If
Cnt = 0
End If
Return


Löst zwar wahrscheinlich dein Problem, hat aber weitere Fallstricke.

hunikuni
01.06.2012, 20:58
Danke werd ich morgen ausprobieren. Wollte aber am ende der Entwicklung Motoren zu einer bestimmten Zeit (z.B 1h23m)einschalten und nach einer Bestimmten Anzahl an Umdrehungen ( z.B. 20) wieder ausschalten, nach einer bestimmten Zeit ( z.B. 3h56) wieder einschalten und nach 20 Umdrehungen wieder ausschalten usw...

Tido
01.06.2012, 21:27
Dann setz dir in der Sub ne Variable auf 1 und lösche sie in der irq wieder, wenn sich die minute ändert. Und den "gosub" führst du nur aus wenn variable=0. So ist sichergestellt, dass die sub nur einmal pro minute aufgerufen wird.

hunikuni
02.06.2012, 20:51
Hallo danke für die Hilfe hat leider nicht den gewünschten Erflog gebracht !!

Sauerbruch
02.06.2012, 22:52
Ich weiß zwar nicht ob darin das Problem liegt, aber in diesem Teils des Codes fallen zwei Dinge auf:



Led: Hallimpuls = 0 On Int0 Zaehlen If Hallimpuls = 0 Then Toggle Portd.1

1. Wenn Du in der ersten Zeile die Variable Hallimpuls auf 0 setzt, brauchst D zwei Zeilen später nicht abzufragen, ob sie auch tatsächlich 0 ist :-)
(das ist aber nur ein "Schönheitsfehler" und dürfte keine Fehlfunktionen nach sich ziehen)

2. Das Statement "On Int0 Zaehlen" sollte vor die Hauptschleife, denn es muss nur ein einziges mal deklariert werden, welche ISR beim entsprechenden Interrupt ausgeführt werden soll.
Wenn Du damit erreichen wolltest dass der Interrupt0 als solches aktiviert werden soll, wäre "Enable Int0" der richtige Befehl. Erst nach dieser Anweisung ist der Interrupt "scharf".

Außerdem sehe ich das gleiche Problem wie Tido: Das Unterprogramm LED wird nach jeweils 10 Hallsensor-Impulsen gleich wieder aufs neue ausgeführt, weil die Bedingung "Stunde = 0 und Minute = 1 (bzw. 3) ja weiterhin erfüllt ist.

hunikuni
03.06.2012, 08:05
Dank für die Antwort.

Außerdem sehe ich das gleiche Problem wie Tido: Das Unterprogramm LED wird nach jeweils 10 Hallsensor-Impulsen gleich wieder aufs neue ausgeführt, weil die Bedingung "Stunde = 0 und Minute = 1 (bzw. 3) ja weiterhin erfüllt ist

Ich dachte Timer läuft weiter und Bedingung Stunde = 0 Minute =1 bzw 3 ist nur einmal erfüllt ist.

Sauerbruch
03.06.2012, 09:01
Natürlich ist die Bedingung nur "einmal" erfüllt -aber das für eine ganze Minute lang! Und während dieser Zeit wird die Hautschleife schätzungsweise ein paar Millionen male durchlaufen, und jedes mal wird das Unterprogramm ausgeführt!

Und der Timer läuft sowieso weiter...

hunikuni
03.06.2012, 09:16
Danke, aber dann müsste das Led sofort wieder anfangen zu leuchten und nicht aus bleiben ??? Habe ja das Problem dass es ausgeht und nach der definierten Zeit ( hier 3. Minute )nicht wieder an geht !! Oder habe ich einen Denkfehler ??? Werde wahrscheinlich umdrehungsabhängige Motorenabschaltung aufgeben und zeitgesteuterte verwenden.

Sauerbruch
03.06.2012, 09:25
Werde wahrscheinlich umdrehungsabhängige Motorenabschaltung aufgeben

Das wäre aber schade, denn (fast) jede Aufgabe lässt sich in Bascom realisieren!

Vielleicht beschreibst Du nochmal etwas genauer, was denn genau passieren soll? Bislang ist zwar von einem Motor, dann aber wieder von an- und ausgehenden LEDs die Rede - und die Bedeutung der 1 und 2 Minuten (die manchmal ja auch 3 sein können) erschließt sich auch noch nicht so ganz...

hunikuni
03.06.2012, 10:08
Ich will einen Uhrenbeweger steuern. D.h. Die Uhren brauchen eine bestimmte Anzahl an Umdrehungen z.B 650/ Tag in ca. 6 Drehperioden zeitlich unregelmässig aufgeteilt über den Tag. Z.B. Stunde 00 Minute 1 - Motor starten 108 Umdrehungen Motor aus. Dann z.B. Stunde = 3 Minute = 0 Motor an 108 Umdrehungen Motor aus . Stunde = 4 Minute = 8 ........ Danke für Deine Mühe !!!

hunikuni
03.06.2012, 10:15
Ausserdem sollte er auch noch die Drehrichtung Nach jeder Periode, als Periode 1 108* links . Periode 2 108* rechts usw. Wahrscheinlich für einen Anfänger wie mich zu komplex. Wollte zweite sub mit anderer Drehrichtung schreiben.

MagicWSmoke
03.06.2012, 10:50
Danke, aber dann müsste das Led sofort wieder anfangen zu leuchten und nicht aus bleiben ???
Das gezeigte Verhalten rührt daher, da die LED nicht über Reset im Else-Zweig ausgeschaltet wird, sondern über Toggle, da nach 10 Impulsen die Sub verlassen, aber sofort erneut angesprungen wird. Bei diesem zweiten Mal wird also die LED ausgeschaltet. Da aber wahrscheinlich dann keine Hallimpulse mehr kommen, hängt es von da an in der Do/Loop und kann natürlich auch nicht auf die dritte Minute reagieren. Du kannst das überprüfen, indem Du nach Ablauf der ersten Minute genügend Hallimpulse erzeugst, damit die Loop verlassen wird. Danach wirst Du sehen, dass die LED bei Minute 3 angeht. Der Fehler wäre Dir einfacher klar geworden, wenn Du statt Toggle ein Set verwendet hättest.

hunikuni
03.06.2012, 13:12
Danke für eure Mithilfe. Ich Glaube jetzt funktionietrs. Habe folgende Ergänzungen und Umstellungen vogenommen:


'Bascom Hallsensor test

$regfile = "m328pdef.dat"
$crystal = 20000000 'Quarzfrequenz
$hwstack = 32
$framesize = 64
$swstack = 32


On Int0 Zaehlen
Config Pind.1 = Output



'Timer und der Teiler festlegen 10ms
Config Timer0 = Timer , Prescale = 1024
On Timer0 Timer_irq
Const Timervorgabe = 175
Config Int0 = Rising
Enable Int0




Enable Interrupts

Dim Hallimpuls As Integer
Dim Cnt As Byte
Dim Sekunde As Byte
Dim Minute As Byte
Dim Stunde As Byte
Dim Sekunde_last As Byte


Hallimpuls = 0
Stunde = 0
Minute = 0
Sekunde = 0
Enable Timer0



Do




' 1. Minute
If Stunde = 0 And Minute = 1 And Sekunde = 0 Then Gosub Led
' 2. Minute
If Stunde = 0 And Minute = 3 And Sekunde = 1 Then Gosub Led



Loop



Led:
Hallimpuls = 0

If Hallimpuls = 0 Then
Portd.1 = 1

Do

Idle
Loop Until Hallimpuls = 10
Else

Portd.1 = 0
End If
Return





Zaehlen:

Incr Hallimpuls

Return


Timer_irq:
Timer0 = Timervorgabe

Incr Cnt

If Cnt = 50 Then
Portb.6 = 0
End If

If Cnt = 100 Then
Portb.6 = 1

Sekunde = Sekunde + 1
If Sekunde = 60 Then
Sekunde = 0
Minute = Minute + 1
If Minute = 60 Then
Minute = 0
Stunde = Stunde + 1
If Stunde = 24 Then
Stunde = 0
End If
End If
End If
Cnt = 0
End If
Return



Dank eurer Tips scheint es zu funktionieren !!:p:p:p:p:p:p

Sauerbruch
03.06.2012, 13:26
Na siehst Du - es geht doch :-)

Neben dem Toggeln war der Knackpunkt vermutlich, dass die Subroutine "LED" immer wieder auf´s neue ausgeführt wurde, so lange die aktuelle Minute noch nicht rum war - das hast Du jetzt scheinbar dadurch gelöst, dass Du die Zeit sekundengenau abfragst (und die 10 Hallimpulse anscheinend länger als 1 Sekunde brauchen).

Grundsätzlich (und Zeit-unabhängiger!) kann man so ein Problem auch mit einem "Flag" lösen, wie es Tido schon angedeutet hat:
Ein Flag ist ein einzelnes Bit, mit dem man sich bestimmte Zustände sozusagen "merken" kann. In diesem Beispiel etwa so:

Immer wenn eine neue Minute beginnt, setzt Du das Flag in der entsprechenden ISR auf 1 (also hinter dem Befehl Minute = Minute + 1).
Die Abfrage machst Du dann so: If Stunde = XX AND Minute = YY AND Flag = 1 then...
Am Ende der LED-Subroutine setzt Du dann das Flag wieder auf 0 - damit ist sie dann gesperrt, bis der nächste Minutensprung stattgefunden hat.

Aber Hauptsache es funktioniert erstmal - der Spaß am Optimieren kommt schon noch ganz von alleine :-)

MagicWSmoke
03.06.2012, 13:54
Ich Glaube jetzt funktionietrs.
Also wenn Du noch anderen Code hast, der mag dann funktionieren, der Gezeigte dürfte das nicht.

Hallimpuls = 0

If Hallimpuls = 0 Then
folgt ein paar Takte aufeinander und somit wird der Else-Zweig

Else
Portd.1 = 0
unter normalen Umständen nie durchlaufen und damit wird die Led auch nicht ausgeschaltet.
Es gibt nur eine einzige Ausnahme, nämlich wenn der Int0 genau nach

Hallimpuls = 0
triggert und das dürfte eher nicht der Fall sein, die Wahrscheinlichkeit dafür beträgt eins zu mehreren Millionen.
So in etwa wär's besser:

Led:
Disable Int0 ' wird im restlichen Code Int0 nicht erlaubt, so kann dieser Befehl entfallen
EIFR = Bits(INTF0) ' löscht anstehende Interrupts
Hallimpuls = 0
Portd.1 = 1
Do
Enable Int0
Idle
Disable Int0
Loop Until Hallimpuls = 10
Portd.1 = 0
Return
Der Zugriff auf eine Variable größer 8 Bit muss gekapselt werden, sobald ein Interrupt sie verändern kann.
Einen Fehler daraus würdest Du allerdings bei den gezeigten kleinen Werten nicht bemerken.
Warum benötigst Du ein Idle ? Batteriebetrieb ?