Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter Test

Rutscherle 2 - Ein selbstbanancierender Elektroroller

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. 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 Bleiakkus 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. Die Entscheidung für Bleiakkus wurde bewusst getroffen. Eine kWh verteuert sich um ca. 50 cent wenn sie durch den Bleiakku geht bei Litium-Polymer-Akkus sind das ca. 5 Euro. Auch sind Bleiakkus beim Laden wesentlich unempfindlicher.

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

Motorregler
Kontrollerboard
Hochstromteil
Snubber

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
'********************************************************************************************

Hauptsteuerung

Sensoradapter

Tacho

Akkuladestecker

Software

Mechanik

Motorumbau


LiFePO4 Speicher Test