Archiv verlassen und diese Seite im Standarddesign anzeigen : [ERLEDIGT] Pwm Motorsteuerung mit PCINT1
Hey Leute ich muss eine kleine Motorsteuerung über den PWM ausgang eines ATmega168 steuern.
ich möchte das, dass pwm Signal durch auslösen des Tasters PinC.0 (Pcint1) langsammer kommt. das Pwm configurieren geht ja alles nur das mit den PCINT1 und der dazugehörigen Pinabfrage (um mit mehreren Tastern steuern zu können bekomme ich gerade nicht richtig hin.
meinen Testprogramm beinhaltet erstmal nur ein Taster aber es sollen noch 5 hinzukommen.
Die Taster sollen als Falling configuriert werden das funzt aber auch nicht :D
24759
Ich hoffe ihr könnt mir helfen :D es wäre ein wenig dringend aber ich will euch nicht hätzen den gut ding will weile haben ;D
Sauerbruch
08.03.2013, 23:06
Moin Balu!
Als erstes wäre es für alle hier einfacher, sich Gedanken über Deinen Code zu machen, wenn Du ihn mit der "Code"-Funktion direkt im Thread zeigen würdest. Dann muss man nämlich nicht immer erst sein Bascom starten.
Zweitens - kannst Du vielleicht etwas genauer beschreiben, was "nicht funzt"? Je genauer die Fehlerbeschreibung ist, umso wahrscheinlicher ist es, dass jemand die Ursache des Fehlers erkennt :-)
Die Taster sollen als Falling configuriert werden das funzt aber auch nicht
Das ist ganz einfach erklärt: PCINT´s können nicht als rising, falling, low oder high level konfiguriert werden, sondern sind automatisch als nur als change konfiguriert, d.h. jeder Pegelwechsel löst die ISR aus. Deshalb heißen sie ja auch Pin-Change Interrupts.
Und Interrupt-Routinen müssen so kurz wie möglich sein, da sie den Ablauf des Hauptprogramms unterbrechen. Ein "Waitms 2000" in der ISR ist keine gute Idee!
Der code
$regfile "m168def.dat"
$crystal = 8000000
Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input
Config Pinb.1 = Output
Config Pinb.2 = Output
Config Pind.5 = Output
Config Pind.6 = Output
Motor1 Alias Pinb.1
Motor2 Alias Pinb.2
Motor3 Alias Pind.5
Motor4 Alias Pind.6
Freischalten Alias Pind.7
Enable Interupts
Enable Pcint1
On Pcint1 Pwm1
Config Pcint1 = Falling
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 1
'Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up
Dim M As Byte
Dim N As Byte
Dim X As Byte
Dim Y As Byte
M = 128
N = 128
X = 128
Y = 128
Do
Compare1b = M
Freischalten = 1
Loop
Pwm1 :
If Pinc.0 = 0 Then
Compare1b = M - 64
Waitms 2000
End If
Return
End
und es funktioniert nicht das das Pwm signal sich verkürtzt beim betätigen des tasters stattdessen geht sie einfach nur für die zeit aus und macht nichts weiter :( sprigt nach der zeit aber wieder ins Normale Programm :)
Lg
Hey leute ich hab jetzt mal nen bvisschen ausprobiert und es einigermaßen hinbekommen jetzt habe ich aber ein kleines Problem also die Pwm Geschwindigkeiten sind im EEProm abgelegt unter den Stellen 0-2. Die stelle ist am anfang auf 0 gesetzt. und wird durch ausführen des PCINT1 auf 1 Oder 2 gesetzt. Jetzt möchte ich beim Ausführen des Interrupts INT0 das Diese stellen wieder auf 0 Gesetzt werden und da habe ich ein problem undzwar tut es dies nicht :( . Die Varriable E dient aussschließslich dazu das nur ein Taster Betätigt werden kann.
Der Code
$regfile "m168def.dat"
$crystal = 8000000
Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input
Config Pind.2 = Input
Config Pinb.1 = Output
Config Pinb.2 = Output
Config Pind.5 = Output
Config Pind.6 = Output
Motor1 Alias Pinb.1
Motor2 Alias Pinb.2
Motor3 Alias Pind.5
Motor4 Alias Pind.6
Freischalten Alias Pind.7
Pind.2 = 1
Enable Interrupts
Enable Pcint1
Enable Int0
On Pcint1 Pwm1
On Int0 Pwm2
Pcmsk1 = &B11111111
Config Int0 = Falling
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 8
'Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up
$eeprom 'EEprom beschreiben
Label1:
Data 128 , 192 , 64
$data
Dim M As Byte
Dim N As Byte
Dim X As Byte
Dim Y As Byte
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim E As Byte
M = 0
N = 0
X = 0
Y = 0
E = 0
Do
Gedrueckt1:
Readeeprom A , M 'Auslesen der Daten aus dem EEprom und anschließende Ausgabe
Compare1b = A
Freischalten = 1
Loop
Pwm1:
If E = 1 Then
Goto Gedrueckt1
End If
If Pinc.0 = 0 Then
M = M + 2
N = N + 2
E = E + 1
End If
If Pinc.1 = 0 Then
M = M + 1
N = N + 1
E = E + 1
End If
If Pinc.2 = 0 Then
X = X + 2
Y = Y + 1
E = E + 1
End If
If Pinc.3 = 0 Then
M = M + 2
N = N + 1
E = E + 1
End If
If Pinc.4 = 0 Then
M = M + 61
N = N + 2
E = E + 1
End If
If Pinc.5 = 0 Then
X = X + 1
Y = Y + 2
E = E + 1
End If
Return
Pwm2:
M = M * 0
N = N * 0
X = X * 0
Y = Y * 0
E = E - 1
Return
End
Sauerbruch
09.03.2013, 15:34
Mir erschließt sich zwar leider immer noch nicht so genau, WAS der Controller denn nun letzten Endes tun soll - aber ich habe einen weiteres "No-Go" im Zusammenhang mit Interrupts entdeckt (das erste waren "Wait"-Befehle in der ISR):
Die ISR darf niemals mit einem Goto verlassen werden!
Und es ist auch schnell erklärt wieso:
Bei jedem Interrupt werden als allererstes eine Menge Register-Inhalte "gerettet", damit der Controller nach dem Abarbeiten der ISR an genau der gleichen Stelle weiterarbeiten kann, an der er unterbrochen wurde. Die Inhalte dieser Register werden in den sogenannten "Stack" (= "Haufen") geschrieben, für den ein Teil des Speichers reserviert ist. Wenn am Ende der ISR der Befehl Return kommt, werden alle Bytes aus dem Stack in die Register zurückgeschrieben - der Controller kann ganz normal weiterarbeiten, und Stack ist wieder frei für den nächsten Interrupt.
Wenn der Return-Befehl aber übersprungen wird (indem die ISR mit einem Goto verlassen wird), wächst der Stack bei jedem Interrupt an, und da er nur eine endliche Größe besitzt, läuft er irgendwann einmal über - und dann hängt der Controller fest.
Also: Die ISR Immer schön über Return verlassen!!
Allerdings erklärt das Dein Problem noch nicht, denn E ist ja zunächst mal 0, so dass dieses Goto gar nicht ausgeführt werden sollte.
Hast Du denn ordentliche PullUp-Widerstände an den Eingängen? Die Controller-eigenen sind ja nicht aktiviert...
Edit:
Außerdem ist es eine potenzielle Fehlerquelle, E durch Additionen und Subtraktionen auf 1 und 0 zu setzen. Wenn z.B. als erstes die ISR PWM2 abläuft, ist E = 0 - 1 = 255, und dann stimmt sowieso nichts mehr.
Schreib doch stattdessen ganz einfach E=0 oder E=1! Genauso einfach kannst Du die Variablen M, N, X und Y in der ISR PWM2 auf 0 setzen, ohne eine aufwendige Multiplikation zu machen!
Also als erstes habe ich 10KOhm wiederstände als Pull Up wiederstände :D
Zweitens Danke für den Tipp mit dem Return :D
So nun Zur funktion: Das Programm soll die in das Eprom gespeicherten werte als PWM signal ausgeben. (sollte ersichtlich sein :D ) das Freischalten schaltet das IC an.
Jetzt soll durch betätigen des PCINT1 überprüft werden ob schon ein Taster betätigt war ( E=1) und welcgher taster es war.
Wenn der Taster PINC.0 betätigt war soll dich die Stellen angabe M um zwei nach rechts verschieben (M=M+2) und durch E=E+1 signalisieren das ein taster betätigt war.
Die andern Varriablen N,X,Y dienen mir dazu dass ich im nachhinnein noch drei weitere PWM Befehle für drei weitere Motoren einfügen kann.
und nun soll durch betätigen des Tasters PIND.2 (INT0) eine art Reset verwirklicht werden bei dem die Werte für die Stellen im EPRom auf Null zurückgesetzt werden. das funzt aber i wie nicht mit meiner Lösung :(
ich hoffe jetzt wird klarer was das Programm machen soll :D
Lg Balu
Sauerbruch
09.03.2013, 16:14
Okay - weshalb der EEPROM-Speicher verwendet wird, verstehe ich zwar nicht, aber das macht auch nichts...
Wie gesagt - ich würde E nicht durch irgendwelche unkontrollierten Additionen und Subtraktionen manipulieren, die schnell mal außer Kontrolle geraten können wenn sie ungewollt mehrfach hintereinander ablaufen, sondern diese Variable ganz sauber mittels E=0 oder E=1 auf den gewünschten Wert setzen. Dann macht es nämlich nichts, wenn dieser Befehl ein zweites oder drittes mal ausgeführt wird.
Aber da ist noch was anderes:
Motor1 bis Motor4 und Freischalten sind als Ausgänge konfiguriert - und in diesem Fall darfst Du nicht die Pin-Register, sondern musst die Port-Register nehmen!
Also Freischalten Alias PORTD7, Motor1 Alias PORTB.1 usw.
Versuch das mal...
Was macht die Schaltung denn bisher überhaupt? Erzeugt sie wenigstens schon mal ein PWM-Signal?
Ja also das mit dem stellen verschieben durch den PCint1 funktioniert nur das mit dem auf Null setzten nicht ::( sprich zurücksetzen :(
was hättest du den sonst für ne Möglichkeit als vorschlag ;D
und beim Gleichsetzten Z.B. M=2 behält der den Wert nicht wenn er aus dem Interrupt springt :(
Sauerbruch
09.03.2013, 17:35
Was heißt denn er "behält" den Wert nicht?
Und hast Du in der PWM2-ISR den Befehl M=M*0 ersetzt durch M=0?
Und wie hast Du es jetzt gelöst, dass bei E=1 die ganze Verschieberei in der ISR übersprungen wird? D.h. wie "springst" du jetzt aus der ISR PWM1?
Also das ist jetzt mein aktueller code:
$regfile "m168def.dat"
$crystal = 8000000
Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input
Config Pind.2 = Input
Config Pinb.1 = Output
Config Pinb.2 = Output
Config Pind.5 = Output
Config Pind.6 = Output
Motor1 Alias Portb.1
Motor2 Alias Portb.2
Motor3 Alias Portd.5
Motor4 Alias Portd.6
Freischalten Alias Portd.7
Pind.2 = 1
Enable Interrupts
Enable Pcint1
On Pcint1 Pwm1
Pcmsk1 = &B11111111
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 8
'Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up
$eeprom 'EEprom beschreiben
Label1:
Data 128 , 192 , 64
$data
Dim M As Byte
Dim N As Byte
Dim X As Byte
Dim Y As Byte
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim E As Byte
M = 0
N = 0
X = 0
Y = 0
E = 0
Do
Readeeprom A , M 'Auslesen der Daten aus dem EEprom und anschließende Ausgabe
Compare1b = A
Freischalten = 1
Loop
Pwm1:
If E = 1 Then
Return
End If
If Pinc.0 = 0 Then
M = 2
N = 2
E = 1
End If
If Pinc.1 = 0 Then
M = 1
N = 1
E = 1
End If
If Pinc.2 = 0 Then
X = 2
Y = 1
E = 1
End If
If Pinc.3 = 0 Then
M = 2
N = 1
E = 1
End If
If Pinc.4 = 0 Then
M = 1
N = 2
E = 1
End If
If Pinc.5 = 0 Then
X = 1
Y = 2
E = 1
End If
Return
End
Da habe ich jetzt den INT0 rausgenommen um mich erstmal darum zu kömmern das das andere funzt :D
Mit behält meine ich das der zum tasterpassende wert nur solange beibehalten wird wie ich den Taster drücke sobald ich ihn loslasse springt er wieder ins Normalprogramm.
Sauerbruch
09.03.2013, 17:59
Was heißt "Normalprogramm?
Das einzige was feststeht ist, dass die Variable E beim ersten Tastendruck auf 1 gesetzt wird, und damit alle weiteren Tastendrucke blockiert sind, weil sie nirgendwo mehr auf 0 zurückgesetzt hat.
Also Danke Sauerbruch für die hilfe :D
i wie hab ich das ganz durch probieren alleine hinbekommen :D die zipps waren trotzdem gut :D
hier jetzt mein endcode vill kannst du ja dann verstehen was ich vorhatte :D
$regfile "m168def.dat"
$crystal = 8000000
Config Pinc.0 = Input
Config Pinc.1 = Input
Config Pinc.2 = Input
Config Pinc.3 = Input
Config Pinc.4 = Input
Config Pinc.5 = Input
Config Pind.2 = Input
Config Pinb.1 = Output
Config Pinb.2 = Output
Config Pind.5 = Output
Config Pind.6 = Output
Motor1 Alias Portb.1
Motor2 Alias Portb.2
Motor3 Alias Portd.5
Motor4 Alias Portd.6
Freischalten Alias Portd.7
Pind.2 = 1
Enable Interrupts
Enable Pcint1
Enable Int0
On Pcint1 Pwm1
On Int0 Pwm2
Config Int0 = Falling
Pcmsk1 = &B11111111
Config Timer1 = Pwm , Pwm = 8 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up , Prescale = 8
'Config Timer0 = Pwm , Prescale = 1 , Compare A Pwm = Clear Up , Compare B Pwm = Clear Up
$eeprom 'EEprom beschreiben
Label1:
Data 128 , 192 , 64
$data
Dim M As Byte
Dim N As Byte
Dim X As Byte
Dim Y As Byte
Dim A As Byte
Dim B As Byte
Dim C As Byte
Dim D As Byte
Dim E As Byte
M = 0
N = 0
X = 0
Y = 0
E = 0
Do
Readeeprom A , M 'Auslesen der Daten aus dem EEprom und anschließende Ausgabe
Compare1b = A
Freischalten = 1
Loop
Pwm1:
If Pinc.0 = 0 Then
M = 2
N = 2
E = 1
End If
If Pinc.1 = 0 Then
M = 1
N = 1
E = 1
End If
If Pinc.2 = 0 Then
X = 2
Y = 1
E = 1
End If
If Pinc.3 = 0 Then
M = 2
N = 1
E = 1
End If
If Pinc.4 = 0 Then
M = 1
N = 2
E = 1
End If
If Pinc.5 = 0 Then
X = 1
Y = 2
E = 1
End If
Return
Pwm2:
M = 0
N = 0
X = 0
Y = 0
Return
End
Lg der Balu
Sauerbruch
09.03.2013, 18:48
Na, super!
Dan kannste ja noch alle Zeilen rausschmeißen, in denen die Variable "E" vorkommt (schadet zwar nicht, aber wegen der Übersichtlichkeit) :-)
Und Pind.2=1 ist glaube ich auch nur ein "Verwirrer"...
Viel Erfolg noch beim Ausbau auf 4 Taster :-)
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.