(→Rutscherle 2 - Ein selbstbanancierender Elektroroller) |
(→Rutscherle 2 - Ein selbstbanancierender Elektroroller) |
||
Zeile 1: | Zeile 1: | ||
= Rutscherle 2 - Ein selbstbanancierender Elektroroller = | = Rutscherle 2 - Ein selbstbanancierender Elektroroller = | ||
− | [[Bild:rutscherle2.jpg| | + | [[Bild:rutscherle2.jpg|right|thumb|Rutscherle 2]] |
Beim Rutscherle 2 handelt es sich um einen selbstbalancierenden Elektroroller mit großer Ähnlichkeit zum bekannten Segway. Es war und ist beabsichtigt, besser zu sein als das Original. Auch wenn das bisher noch nicht ganz gelungen ist. Dies ist kein kommerzielles Projekt und soll es auch nicht werden. | Beim Rutscherle 2 handelt es sich um einen selbstbalancierenden Elektroroller mit großer Ähnlichkeit zum bekannten Segway. Es war und ist beabsichtigt, besser zu sein als das Original. Auch wenn das bisher noch nicht ganz gelungen ist. Dies ist kein kommerzielles Projekt und soll es auch nicht werden. |
Version vom 4. August 2011, 16:26 Uhr
Inhaltsverzeichnis
Rutscherle 2 - Ein selbstbanancierender Elektroroller
Beim Rutscherle 2 handelt es sich um einen selbstbalancierenden Elektroroller mit großer Ähnlichkeit zum bekannten Segway. Es war und ist beabsichtigt, besser zu sein als das Original. Auch wenn das bisher noch nicht ganz gelungen ist. Dies ist kein kommerzielles Projekt und soll es auch nicht werden. Noch eine Warnung: Das ist kein ungefährliches Projekt. Schon kleine Programmierfehler können sehr schmerzhafte folgen haben.
Und so fährts: Rutscherle2 auf Youtube
Technische Daten
Antrieb
2 BLDC Felgenmotoren mit je 1000W/36V. Vom Hersteller in China direkt importiert. Mittlerweile gibt es auch in Europa vergleichbare Motoren zu kaufen. Die stammen zwar auch aus China, müssen jedoch nicht selbst importiert werden. Die Motoren sind im Lieferzustand nicht direkt verwendbar. Die Sensorik muss um 3 weitere Hallsensoren erweitert werden. Die bisherige Höchstgeschwindigkeit beträgt 27km/h.
Akkus
4 Akkus mit 12V/18AH von denen 3 in Reihe geschaltet sind für die Motoren, einer allein für die Steuerung und eine zukünftige Beleuchtung. Geladen werden die Akkus an einem handelsüblichen Kfz-Ladegerät. Die Reichweite beträgt auf jeden Fall mehr als 20km.
Elektronik
2 Motorregler mit Atmega 168/10Mhz sowie eine Hauptsteuerung mit einem Atmega 644/20Mhz. Zusätzlich noch ein Display von Display3000 als Tacho und Datenlogger. Beschleunigungssensor: ADXL335, Gyros: LISY300AL (ArduIMU Sensor Board - Six Degrees of Freedom)
Software
Die Software ist in Bascom geschrieben. Zeitkritische Teile in Assembler.
Mechanik
Der Mechanische Aufbau besteht nahezu komplett aus Aluminium. Dabei wurde darauf geachtet, dass alles mit einfachen Werkzeugen herstellbar ist. (Eine Ständerbohrmaschine sollte man schon haben.) Die Konstruktion ist so ausgelegt, dass so wenige Teile wie möglich hinter den Rädern hervorstehen. Dies verhindert Kratzer bei den ersten Fahrversuchen.
Sicherheitshinweis
Achtung! Bauen Sie sowas nur wenn Sie genau wissen was Sie machen. Es können an der Elektonik sehr hohe Ströme auftreten. Auch an den Motoren können, vor allem im Fehlerfall, sehr hohe Drehmomente entstehen. Beschweren Sie sich also nicht wenn Sie im Krankenhaus aufwachen. Sie haben es so gewollt.
Funktion
Die Funktion ist im groben recht banal. Im Prinzip macht das teil das gleiche wie jeder Mensch beim gehen. Kommt ein Mensch nach vorn aus dem Gleichgewicht macht er einen Schritt nach vorn. Entsprechend nach hinten. Hier wird das gleiche elektronisch nachbildet. Bewegt sich die Platform nach vorn wird nach vorn beschleunigt. Die genaue technische Umsetzung wird dann doch etwas aufwändiger. Die Regelung selbst erledigt ein PID-Regler. Danach kommen jedoch noch einige zusätzliche Faktoren die z.B. die Motorkennlinie ausgleichen sowie ungewollte Richtungsänderungen bei unebenen Oberflächen reduzieren. Ähnlich aufwendig wird es bei den Motorreglern. Eine reine Blockkommutierung wie bei solchen Motoren üblich ist nur auf glatten Untergründen brauchbar. Darum müssen die Motoren um zusätzliche Hallsensoren erweitert und mit Drehstrom oder genauer Drehspannung angesteuert werden.
Elektronik
Motorregler
Der Motorregler regelt natürlich den Motor. Zusätzlich misst und übermittelt der Motorregler auch Spannung, Strom und Fahrstrecke. Die Temperatur des Kühlkörpers wird ebenfalls gemessen und wenn nötig ein Lüfter zugeschaltet. Die Ansteuerung des Motors ist keine Blockkomutierung. Diese hat sich als untauglich gezeigt. Tatsächlich wird auf den 3 Leitungen eine vereinfachte Sinusspannung ausgegeben. Das reduziert die Drehmomentwelligkeit und das Rückspeisen der Energie beim Bremsen ist deutlich besser. Ob und wieweit sich dadurch der Motorwirkungsgrad ändert wurde bisher nicht gemessen. Die ganze Einheit wird vom PC aus über die Serielle Schnittstelle (5V) parametriert und kalibriert.
Der Motorregler ist auf zwei Platinen aufgebaut. Der Grund dafür ist die einfachere Herstellung der Platinen mit der Bügeleisenmethode sowie die räumliche Trennung der hohen Ströme vom Kontroller. Ob dies wegen der Störsicherheit wirklich notwendig ist wurde aus Kostengründen nie getestet. An der Stelle ist aber eine unnötige Sicherheit besser als eine vergessene. Die Verbindung zwischen den beiden Platinen bildet ein 16-Adriges Flachkabel. Programmierstecker und der Serielle Bus werden seitlich am Kontrollerboard gesteckt. Die Verbindung zu den Hallsensoren wird über ein 6-Adriges Flachkabel hergestellt. Zusätzlich zu den beiden Platinen gehört zum Motorregler auch die im Motor verbaute Sensorplatine. Auf dieser werden die Signale der drei zusätzlichen Hallsensoren zu einem Signal zusammengefasst. Nach einem Ausfall wurde auch noch eine Zusatzplatine mit den Snubbern und den Supressordioden nachgerüstet. Ohne diese ist eine Halbbrücke nach ca. 125km Fahrt ausgefallen.
Motorregler Software
'Version 19 $prog &HFF , &HFF , &HD4 , &HF9 'Fusebits $regfile = "m168def.dat" $crystal = 10000000 $baud = 57600 $hwstack = 32 $swstack = 10 $framesize = 40 Declare Sub Setspeed Declare Sub Pwm_start Declare Sub Pwm_stop Config Portc.0 = Input 'UBAT Config Portc.1 = Input 'USHUNT Config Portc.2 = Input 'TEMP Config Portc.3 = Output 'LED1 Config Portc.4 = Output 'Lüfter Config Portc.5 = Input 'Jumper1 Config Portd.2 = Input 'Hall_C Config Portd.3 = Output 'A+ Config Portd.4 = Input 'Hall_B Config Portd.5 = Output 'C+ Config Portd.6 = Output 'C- Config Portd.7 = Input 'Hall_A Config Portb.0 = Input 'Hall_D Config Portb.1 = Output 'B- Config Portb.2 = Output 'B+ Config Portb.3 = Output 'A- Config Portb.4 = Output 'LED2 Config Portb.5 = Input 'Unbelegt (SCK) Hall_a Alias Pind.7 'gelb Hall_b Alias Pind.4 'blau Hall_c Alias Pind.2 'Grün Hall_d Alias Pinb.0 Led1 Alias Portc.3 Led2 Alias Portb.4 Fan Alias Portc.4 Jumper1 Alias Pinc.5 Dim Uzu As Integer At $100 Dim Izu As Integer At $102 Dim Ausgabeticks As Integer At $104 'Anzahl Kommutieren zwischen Seriellen Telegrammen Dim Temperatur As Integer At $106 ' Dim Drehzahl As Integer At $108 'Drehzahl Dim M1 As Byte At $100 Overlay Dim M2 As Byte At $101 Overlay Dim M3 As Byte At $102 Overlay Dim M4 As Byte At $103 Overlay Dim M5 As Byte At $104 Overlay Dim M6 As Byte At $105 Overlay Dim M7 As Byte At $106 Overlay Dim M8 As Byte At $107 Overlay Dim M9 As Byte At $108 Overlay Dim M10 As Byte At $109 Overlay Dim Kalibrierwert As Integer At $10a Dim Kal(2) As Byte At $10a Overlay Dim A(15) As Byte At $10c Dim S(12) As Byte At $11b Dim Sinus(12) As Byte At $127 Dim Richtung(255) As Byte At $133 Dim Motorposition As Byte At $232 Dim Istrichtung As Integer At $233 Dim Altrichtung As Integer At $235 Dim Aposition As Byte At $237 Dim Zposition As Byte At $238 Dim Zwangskommutieren As Byte At $239 Dim Temp As Word At $23a Dim Fancount As Word At $23c Dim Motoradresse As Byte At $23e Dim Vwinkel As Byte At $23f Dim Rwinkel As Byte At $240 Dim Ticks As Integer At $241 Dim N As Byte At $243 Dim Notaus As Byte At $244 Dim Loopcount As Word At $245 Dim Sollrichtung As Byte At $247 Dim Altsollrichtung As Byte At $248 Dim Sollspeed As Byte At $249 Dim Altsollspeed As Byte At $24a Dim Bdummy As Byte At $24b Dim Intbdummy As Byte At $24c Dim Intidummy As Integer At $24d Dim Sdummy As Single At $24f Dim Idummy1 As Integer At $253 Dim Idummy2 As Integer At $255 Dim Uw As Word At $257 Dim Iw As Word At $259 Dim Uwsum As Long At $25b Dim Iwsum As Long At $25f Dim Wcount As Long At $263 Dim Uoffset As Single At $267 Dim Ufaktor As Single At $26b Dim Ioffset As Single At $26f Dim Ifaktor As Single At $273 Dim Ep0 As Byte At $277 Dim Ep1 As Byte At $278 Dim Ep2 As Byte At $279 Dim Ep3 As Byte At $27a Dim Ep4 As Byte At $27b Dim Ep5 As Byte At $27c Dim Ta As Byte At $27d Dim Tb As Byte At $27e Dim Tc As Byte At $27f Dim Fehler As Byte At $280 Sollspeed = 0 Pwm_stop 'Erstmal alles auschalten 'Variablen für die Richtungserkennung vorbelegen 'Diese Variante frisst zwar viel Arbeitsspeicher, ist aber sehr schnell For N = 1 To 15 A(n) = 0 Next For N = 1 To 255 Richtung(n) = 2 Next If Jumper1 = 0 Then 'R Motoradresse = 82 A(12) = 12 A(4) = 11 A(6) = 10 A(14) = 9 A(10) = 8 A(2) = 7 A(3) = 6 A(11) = 5 A(9) = 4 A(1) = 3 A(5) = 2 A(13) = 1 Richtung(21) = 3 Richtung(93) = 3 Richtung(220) = 3 Richtung(196) = 3 Richtung(70) = 3 Richtung(110) = 3 Richtung(234) = 3 Richtung(162) = 3 Richtung(35) = 3 Richtung(59) = 3 Richtung(185) = 3 Richtung(145) = 3 Richtung(81) = 1 Richtung(25) = 1 Richtung(155) = 1 Richtung(179) = 1 Richtung(50) = 1 Richtung(42) = 1 Richtung(174) = 1 Richtung(230) = 1 Richtung(100) = 1 Richtung(76) = 1 Richtung(205) = 1 Richtung(213) = 1 Else Motoradresse = 76 'L A(11) = 1 A(3) = 2 A(1) = 3 A(9) = 4 A(13) = 5 A(5) = 6 A(4) = 7 A(12) = 8 A(14) = 9 A(6) = 10 A(2) = 11 A(10) = 12 Richtung(236) = 3 Richtung(196) = 3 Richtung(69) = 3 Richtung(93) = 3 Richtung(217) = 3 Richtung(145) = 3 Richtung(19) = 3 Richtung(59) = 3 Richtung(186) = 3 Richtung(162) = 3 Richtung(38) = 3 Richtung(110) = 3 Richtung(42) = 1 Richtung(171) = 1 Richtung(179) = 1 Richtung(49) = 1 Richtung(25) = 1 Richtung(157) = 1 Richtung(213) = 1 Richtung(84) = 1 Richtung(76) = 1 Richtung(206) = 1 Richtung(230) = 1 Richtung(98) = 1 End If 'AD-Wandler einstellen Config Adc = Single , Prescaler = Auto , Reference = Off Start Adc '<Test Hallsensoren> Fehler = 1 Fan = 1 While Fehler = 1 Fehler = 0 Motorposition = 0 Motorposition.0 = Hall_a Motorposition.1 = Hall_b Motorposition.2 = Hall_c Motorposition.3 = Hall_d If Motorposition = 0 Then Fehler = 1 'Stecker nicht gesteckt If Motorposition > 0 Then If A(motorposition) = 0 Then Fehler = 1 'Das währe eine Motorposition die es nicht gibt! End If If Fehler = 1 Then Toggle Led1 Toggle Led2 Waitms 500 End If Wend '</Test Hallsensoren> On Timer2 Update_pwm Nosave 'Pin-Change Interrupt einstellen: Pcmsk2 = &B10010100 Pcmsk1 = &B00000000 Pcmsk0 = &B00000001 Pcicr = &B00000101 On Pcint2 Kommutieren Nosave On Pcint0 Kommutieren Nosave Readeeprom Uoffset , 1 Readeeprom Ufaktor , 5 Readeeprom Ioffset , 9 Readeeprom Ifaktor , 13 'Angepasste Sinuskurve aus dem EEprom laden For N = 1 To 12 Bdummy = N + 16 Readeeprom Sinus(n) , Bdummy Next 'Voreilwinkel: Readeeprom Vwinkel , 29 Readeeprom Rwinkel , 30 If Ufaktor = 0 Then Ufaktor = 1 If Ifaktor = 0 Then Ifaktor = 1 On Urxc Datenempfang Nosave Enable Urxc Enable Interrupts Fancount = 15000 'Lüfter erstmal einschalten Do Led1 = 0 '<Messen> Uw = Getadc(0) Uwsum = Uwsum + Uw Iw = Getadc(1) Iwsum = Iwsum + Iw Incr Wcount Temp = Getadc(2) '</Messen> '<Serielle Telegramme abarbeiten> If Ep0 = 13 Then If Ep5 = 13 Then If Ep1 = Motoradresse Then '"R", "L" Disable Urxc $asm lds R24,{EP1} LDs R25,{EP2} add R24,R25 LDs R25,{EP3} add R24,R25 STS {Bdummy},R24 $end Asm If Bdummy = Ep4 Then 'Die Prüfsumme stimmt Led1 = 1 Pcicr = &B00000000 'Kommutieren kurz deaktivieren, weil sonst die Ticks während dem Zugriff geändert werden könnten Ausgabeticks = Ticks Ticks = 0 Pcicr = &B00000101 $asm lds R24,{M1} LDs R25,{M2} add R24,R25 LDs R25,{M3} add R24,R25 LDs R25,{M4} add R24,R25 LDs R25,{M5} add R24,R25 LDs R25,{M6} add R24,R25 STS {Bdummy},R24 'Antwort ausgeben 'Print Chr(m1) ; Chr(m2) ; Chr(m3) ; Chr(m4) ; Chr(m5) ; Chr(m6) ; Chr(bdummy) ; Chr(13) ; LdS R24,{M1} STS udr,R24 Warten1: LDS R24,UCSR0A BST R24,5 Brtc warten1 LDS R24,{M2} STS udr,R24 Warten2: LDS R24,UCSR0A BST R24,5 Brtc warten2 lds R24,{M3} STS udr,R24 Warten3: LDS R24,UCSR0A BST R24,5 Brtc warten3 LDS R24,{M4} STS udr,R24 Warten4: LDS R24,UCSR0A BST R24,5 Brtc warten4 LDS R24,{M5} STS udr,R24 Warten5: LDS R24,UCSR0A BST R24,5 Brtc warten5 LDS R24,{M6} STS udr,R24 Warten6: LDS R24,UCSR0A BST R24,5 Brtc warten6 LDS R24,{bdummy} STS udr,R24 Warten7: LDS R24,UCSR0A BST R24,5 Brtc warten7 LDi R24,13 STS udr,R24 Warten8: LDS R24,UCSR0A BST R24,5 Brtc warten8 $end Asm If Ep2 < 3 Then Notaus = 0 Loopcount = 0 Sollrichtung = Ep2 Sollspeed = Ep3 If Sollrichtung = 2 Then Sollrichtung = 1 Notaus = 1 Loopcount = 250 Sollspeed = 0 End If Setspeed '<Messwerte berechnen> 'Messwerte werden hier berechnet, weil genau jetzt 1/100s Zeit ist. 'Spannung berechnen Sdummy = Uwsum / Wcount Sdummy = Sdummy - Uoffset Sdummy = Sdummy * Ufaktor Uzu = Int(sdummy) Uwsum = 0 'Strom berechnen Sdummy = Iwsum / Wcount Sdummy = Sdummy - Ioffset Sdummy = Sdummy * Ifaktor Izu = Int(sdummy) Iwsum = 0 Wcount = 0 '</Messwerte berechnen> Else Select Case Ep2 Case 3 'Sinus(1) empfangen Sinus(1) = Ep3 Writeeeprom Sinus(1) , 17 Case 4 'Sinus(2) empfangen Sinus(2) = Ep3 Writeeeprom Sinus(2) , 18 Case 5 'Sinus(3) empfangen Sinus(3) = Ep3 Writeeeprom Sinus(3) , 19 Case 6 'Sinus(4) empfangen Sinus(4) = Ep3 Writeeeprom Sinus(4) , 20 Case 7 'Sinus(5) empfangen Sinus(5) = Ep3 Writeeeprom Sinus(5) , 21 Case 8 'Sinus(6) empfangen Sinus(6) = Ep3 Writeeeprom Sinus(6) , 22 Case 9 'Sinus(7) empfangen Sinus(7) = Ep3 Writeeeprom Sinus(7) , 23 Case 10 'Sinus(8) empfangen Sinus(8) = Ep3 Writeeeprom Sinus(8) , 24 Case 11 'Sinus(9) empfangen Sinus(9) = Ep3 Writeeeprom Sinus(9) , 25 Case 12 'Sinus(10) empfangen Sinus(10) = Ep3 Writeeeprom Sinus(10) , 26 Case 13 'Sinus(11) empfangen Sinus(11) = Ep3 Writeeeprom Sinus(11) , 27 Case 14 'Sinus(12) empfangen Sinus(12) = Ep3 Writeeeprom Sinus(12) , 28 Case 15 'Spannung Kalibrieren (Byte 1) Kal(1) = Ep3 Case 16 'Spannung Kalibrieren (Byte 2) Kal(2) = Ep3 Sdummy = Uwsum / Wcount Ufaktor = Kalibrierwert / Sdummy Writeeeprom Ufaktor , 5 Uoffset = 0 'Schaltungsbedingt Writeeeprom Uoffset , 1 Case 17 'Strom Kalibrieren (Byte 1) Kal(1) = Ep3 Case 18 'Strom Kalibrieren Byte (2) Kal(2) = Ep3 Sdummy = Iwsum / Wcount If Kalibrierwert = 0 Then 'Das ist der Offset Ioffset = Sdummy + 1 Writeeeprom Ioffset , 9 Else 'Jetzt den Faktor berechnen Sdummy = Sdummy - Ioffset Ifaktor = Kalibrierwert / Sdummy Writeeeprom Ifaktor , 13 End If Case 19 Vwinkel = Ep3 Writeeeprom Vwinkel , 29 Case 20 Rwinkel = Ep3 Writeeeprom Rwinkel , 30 End Select End If $asm 'Empfangspuffer löschen LDI R24,0 sTS {EP1},R24 sTS {EP2},R24 sTS {EP3},R24 sTS {EP4},R24 $end Asm End If Enable Urxc End If End If End If '</Serielle Telegramme abarbeiten> '<Lüfter schalten> If Temp > 740 Then Fancount = 15000 'Schaltet den Lüfter ein If Fancount > 0 Then Fan = 1 Else Fan = 0 End If If Fancount > 0 Then Decr Fancount '</Lüfter schalten> 'Notaus mit Freilauf wenn keine Nachricht von Seriell If Loopcount < 50 Then 'Das sind schätzungsweise 0.1s Led2 = 1 Notaus = 0 Incr Loopcount Else Led2 = 0 Notaus = 1 Sollspeed = 0 Setspeed End If Loop '******************************************************************************************** Kommutieren: $asm PUSH R10 PUSH R11 PUSH R16 PUSH R17 PUSH R20 PUSH R21 PUSH R24 PUSH R26 PUSH R27 IN R24,sreg PUSH R24 clr R16 lds R17, $0023 BST R17,0 BLD R16,3 LDS R17, $0029 BST R17,2 bld R16,2 BST R17,4 bld R16,1 BST R17,7 bld R16,0 lds R17,{aposition} !swap R17 andi R17,&B11110000 add R17,R16 STS {Aposition},R17 CLR R17 LDI R26,$0B LDI R27,$01 ADD R26,R16 ADC R27,R17 LD R24,X LDS R16,{Sollrichtung} CPI R16,0 BREQ Sollrichtungnull Jmp Sollrichtungnichtnull Sollrichtungnull: LDS R20,{Vwinkel} Add R24,R20 JMP Richtunggesetzt Sollrichtungnichtnull: LDS R20,{Rwinkel} Add R24,R20 Richtunggesetzt: CPI R24,$0D BRCC Istgroesser13_1 JMP Istkleiner13_1 Istgroesser13_1: SUBI R24,$0C Istkleiner13_1: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Ta},R16 subi R24,$fc CPI R24,$0D BRCC Istgroesser13_2 JMP Istkleiner13_2 Istgroesser13_2: SUBI R24,$0C Istkleiner13_2: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Tc},R16 subi R24,$fc CPI R24,$0D BRCC Istgroesser13_3 JMP Istkleiner13_3 Istgroesser13_3: SUBI R24,$0C Istkleiner13_3: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Tb},R16 lds R10,{Aposition} CLR R11 LDI R26,$32 LDI R27,$01 ADD R26,R10 ADC R27,R11 LD R16,X+ CLR R17 LDI R20,$02 LDI R21,$00 !Sub R16 , R20 SBC R17,R21 LDI R26,$33 LDI R27,$02 ST X+,R16 ST X,R17 LDI R26,$41 LDI R27,$02 LD R16,X+ LD R17,X LDI R26,$33 LDI R27,$02 LD R20,X+ LD R21,X ADD R16,R20 ADC R17,R21 LDI R26,$41 LDI R27,$02 ST X+,R16 ST X,R17 LDS R24,timsk2 ORI R24,$01 STS timsk2,R24 POP R24 !Out sreg , R24 POP R27 POP R26 POP R24 POP R21 POP R20 POP R17 POP R16 POP R11 POP R10 $end Asm Return '******************************************************************************************** '******************************************************************************************** Update_pwm: $asm PUSH R24 IN R24,sreg PUSH R24 lds R24,{Ta} STS ocr2a,R24 STS ocr2b,R24 LDS R24,{Tb} STS ocr1al,R24 STS ocr1bl,R24 lds R24,{Tc} !OUT ocr0a,R24 !OUT ocr0b,R24 LDS R24,timsk2 ANDI R24,$FE STS timsk2,R24 POP R24 !OUT sreg,R24 POP R24 $end Asm Return '******************************************************************************************** '******************************************************************************************** Datenempfang: $asm PUSH R24; IN R24, SREG; PUSH R24; LDS R24,{EP1} STS {EP0},R24 LDS R24,{EP2} STS {EP1},R24 LDS R24,{EP3} STS {EP2},R24 LDS R24,{EP4} STS {EP3},R24 LDS R24,{EP5} STS {EP4},R24 IN R24,UDR STs {EP5},R24 POP R24; Out Sreg , R24; POP R24; $end Asm Return '******************************************************************************************** '******************************************************************************************** Sub Setspeed If Notaus = 1 Then Pwm_stop Sollspeed = 0 For N = 1 To 12 S(n) = 0 Next Else For N = 1 To 12 Idummy1 = Sollspeed * Sinus(n) Idummy1 = Idummy1 / 100 S(n) = Idummy1 Next If Tccr0a = 0 Then 'Wenn die PWM aus ist Pwm_start End If '<Zwangskommutieren> Zwangskommutieren = 0 If Sollrichtung <> Altsollrichtung Then Zwangskommutieren = 1 If Sollspeed <> Altsollspeed Then Zwangskommutieren = 1 If Zwangskommutieren = 1 Then Pcicr = &B00000000 'Den Eigentlichen Kommutierinterrupt abschalten $asm clr R16 lds R17, $0023 BST R17,0 BLD R16,3 LDS R17, $0029 BST R17,2 bld R16,2 BST R17,4 bld R16,1 BST R17,7 bld R16,0 lds R17,{aposition} !swap R17 andi R17,&B11110000 add R17,R16 STS {Aposition},R17 CLR R17 LDI R26,$0B LDI R27,$01 ADD R26,R16 ADC R27,R17 LD R24,X LDS R16,{Sollrichtung} CPI R16,0 BREQ Sollrichtungnullz Jmp Sollrichtungnichtnullz Sollrichtungnullz: LDS R20,{Vwinkel} Add R24,R20 JMP Richtunggesetztz Sollrichtungnichtnullz: LDS R20,{Rwinkel} Add R24,R20 Richtunggesetztz: CPI R24,$0D BRCC Istgroesser13_1z JMP Istkleiner13_1z Istgroesser13_1z: SUBI R24,$0C Istkleiner13_1z: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Ta},R16 subi R24,$fc CPI R24,$0D BRCC Istgroesser13_2z JMP Istkleiner13_2z Istgroesser13_2z: SUBI R24,$0C Istkleiner13_2z: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Tc},R16 subi R24,$fc CPI R24,$0D BRCC Istgroesser13_3z JMP Istkleiner13_3z Istgroesser13_3z: SUBI R24,$0C Istkleiner13_3z: CLR R20 Ldi R26,$1a LDI R27,$01 ADD R26,R24 ADC R27,R20 LD R16,X STS {Tb},R16 $end Asm Pcicr = &B00000101 'Den Eigentlichen Kommutierinterrupt einschalten 'Nur Overflow Interrupt (Seite 105) Timsk2.toie2 = 1 Toggle Led2 End If '</Zwangskommutieren> End If Altsollrichtung = Sollrichtung Altsollspeed = Sollspeed End Sub '******************************************************************************************** '******************************************************************************************** Sub Pwm_start Disable Interrupts 'Damit die Timer auch wirklich synchron laufen Tccr0a = 161 Tccr0b = 1 Ocr0a = 0 Ocr0b = 0 Tccr1a = 161 Tccr1b = 1 Ocr1ah = 0 Ocr1al = 0 Ocr1bh = 0 Ocr1bl = 0 Tccr2a = 161 Tccr2b = 1 Ocr2a = 0 Ocr2b = 0 Tcnt0 = 0 'Timer Startwert, wegen Synchron Tcnt1 = 6 'Timer Startwert, wegen Synchron Tcnt2 = 9 'Timer Startwert, wegen Synchron Enable Interrupts End Sub '******************************************************************************************** '******************************************************************************************** Sub Pwm_stop Tccr0a = 0 Tccr0b = 0 Ocr0a = 0 Ocr0b = 0 Tccr1a = 0 Tccr1b = 0 Ocr1ah = 0 Ocr1al = 0 Ocr1bh = 0 Ocr1bl = 0 Tccr2a = 0 Tccr2b = 0 Ocr2a = 0 Ocr2b = 0 'alles aus Portd.3 = 0 'A+ Portb.3 = 1 'A- Portb.2 = 0 'B+ Portb.1 = 1 'B- Portd.5 = 0 'C+ Portd.6 = 1 'C- End Sub '********************************************************************************************