PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PID-Regler mit PWM - Frage



Che Guevara
08.12.2009, 14:37
Hallo Leute,

ich bins mal wieder :-)
ich habe jetzt einen Servo gehackt und habe ihm noch einen CNY70 eingebaut, welcher auf ein Zahnrad (schwarz und weiß angemalt) gerichtet ist. Ich steuere nur noch den Motor des Servos an, also ein ganz normaler Motor mit anschließender Übersetzung. Die impulse des CNY70 werden mit einem Schmitttrigger (74HC14N) "digitalisiert".

Hier mein Programm:


$regfile = "m32def.dat"
$crystal = 16000000
$baud = 19200
$framesize = 80
$hwstack = 80
$swstack = 80


Config Int0 = Change
On Int0 Isr_von_int0
Enable Int0

Config Timer1 = Pwm , Pwm = 10 , Compare A Pwm = Clear Down , Compare B Pwm = Clear Down , Prescale = 8
Pwm1a = 0
Pwm1b = 0

Config Timer2 = Timer , Prescale = 1024
Timer2 = 178
On Timer2 Isr_von_timer2
Enable Timer2

Config Pind.2 = Input
Portd.2 = 0

Config Portb.0 = Output
Config Portb.1 = Output
Config Portd.4 = Output
Config Portd.5 = Output
Portb.0 = 0
Portb.1 = 0

Const Kp = 0.9
Const Ki = 0.8
Const Kd = 0.86

Dim Cny_counter As Word
Dim Timer2_counter As Byte

Dim Print_flag As Bit

Dim Esum As Single
Dim E As Single
Dim Ta As Single
Dim Ealt As Single

Dim Soll As Single
Dim Ist As Single

Dim Kp_buffer As Single
Dim Ki_buffer As Single
Dim Kd_buffer As Single
Dim Kpid_buffer As Single

Ta = 0.05

Soll = 20

Print "PID-Regler mit CNY70"
Print

Waitms 500
Portb.0 = 1
Portb.1 = 0

Enable Interrupts




Do

If Print_flag = 1 Then
Reset Print_flag
Print "Counter = " ; Ist
Print
End If

Loop

End


Isr_von_int0:
Incr Cny_counter
Return

Isr_von_timer2:
Timer2 = 178
Incr Timer2_counter
If Timer2_counter = 10 Then
Set Print_flag
Timer2_counter = 0
Ist = Cny_counter
Cny_counter = 0
Gosub Regulator
Soll = Soll + Kpid_buffer
Pwm1a = Soll
End If
Return

Regulator:
E = Soll - Ist
Esum = Esum + E

Kp_buffer = Kp * E

Ki_buffer = Ki * Ta
Ki_buffer = Ki_buffer * Esum

Kd_buffer = E - Ealt
Kd_buffer = Kd_buffer / Ta
Kd_buffer = Kd_buffer * Kd

Kpid_buffer = Kp_buffer + Ki_buffer
Kpid_buffer = Kpid_buffer + Kd_buffer

Ealt = E
Return


Jetzt zu meinem Problem:
ich steuere die Geschwindigkeit über PWM, allerdings lese ich aber die Anzahl der Impulse in einer gewissen zeit (ta) ein. Das führt i-wie zu Problemen. Wie muss ich das Programm verändern, damit die Regelung vernünftig funktioniert?

Vielen Dank
Gruß
Chris

Besserwessi
08.12.2009, 18:02
Da ist schon mal ein Pronzipielles Problem: mit dem Zählen der Impulse hat man eine nur relativ geringe Auflösung. Bei der Geringen Auflösung ist ein Differenzieren für eine PID Regler besonders schlecht. Wenn der Sollwert bei 10 sein soll, hat man bei funktionieren der Regelung für die Differenz wohl nur Werte von -1,0 oder 1 und damit alles andere als einen stetigen Regler.

Wenn möglich sollte man besser per ICP die Zeit messen wann an der Lichtschranke Flanken auftreten. So hat man wesentlich mehr Informationen. Wenn die Pulse nicht zu schnell kommen könnte es auch noch in basic gehen. Dann kann man sich immer noch entscheiden ob man die Geschwindigkeit oder die Position nachregeln will. Wenn man die Postion nachregelt, kommt man schon mit nur einem PD Regler aus. Das ganze wird dann ein Speziallfall eines Teilweise digitalen PLLs.

Che Guevara
08.12.2009, 18:38
Hallo Besserwessi,

danke für deine Antwort!
Ich habe bei einer Servo-Rad umdrehung ca. 200 impulse, da ich ein "zwischenzahnrad" ablese ;-)
Aber bei ICP brauche ich doch pro Rad einen "richtigen" timer, also beim mega32 den Timer1. dann bräuchte ich zwei mega32 für zwei Räder?!?!

Ich möchte die Geschwindigkeit nachregeln!

Gruß
Chris

Besserwessi
08.12.2009, 22:20
Auch wenn man 2 Kanäle haben will, braucht an zur Zeitmessung nicht unbedingt 2 Timer. Es wäre aber gut wenn man 2 ICP Einheiten hätte, was der Mega32 aber auch nicht hat. Der Timer wird ja einfach durchlaufen. Man kann sich aber helfen indem man die Zeitmessung in Software macht : Das Lichtschrankensignal erzeugt einen Interrupt, und man ließt dann im Interrupt den Zählerstand aus. Die Genauigkeit ist zwar nicht so gut wie mit ICP, sollte aber noch ausreichend sein. Die Zeiten sollten dann ja in der Größenordnung 10 ms liegen - für den µC schon eine relativ lange zeit. Wenn man will kann man für den einen Kanal ja ICP nutzen, muß es aber nicht.

Die Zeit für eine Periode und damit die Geschwindigkeit kriegt man dann aus der Differenz aufeinander folgender Zeiten.

Che Guevara
08.12.2009, 22:27
Und was ist, wenn ich einen Timeroverflow zwischen zwei Impulsen habe?

Gruß
Chris

Bammel
08.12.2009, 23:03
hallo,

ich habe es gerade mit hilfe von willa und oberallgeier (danke nochmal an dieser stelle) für meinen roboter eine geschwindigkeitsregelung auf die beine gestellen. das ganze ist ein PI-Regler und erfolgt in mm/s nun habe ich mit erfolg eine steigung von 70% in einer geschwindigkeit von 150mm/s rauf und runterfahren können. ohne regler kam der bot nicht rauf und raste runter! mehr zum algo werde ich morgen abend berichten! nun ist es zeit ins bett zu gehen.

gruß und gute nacht vom bammel

Besserwessi
08.12.2009, 23:22
Der Timerüberlauf ist kein Problem, solage zwischen 2 Interrupts höchstens 1 Überlauf auftreten kann. Wenn man bei einem 16 Bit Timer mit Word Variablen (16 Bit) rechnet und Überläufe ignoriert kommt das richtige Ergebnis raus.

Bammel
09.12.2009, 23:20
so hier hab ich eine erklärung niedergeschreiben

https://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=474658#474658

Che Guevara
10.12.2009, 15:34
habs mir gerade durchgelesen ... bin sehr begeistert von dem Video :-)
aber drei fragen habe ich noch dazu:
1. welchen wert hast du für ta? 0.00005?
2. kannst du mir das mit excel erklären oder soll ich willa fragen?
3. wenn der robi aber z.b. berab fährt, dann ist der benötigte pwm-wert zum wegfarhen kleiner!?! führt dies nicht zu problemen?

Gruß
Chris

Bammel
10.12.2009, 16:41
danke!

zu 1.: ta habe ich z.Z. garnicht berücksichtigt. muss man auch nicht umbedingt man kann auch direkt Ki mit Ta multiplizieren. willa und ich haben bei der ausarbeitung erstmal geschätze grobe werte eingetragen. die aber wie ich dann feststellte doch so erstmal gefühlsmäßig die besten sind.

zu 2.: bild im anhang! sollte zu meine beschreibung in meinem thread passen.

zu 3.: das siehst du richtig. bei mir fährt der roboter allerdings erst im leerlauf ab einem pwm-wert von 130 los. wenn er dann bergab fährt verringert er einfach den wert bis auf null bin ich nur gekommen wenn ich mit der hand die ketten extrem beschleunigt habe was allerdings im normalbetrieb nie vorkommen kann. wenn du im prinzip jedoch einen negativ pwm-wert bräuchtest könntest du entweder versuchen das ganze zu umgehen indem du eine kontroliert motorbremse durchführst (kurzschließen) oder "einfach" die drehrichtung der motoren umkehrst und gegensteuerst. mit der thematik beschäftigt oberallgeier sich gerade bei seinem miniD0. klings soweit ganz leicht soll aber doch recht kompliziert sein. daran würde ich an deiner stelle erstmal nicht denken.

gruß Bammel

Che Guevara
12.12.2009, 14:57
Sorry, dass ich mich jetzt erst wieder melde.

@Bammel
Ich hab mal deine Werte für PWM und Geschwindigkeit hergenommen und das mit Excel mal probiert, jedoch zeigt mir Excel ganz andere Formeln an, als bei dir. Vielleicht könntest du dir das ja mal ansehen und mir sagen, was ich falsch gemacht habe?! Wäre nett ^^

Gruß
Chris