PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : timer0 hört auf zu zählen...



Grillmeister Markus
27.12.2005, 17:21
Hallo allerseits,
ich hab ein kleines problemchen mit meinem code. mein robby hat vorne 3 taster un soll bei kollision erst ein stück zurückfahren, sich dann um ca. 90 grad (bei kollision am mittleren taster etwas mehr) drehen und dann weiterfahren. Dass das drücken eines anderen tasters bei dem ausweichvorgang auch wahrgenommen werden kann, hab ich versucht, das ganze mit timer0 zu ralisieren, was auch eigentlich ganz gut funktioniert.
Jetzt aber zum problem: es kommt von zeit zu zeit vor, dass sich der controller einfach "neu startet" also wieder von ganz am anfang anfängt. das kann allerdings nicht an den timern liegen, da ich dieses problem auch schon mit einem anderen code hatte. und ein neues problem ist dazugekommen: es kommt vor, dass der timer auf einmal aufhört zu zählen (an unterschiedlichen werten vom zaehler).Beide motoren drehen sich dann endlos rückwärts, bis man den strom aus und wieder einschaltet. könnte es enventuell daran liegen, dass ich keine diode vor den relais habe, die den motor schalten? oder liegts an was ganz anderem?
mfg Markus



$regfile = "2313def.dat"
$crystal = 3686400
$baud = 9600

Dim Zaehler As Byte

Ddrd.2 = 1 'motor links vorwärts
Ddrd.3 = 1 'motor links rückwärts
Ddrd.4 = 1 'motor rechts vorwärts
Ddrd.5 = 1 'motor rechts rückwärts
Ddrb.0 = 0 'taster links vorne
Ddrb.1 = 0 'taster mitte vorne
Ddrb.2 = 0 'taster rechts vorne
Portb.0 = 1
Portb.1 = 1
Portb.2 = 1

Mlinksvor Alias Portd.2
Mlinksrueck Alias Portd.3
Mrechtsvor Alias Portd.4
Mrechtsrueck Alias Portd.5

Schalterlinks Alias Pinb.0
Schaltermitte Alias Pinb.1
Schalterrechts Alias Pinb.2

Config Timer0 = Timer , Prescale = 1024
Enable Timer0
Start Timer0
Enable Interrupts
On Timer0 Ontimer


Main:
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 1
Mrechtsrueck = 0
If Schalterlinks = 0 Then
Zaehler = 0
Gosub Links
End If
If Schaltermitte = 0 Then
Zaehler = 0
Gosub Mitte
End If
If Schalterrechts = 0 Then
Zaehler = 0
Gosub Rechts
End If
Goto Main

Links:

If Schaltermitte = 0 Then
Zaehler = 0
Gosub Mitte
End If
If Schalterrechts = 0 Then
Zaehler = 0
Gosub Rechts
End If

If Zaehler < 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler > 33 Or Zaehler = 33 Then
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 83 Then
Gosub Main
End If
Goto Links

Mitte:

If Schalterlinks = 0 Then
Zaehler = 0
Gosub Links
End If
If Schalterrechts = 0 Then
Zaehler = 0
Gosub Rechts
End If

If Zaehler < 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler > 33 Or Zaehler = 33 Then
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 101 Then
Gosub Main
End If
Goto Mitte

Rechts:

If Schalterlinks = 0 Then
Zaehler = 0
Gosub Links
End If
If Schaltermitte = 0 Then
Zaehler = 0
Gosub Mitte
End If

If Zaehler < 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler > 33 Or Zaehler = 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 1
Mrechtsrueck = 0
End If
If Zaehler = 83 Then
Gosub Main
End If
Goto Rechts

Ontimer:
Incr Zaehler
Print Zaehler
Return

PicNick
27.12.2005, 17:42
Bitte, Kollege, du mußt deine "GOTO" und "GOSUB" kreuz und quer ein wenig zusammenräumen, bevor das noch wer sieht und tot umfällt.

Bei dir kommt vor:
Main:
....
Gosub Links
..
Innerhalb von "Links" steht u.A.
...
If Zaehler = 83 Then
Gosub Main
End If
Goto Links

Irgendwann haut der COntroller den Stack weg und fängt von vorne wieder an, is ja auch nur ein Mensch

Grillmeister Markus
27.12.2005, 18:35
so...ich hab jetzt alle "gosub" durch "goto" ersetzt und jetzt scheint es stabiel zu laufen (auch wenn mir der unterschied zwischen den beiden nicht klar ist...werd wohl nochmal googlen).
wenn der controller allerdings, wie du gesagt hast, von vorne wieder anfängt, dann sollte doch der timer trotzdem wieder laufen oder?
mfg Markus

Torsten_G
27.12.2005, 21:52
Hallo Markus

Bei "Gosub" erwartet der Controller irgendwann ein "Return" - also speichert er die Rücksprungadresse.
Da kannst Du Dir jetzt leicht ausrechnen, was bei verschachtelten Gosubs passiert...

Anders bei "Goto" - da hüpft er hin und hat fertig!

Eine gute und elegante Möglichkeit für Auswahlabfragen bietet auch der "Case"-Befehl. Ist auch wesentlich übersichtlicher als verschachtelte Goto´s und Gosub´s!

Viele Grüße

Torsten

Guy
28.12.2005, 14:46
Das ist ein typisches Beispiel für das was wir Früher Spaghettiprogramme genannt haben. Und durch solch ein Programmierstiel ist schon so mancher Rechner abgestürzt.

Vorsichtshalber kann man einen WATCHDOG einbauen. Bei deinem Programm würde der auf jeden Fall nicht arbeitslos.

Du hast das Problem jetzt gelöst in dem du GOTOs benutzt. Aber in Wirklichkeit ist das keine Lösung, besser währe es, du würdest dich mal mit strukturierter Programmierung beschäftigen. Dann braust nur noch GOSUBs. Vielleicht in seltenen Fällen noch ein GOTO.

Sicher wirst du dich jetzt fragen warum soll ich den GOSUB benutzten, wenn es mit GOTO doch besser klappt.

Die Anwort ist sehr einfach. In einem etwas größerem Programm wirst du dich mit vielen GOTOs nach einer Zeit selber nicht mehr zurecht finden wenn du da mal einen Änderung machen mußt, ganz davon zu schweigen wenn ein andrer da einen Änderung machen soll.

Meinem Rat, gewöhne dir einen sauberen Programmierstiel an, sonst wirst du noch eines Tages an deinem eigenen Programm verzweifeln.

MFG
Guy

Grillmeister Markus
28.12.2005, 16:03
Hallo Guy.
Auch wenn die sache mit GOTO angeblich ein unsaubererprogrammierstiel ist, so erscheint es mir doch deutlich einfacher und überlichtlicher. Bei GOSUBs braucht man ja, wie Torsten_G oben geschrieben hat, irgendwann einen RETURN befehl, was bei GOTO wegfällt. So kann es doch bei einem größeren programm (mit mehreren Subs) durch den GOSUB befehl leichter zu komplikationen kommen.
Da ich mich aber natürlich trotzdem um einen sauberen programmierstiel bemühen will, wäre es nett, wenn jemand eine seite wüsste, wo ein paar tipps zum sauberen programmieren zusammengefasst sind.
mfg Markus

Guy
29.12.2005, 10:27
Auch wenn die sache mit GOTO angeblich ein unsaubererprogrammierstiel ist, so erscheint es mir doch deutlich einfacher und überlichtlicher.
Hallo

Einfacher schon, aber nicht übersichtlicher. Und einfacher auch nur bei sehr kleinen Programme und weil du den Stack nicht überflutest.

Du hast zum Beispiel einen (On Timer0 Ontimer) in deinem Programme, wenn du jetzt in der Ontimer Routine einen GOTO rein setzt wirst du wieder einen Stacküberlauf haben, weil bei einem Interrupt Automatisch die Rücksprungadresse auf den Stack abgelegt wird, und sie so nie gelöscht wird.

Im Grund ist es so. du sollst ein Hauptprogramm haben was in einer Schleife läuft, in dem Hauptprogramme reagierst du auf verschiedene Ereignisse wie zum Beispiel Tassendruck, dann rufst eine Unterroutine auf die diese Arbeit erledigt dann springst du wieder in die Hauptroutine zurück. So das dein Programm aus einem Mainprogramm besteht, und viele kleinen Unterprogramme.

Du kannst auch aus einem Unterprogramm ein andres Unterprogramm aufrufen, aber immer wieder dahin zurück springen wo du herkommst.

Was du auch vermeiden sollst ist, aus einem aufgerufenen Unterprogramm das aufrufende Unterprogramm aufrufen. Weil du dich dann in eine Endlosschleife begeben kannst die nie endet.

So kannst du dein Programm Ablauf sehr einfach verfolgen und schnell Fehler entdecken. Mit GOTO Ist das nicht so einfach. Wenn du zum Beispiel eine Variable hast die an einer bestimmten Stelle einen falschen Wehrt hat, und du dann feststellen sollst wo der her kommt ist das nicht mehr so einfach, weil du eben hin und her springst.

Ich habe dir mal dein Programm so umgeändert wie es aussehen sollte. Du kannst es nicht so einsetzen, es soll lediglich das Prinzip verdeutlichen.




$regfile = "2313def.dat"
$crystal = 3686400
$baud = 9600

Dim Zaehler As Byte

Ddrd.2 = 1 'motor links vorwärts
Ddrd.3 = 1 'motor links rückwärts
Ddrd.4 = 1 'motor rechts vorwärts
Ddrd.5 = 1 'motor rechts rückwärts
Ddrb.0 = 0 'taster links vorne
Ddrb.1 = 0 'taster mitte vorne
Ddrb.2 = 0 'taster rechts vorne
Portb.0 = 1
Portb.1 = 1
Portb.2 = 1

Mlinksvor Alias Portd.2
Mlinksrueck Alias Portd.3
Mrechtsvor Alias Portd.4
Mrechtsrueck Alias Portd.5

Schalterlinks Alias Pinb.0
Schaltermitte Alias Pinb.1
Schalterrechts Alias Pinb.2

Config Timer0 = Timer , Prescale = 1024
Enable Timer0
Start Timer0
Enable Interrupts
On Timer0 Ontimer

''Main:

Do
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 1
Mrechtsrueck = 0
If Schalterlinks = 0 Then
Zaehler = 0
Gosub Links
End If
If Schaltermitte = 0 Then
Zaehler = 0
Gosub Mitte
End If
If Schalterrechts = 0 Then
Zaehler = 0
Gosub Rechts
End If
Loop

Links:
Do
If Zaehler => 33 Then
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If

If Zaehler = 83 Then
Return
End If
Loop

Mitte:
Do
If Zaehler => 33 Then
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 101 Then
Return
End If
Loop

Rechts:
Do
If Zaehler => 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 1
Mrechtsrueck = 0
Else
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 83 Then
Return
End If
Loop

Ontimer:
Incr Zaehler
Print Zaehler
Return


Schau dir auch mal an wie ich aus deinen Zwei (If Zaehler > 33 Or Zaehler = 33 Then If Zaehler < 33 Then ) eine mit ELSE gemacht habe. Die ist viel übersichtlicher, und zudem im Prinzip auch noch schneller.

Ein andrer Grund ist, dass es in andren Sprachen keinen GOTO gibt. Wenn du dir den GOTO zu sehr angewöhnst wirst du beim umsteigen auf eine andere Sprache viel Schwierigkeiten haben.

Für den Anfang würde ich dir raten mit einem Flußdiagramme zuarbeiten Googel mal nach Flußdiagramme. Eine andre und bessere Möglichkeit ist mit einem Struktogramme, aber das ist ein wenig schwieriger. Und erst wenn dein Programm im Flußdiagramme funktioniert solltest du anfangen den Code zuschreiben.

So ich hoffe ich konnte dir ein wenig weiter helfen, und noch viel Spaß beim Progen.

mfg
Guy

PicNick
29.12.2005, 10:45
...dir raten mit einem Flußdiagramm...

Das ist ja grad das böse. Gerade Flußdiagramme verleiten zu unstrukturierten Monstrositäten, ganz einfach, weil sie es zulassen.
Ganz einfach: Jeder, der "goto" reinschreibt, gibt jedesmal 5 € in die Kaffee-Kassa

Guy
29.12.2005, 11:11
Ja schon, Ich finde es für einen Anfänger aber einfacher, und allemal besser als gleich den Code zuschreiben.

Ich bin auch nicht der Meinung, daß man den GOTO gar nicht benutzen soll, man sollte ihn nur sehr bewußt einsetzen und ihn dann gut kommentieren.

Torsten_G
29.12.2005, 19:56
Gefährlich sind pikante Mischungen aus "goto" und "gosub", vor allem noch im Zusammenhang mit Interrupts.

Wenn man in einer Subroutine ist, sollte man nicht mit einem Goto wieder aussteigen, weil eben sonst die Rücksprungadresse auf ewig gepeichert bleibt, irgendwann braucht jedes "Gosub" sein "Return"!

Kleine Grundregel:
Kein "Goto" in Subroutinen, dessen Ziel außerhalb der Routine liegt...

Grüße

Torsten

@PicNick:
http://www.schiffsmodell.net/users/torsten/pics/donald.jpg

\:D/ \:D/ \:D/ :mrgreen:

PicNick
30.12.2005, 06:29
@torsten_G: ogottogott, da ist ja mein Schwager !

Grillmeister Markus
30.12.2005, 22:34
Hallo.
So, ich hab jetzt das programm nochmal komplett anders aufgebaut (ohne GOTOs) und es funktioniert auch. Jetzt wollt ich wissen, ob das vom "Stiel" her so OK ist. Wär nett, wenn einer von euch das mal kurz überfliegen könnte.



$regfile = "2313def.dat"
$crystal = 3686400
$baud = 9600

Dim Zaehler As Byte

Ddrd.2 = 1 'motor rechts vorwärts
Ddrd.3 = 1 'motor rechts rückwärts
Ddrd.4 = 1 'motor links vorwärts
Ddrd.5 = 1 'motor links rückwärts
Ddrb.6 = 1 'enable rechts
Ddrb.7 = 1 'enable links

Ddrb.0 = 0 'taster links vorne
Ddrb.1 = 0 'taster mitte vorne
Ddrb.2 = 0 'taster rechts vorne
Portb.0 = 1
Portb.1 = 1
Portb.2 = 1

Mrechtsvor Alias Portd.2
Mrechtsrueck Alias Portd.3
Mlinksvor Alias Portd.4
Mlinksrueck Alias Portd.5
Enablerechts Alias Portb.6
Enablelinks Alias Portb.7

Schalterlinks Alias Pinb.0
Schaltermitte Alias Pinb.1
Schalterrechts Alias Pinb.2

Config Timer0 = Timer , Prescale = 1024
Enable Timer0
Start Timer0
Enable Interrupts
On Timer0 Ontimer

Enablelinks = 1
Enablerechts = 1

Do
If Schalterlinks = 1 And Schaltermitte = 1 And Schalterrechts = 1 Then
Print "g"
Gosub Gerade
End If
If Schalterlinks = 0 Then
Print "L"
Zaehler = 0
Gosub Links
End If
If Schaltermitte = 0 Then
Print "M"
Zaehler = 0
Gosub Mitte
End If
If Schalterrechts = 0 Then
Print "R"
Zaehler = 0
Gosub Rechts
End If
Loop

Gerade:
Mlinksvor = 0
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100
Do
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 1
Mrechtsrueck = 0
If Schalterlinks = 0 Or Schaltermitte = 0 Or Schalterrechts = 0 Then
Return
End If
Loop

Links:
Mlinksvor = 0
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100
Do
If Schaltermitte = 0 Or Schalterrechts = 0 Then
Return
End If
If Zaehler <= 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 70 Then
Return
End If
Loop

Mitte:
Mlinksvor = 0
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100
Do
If Schalterlinks = 0 Or Schalterrechts = 0 Then
Return
End If
If Zaehler <= 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 1
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
If Zaehler = 90 Then
Return
End If
Loop

Rechts:
Mlinksvor = 0
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100
Do
If Schalterlinks = 0 Or Schaltermitte = 0 Then
Return
End If
If Zaehler <= 33 Then
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 0
Mlinksrueck = 1
Mrechtsvor = 1
Mrechtsrueck = 0
End If
If Zaehler = 70 Then
Return
End If
Loop

Ontimer:
Incr Zaehler
Return


mfg Markus

Edit: Achja, ich hab jetzt keine Relais mehr, sondern nen L293D, deswegen sind die pinbelegungen jetzt etwas anders.

Torsten_G
30.12.2005, 23:39
Also, ich find´s schon viel besser als vorher!

Sogar die If-Then-Abfragen mit Tab eingerückt, sieht richtig gut aus!

Allerdings, Kommentarzeilen (die beginnen mit Hochkomma ') sind nicht nur ein uncooles Feature für Alzheimer-geplagte Programmierer - sie erleichtern auch "Programmfremden" den Durchblick und beschleunigen sogar die Orientierung im eigenen Programm! :-b

Ich weiß ja, "Kommentarzeilen-Einfüger" steht in einer Reihe mit "Schattenparker" und "Warmduscher", aber ich finde, fehlende Kommentare sind fast noch schlimmer als verstrubbelte Goto´s und Gosub´s, weil hinterher noch nicht einmal mehr die Intentionen des Programmierers nachvollzogen werden können -> 10 Euro in die Kaffeekasse! \:D/

Man kann im Übrigen Kommentare ins Bascom-Programm hacken bis zum Abwinken, sie fressen keinen Speicherplatz im Chip und werden somit auch bei der Einschränkung der Bascom-Demo nicht berücksichtigt.

Du hattest ja gefragt, ob der Stil so ok ist, und das würde halt noch fehlen.

Hier ein Beispiel aus eigener Feder, stell Dir mal vor, Du müsstest da ohne die Kommentare durchsteigen:

:
'*****************************************
' Program for PWM Speed Controller
' based on Stupsi´s RN-Power-Board
' Designed for Atmel AVR Mega 8
' Bascom Version 1.11.7.9
' 18.11.2005 T. Gietenbruch
'
' Hardware Configuration:
' -> Setup button input at Pinb.0 (14)
' -> RC-Channel PWM input at Pind.2 (4) (INT0)
' -> Output FWD direction signal at Portd.6 (12)
' -> Output BWD direction signal at Portd.7 (13)
' -> LED for FWD direction indication at Portd.4 (6)
' -> LED for BWD direction indication at Portd.5 (11)
' -> Output PWM_Pulse at Portb.3 (17) (MOSI / OC2)
' -> I2C-Bus: SDA at PC4 / SCL at PC5
' -> Internal Oscillator 8000000Hz
'
' External TTL logic for circuit protection
'
'******************************************

'==========================================
' System Configurations
'==========================================

'Definition for Mega 8
$regfile "m8def.dat"

$crystal = 8000000

'$lib "i2c_twi.lbx"

'==========================================
' Configurations
'==========================================

'PIN Configurations
' Bit 76543210 0->IN / 1->OUT
Ddrb = &B00001000
Ddrd = &B11110000


'Timer 1 for RC-Channel measurement
Config Timer1 = Timer , Prescale = 1

'Timer 2 for PWM-signal on OC2
Config Timer2 = Pwm , Prescale = 64 , Compare = Clear


'==========================================
' Tag Declarations
'==========================================
Dim Error As Byte
Dim Init As Bit
Dim N As Byte
Dim Timer_calc As Long
Dim Steps_max As Word
Dim Steps_min As Word
Dim Upperlimit As Word
Dim Lowerlimit As Word
Dim Window As Word
Dim Start_max As Word
Dim Start_min As Word
Dim State As Byte

'EEPROM Tags
Dim Neutral As Eram Word
Dim Maximum As Eram Word
Dim Minimum As Eram Word

Dim State_byte As Eram Byte
'State_Byte.0 for Direction: 0-> Not inverted, 1-> Inverted

'==========================================
' Interrupt Handlings
'==========================================
On Timer1 Read_error
Enable Interrupts


'==========================================
' Initializing Timers
'==========================================
Enable Timer1
Enable Timer2
Stop Timer1
Stop Timer2
Timer1 = 0
Timer2 = 0


'==========================================
' Initializing values
'==========================================
Ocr2 = 0
Portb = &B11111111
Portd = &B00111111

Window = 250
Init = 0
Error = 0

'==========================================
' Configure RC-Channel Settings
'==========================================
Setup_again:

'1. Wait until switch on B.0 is on

If Pinb.0 = 1 Then Goto Nosetup

Bitwait Pinb.0 , Set

While Pinb.0 <> 0
Toggle Portd.4
Toggle Portd.5
Waitms 500
Wend
Portd.4 = 1
Portd.5 = 1

'2. Read neutral position value
Timer1 = 0
Start Timer1
Bitwait Pind.2 , Reset
Gosub Read_channel
Stop Timer1
Neutral = Timer1
Timer1 = 0
'Flash LED for read confirmation
For N = 0 To 2
Toggle Portd.4
Toggle Portd.5
Waitms 30
Toggle Portd.4
Toggle Portd.5
Waitms 100
Next
Portd.4 = 1
Portd.5 = 1

'4. Wait until switch on B.0 is off and on again
Bitwait Pinb.0 , Set
Waitms 100
While Pinb.0 <> 0
Toggle Portd.4
Waitms 500
Wend
Portd.4 = 1

'5. Read forward value
Timer1 = 0
Start Timer1
Bitwait Pind.2 , Reset
Gosub Read_channel
Stop Timer1

If Timer1 > Neutral Then
Maximum = Timer1
State.0 = 0
Else
Minimum = Timer1
State.0 = 1
End If

Timer1 = 0

'Flash LED for read confirmation
For N = 0 To 2
Toggle Portd.4
Waitms 30
Toggle Portd.4
Waitms 100
Next
Portd.5 = 1

'6. Wait until switch on B.0 is off and on again
Bitwait Pinb.0 , Set
Waitms 100
While Pinb.0 <> 0
Toggle Portd.5
Waitms 500
Wend
Portd.5 = 1

'7. Read backward value
Timer1 = 0
Start Timer1
Bitwait Pind.2 , Reset
Gosub Read_channel
Stop Timer1

Select Case State.0

Case 0:
If Timer1 > Neutral Then
Goto Setup_again
Else
Minimum = Timer1
End If

Case 1:
If Timer1 < Neutral Then
Goto Setup_again
Else
Maximum = Timer1
End If

End Select

Timer1 = 0
'Flash LED for read confirmation
For N = 0 To 2
Toggle Portd.5
Waitms 30
Toggle Portd.5
Waitms 100
Next
Portd.5 = 1

'8. Write State to eprom byte
State_byte = State

'8. Wait until switch on B.0 is off
Bitwait Pinb.0 , Set

'Target without setup
Nosetup:

If Neutral < 2000 Or Neutral > 20000 Or Maximum < 6000 Or Maximum > 30000 Or Maximum <= Neutral Or Minimum < 2000 Or Minimum > 30000 Or Minimum >= Neutral Then
Portd.4 = 0
Portd.5 = 1
While Pinb.0 = 1
Toggle Portd.4
Toggle Portd.5
Waitms 100
Wend
Portd.4 = 1
Portd.5 = 1
Goto Setup_again
End If

'Calculation of RC-Channel compare values
Start_max = Neutral + Window
Steps_max = Maximum - Start_max
Steps_max = Steps_max - 30

Start_min = Neutral - Window
Steps_min = Start_min - Minimum
Steps_min = Steps_min - 30

State = State_byte



'==========================================
' Main Program Loop
'==========================================
Do

'Disable PWM with Pinb.0=0 (Button pressed)
If Pinb.0 = 0 Or Init = 0 Then
Stop Timer2
Timer2 = 0
Ocr2 = 0
Portd.6 = 0
Portd.7 = 0
End If

'Enable PWM with Pinb.0=1
If Pinb.0 = 1 And Init = 1 Then
Start Timer2
End If


'Calculate PWM-value for maximum direction
If Timer1 >= Start_max And Pinb.0 = 1 And Init = 1 Then
Portd.6 = Not State.0
Portd.7 = State.0
Timer_calc = Timer1 - Start_max
Timer_calc = Timer_calc * 255
Timer_calc = Timer_calc / Steps_max
End If

'Calculate PWM-value for minimum direction
If Timer1 <= Start_min And Pinb.0 = 1 And Init = 1 Then
Portd.6 = State.0
Portd.7 = Not State.0
Timer_calc = Start_min - Timer1
Timer_calc = Timer_calc * 255
Timer_calc = Timer_calc / Steps_min
End If

'Set PWM-value to zero in within neutral position window
If Timer1 > Start_min And Timer1 < Start_max Then
Portd.6 = 0
Portd.7 = 0
Timer_calc = 0
Init = 1
End If

'Limit PWM-value to maximum 255
If Timer_calc > 255 Then Timer_calc = 255

'Write PWM-value to compare register for timer2
If Init = 1 And Pinb.0 = 1 Then
Ocr2 = Timer_calc
Else
Portd.6 = 0
Portd.7 = 0
Ocr2 = 0
End If

'Switch LED´s on according direction bits
Portd.4 = Not Portd.6
Portd.5 = Not Portd.7

'Jump to RC-channel subroutine
Enable Interrupts
Timer1 = 0
Start Timer1
Bitwait Pind.2 , Reset
Stop Timer1
Gosub Read_channel
Disable Interrupts

Loop

'RC-channel reading
Read_channel:
Timer1 = 0
Start Timer1
Bitwait Pind.2 , Set
Timer1 = 0
Bitwait Pind.2 , Reset
Stop Timer1
Error = 0
Return

'Error handler
Read_error:
If Error < 10 Then Error = Error + 1
While Error = 10
Stop Timer2
Timer2 = 0
Ocr2 = 0
Init = 0
Portd.6 = 0
Portd.7 = 0
Portd.4 = 0
Portd.5 = 0
Gosub Read_channel
Wend

Return

Grüße

Torsten

@PicNick:
Dir wär´s bestimmt lieber, wenn das der reiche Erbonkel wäre... :mrgreen:

Guy
31.12.2005, 12:30
Ist OK so, So habe ich mich gleich in deinem Programm zurecht gefunden. Bei deiner ersten Version hätte ich mir erst gar nicht die Mühe gemacht den Ablauf zu verstehen.

Nur wie Torsten schon sagte, Kommentarzeilen einfügen. Auch wenn das anfangs lästig erscheint spart es dir im nachhinein viel ärger und Zeit. Ich habe durch gute Kommentarzeilen schon oft viel Zeit gespart.

Du kannst auch Kommentare hinter eine Anweisung setzen, zum Beispiel
Else ' ***** Kommentar ****

Ich würde jetzt noch deine If umändern. So ist sie noch übersichtlicher. Man sieht gleich, daß wenn die drei Schalter 1 sind "Gerade" ausgeführt wird, andernfalls die andren Ifs abgearbeitet werden. Zudem kannst du die drei andren Abfragen noch einrücken, was das ganze noch übersichtlicher macht.




Do
If Schalterlinks = 1 And Schaltermitte = 1 And Schalterrechts = 1 Then
Print "g"
Gosub Gerade
Else
If Schalterlinks = 0 Then
Print "L"
Zaehler = 0
Gosub Links
End If
If Schaltermitte = 0 Then
Print "M"
Zaehler = 0
Gosub Mitte
End If
If Schalterrechts = 0 Then
Print "R"
Zaehler = 0
Gosub Rechts
End If
End If
Loop


mfg
guy

Grillmeister Markus
31.12.2005, 14:48
Hallo.
So, ich hab jetzt die IF-schleifen noch so umgebaut und kommentare eigefuegt.
Mfg Markus



$regfile = "2313def.dat" 'Atmel AT90S2313
$crystal = 3686400 'Quarz = 3.6864 mhz
$baud = 9600 ' Baudrate = 9600

Dim Zaehler As Byte

Ddrd.2 = 1 'motor rechts vorwärts
Ddrd.3 = 1 'motor rechts rückwärts
Ddrd.4 = 1 'motor links vorwärts
Ddrd.5 = 1 'motor links rückwärts
Ddrb.6 = 1 'enable rechts
Ddrb.7 = 1 'enable links

Ddrb.0 = 0 'taster links vorne
Ddrb.1 = 0 'taster mitte vorne
Ddrb.2 = 0 'taster rechts vorne
Portb.0 = 1 'Pullups fuer taster aktivieren
Portb.1 = 1
Portb.2 = 1

Mrechtsvor Alias Portd.2 'Pins entsprechent der belegung benennen
Mrechtsrueck Alias Portd.3
Mlinksvor Alias Portd.4
Mlinksrueck Alias Portd.5
Enablerechts Alias Portb.6
Enablelinks Alias Portb.7

Schalterlinks Alias Pinb.0
Schaltermitte Alias Pinb.1
Schalterrechts Alias Pinb.2

Config Timer0 = Timer , Prescale = 1024 'timer0 wird verwendet, quarz / 1024
Enable Timer0 'timer0 einschalten
Start Timer0 'timer0 starten
Enable Interrupts 'interrupts zulassen
On Timer0 Ontimer 'bei timerueberlauf gehe zu "ontimer"

Enablelinks = 1 'Pin fuer linken motor auf 5V
Enablerechts = 1 'Pin fuer rechten motor auf 5V

'***************###### HAUPTSCHLEIFE ######***************

Do
If Schalterlinks = 1 And Schaltermitte = 1 And Schalterrechts = 1 Then 'wenn alle schalter frei
Print "g" 'print "g" für fahrtenschreiber
Gosub Gerade 'gehe zu "gerade"
Else
If Schalterlinks = 0 Then 'wenn linker schalter gedrückt
Print "L" 'print "L" für fahrtenschreiber
Zaehler = 0 'setzte Zaehler auf null
Gosub Links 'gehe zu "links"
End If
If Schaltermitte = 0 Then 'wenn mittlerer schalter gedrückt
Print "M" 'print "M" für fahrtenschreiber
Zaehler = 0 'setzte Zaehler auf null
Gosub Mitte 'gehe zu "mitte"
End If
If Schalterrechts = 0 Then 'wenn rechter schalter gedrückt
Print "R" 'print "R" für fahrtenschreiber
Zaehler = 0 'setzte Zaehler auf null
Gosub Rechts 'gehe zu "rechts"
End If
End If
Loop


'***************###### GERADE ######***************
Gerade:
Mlinksvor = 0 'motoren bremsen
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100 'zeit zum bremsen
Do
Mlinksvor = 1 'unendlich vorwaerts fahren, bis anderer befehl kommt
Mlinksrueck = 0
Mrechtsvor = 1
Mrechtsrueck = 0
If Schalterlinks = 0 Or Schaltermitte = 0 Or Schalterrechts = 0 Then 'wenn irgendein schalter gedrückt
Return 'dann zurueck zur hauptschleife
End If
Loop


'***************###### BEI LINKEM SCHALTER ######***************
Links:
Mlinksvor = 0 'motoren bremsen
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100 'zeit zum bremsen
Do
If Schaltermitte = 0 Or Schalterrechts = 0 Then 'wenn mittlerer oder rechter schalter gedrueckt
Return 'dann zurueck zur hauptschleife
Else
If Zaehler <= 33 Then 'wenn Zaehler <= 33
Mlinksvor = 0 'dann rueckwaerts fahren bis Zaehler > 33
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 1 'danach drehung nach rechts
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
End If
If Zaehler = 70 Then 'wenn Zaehler = 70
Return 'dann zurueck zur hauptschleife
End If
Loop


'***************###### BEI MITTLEREM SCHALTER ######***************
Mitte:
Mlinksvor = 0 'motoren bremsen
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100 'zeit zum bremsen
Do
If Schalterlinks = 0 Or Schalterrechts = 0 Then 'wenn linker oder rechter schalter gedrueckt
Return 'dann zurueck zur hauptschleife
Else
If Zaehler <= 33 Then 'wenn Zaehler <= 33
Mlinksvor = 0 'dann rueckwaerts fahren bis Zaehler > 33
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 1 'danach drehung nach rechts
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 1
End If
End If
If Zaehler = 90 Then 'wenn Zaehler = 90
Return 'dann zurueck zur hauptschleife
End If
Loop


'***************###### BEI RECHTEM SCHALTER ######***************
Rechts:
Mlinksvor = 0 'motoren bremsen
Mlinksrueck = 0
Mrechtsvor = 0
Mrechtsrueck = 0
Waitms 100 'zeit zum bremsen
Do
If Schalterlinks = 0 Or Schaltermitte = 0 Then 'wenn linker oder mittlerer schalter gedrueckt
Return 'dann zurueck zur hauptschleife
Else
If Zaehler <= 33 Then 'wenn Zaehler <= 33
Mlinksvor = 0 'dann rueckwaerts fahren bis Zaehler > 33
Mlinksrueck = 1
Mrechtsvor = 0
Mrechtsrueck = 1
Else
Mlinksvor = 0 'danach drehung nach links
Mlinksrueck = 1
Mrechtsvor = 1
Mrechtsrueck = 0
End If
End If
If Zaehler = 70 Then 'wenn Zaehler = 70
Return 'dann zurueck zur hauptschleife
End If
Loop


'Interrupt-Routine für TIMER0
Ontimer: 'wenn timer0 ueberlaeuft
Incr Zaehler 'dann Zaehler incrementieren
Return 'danach zurueck zur hauptschleife

Guy
31.12.2005, 15:36
Gut so, aber du darfst auch nicht über kommentieren.

Anweisungen die selbsterklärend sind wie
$crystal = 3686400 'Quarz = 3.6864 mhz
$baud = 9600 ' Baudrate = 9600
Enable Timer0 'timer0 einschalten
Start Timer0 'timer0 starten
Enable Interrupts 'interrupts zulassen

Braus du nicht unbedingt zu kommentieren sonst wird das auch unübersichtlich.

So was kannst du in den Kopf des Programms als Kommentar schreiben.
Zum Beispiel Wozu das Programm gut ist, Version, Datum, Quart, Controler etc.