Aus RN-Wissen.de
Wechseln zu: Navigation, Suche
Rasenmaehroboter fuer schwierige und grosse Gaerten im Test

(Listrik01 - Ein selbstbalancierendes Elektroeinrad)
(Schaltbild)
 
(13 dazwischenliegende Versionen desselben Benutzers werden nicht angezeigt)
Zeile 5: Zeile 5:
  
  
Beim Listrik01 handelt es sich um einen selbstbalancierenden Elektroroller. Die Elektronik basiert auf den Veröffentlichungen des Rutscherle 2 [http://www.rn-wissen.de/index.php/Rutscherle_-_selbstbalancierender_Elektroroller]. Die Schaltung wurde verändert um I2C Gyro und Accelerometer anschließen zu können. Die Listing wurden außerdem umfangreicher kommentiert.
+
Beim Listrik01 handelt es sich um einen selbstbalancierenden Elektroroller. Die Elektronik basiert auf den Veröffentlichungen des [http://www.rn-wissen.de/index.php/Rutscherle_-_selbstbalancierender_Elektroroller Rutscherle 2]. Die Schaltung wurde verändert um I2C Gyro und Accelerometer anschließen zu können. Die Listing wurden außerdem umfangreicher kommentiert.
  
 
===Antrieb===
 
===Antrieb===
Zeile 20: Zeile 20:
  
 
===Elektronik===
 
===Elektronik===
[[Bild:IMGP0416small.JPG|right|thumb|Platinen]]
 
  
 
Motorregler mit Atmega 168A sowie eine Hauptsteuerung mit einem Atmega 644PA. Ein Display von Display3000 als Tacho (und Datenlogger). Siehe Stückliste.
 
Motorregler mit Atmega 168A sowie eine Hauptsteuerung mit einem Atmega 644PA. Ein Display von Display3000 als Tacho (und Datenlogger). Siehe Stückliste.
Zeile 27: Zeile 26:
  
 
Die Software ist in Basic mit BASCOM geschrieben. Zeitkritische Teile in Assembler.  
 
Die Software ist in Basic mit BASCOM geschrieben. Zeitkritische Teile in Assembler.  
Siehe Link oben zum Rutscherle 2 [http://www.rn-wissen.de/index.php/Rutscherle_-_selbstbalancierender_Elektroroller].
+
Siehe Link oben zum [http://www.rn-wissen.de/index.php/Rutscherle_-_selbstbalancierender_Elektroroller Rutscherle 2].
  
 
==Sicherheitshinweis==
 
==Sicherheitshinweis==
Zeile 36: Zeile 35:
  
 
==Programme==
 
==Programme==
'''Motorcontroller.bas (BASCOM)'''
 
<pre>
 
'******************Listrik01 Motorsteuerung, Version 01 **********************
 
  
'Es gibt keine Stromregelung, sondern eine Lageregelung im Hauptcontroller
+
[http://www.listrik.de/html/freeware.html Motorcontroller.bas (BASCOM)]
  
'LED1 blinkt mit gültigem seriellen Telegramm
+
[http://www.listrik.de/html/freeware.html Hauptsteuerung.bas (BASCOM)]
  
'LED2 blinkt wenn Zwangskommutierung
+
[http://www.listrik.de/html/freeware.html Display3000.bas (BASCOM)]
'LED2 dauerlicht wenn serielle Verbindung fehlt, d.h. Not Halt
+
  
'LED1 und LED2 blinken abwechselnd mit 1Hz für 3 Sekunden während CPU Anlauf
 
 
'LED1 und LED2 blinken mit 2Hz wenn Hallstecker nicht gesteckt ist.
 
'              Ausserdem antwortet der Controller jetzt nicht auf Telegramme.
 
 
'LockBit, FuseBit , FuseBitHigh , FuseBitExtended
 
'$prog &HFF , &HF9 , &HDF , &HF6      'Fusebits 168A CPU
 
 
'Use AMTEL Studio / Fuses Menu instead to set fusebits
 
'BOOTSZ = 1024W_1C00
 
'BOOTRST = unchecked
 
'RSTDISBL = unchecked
 
'DWEN = unchecked
 
'SPIEN = checked
 
'WDTON = unchecked
 
'EESAVE = unchecked
 
'BODLEVEL = unchecked
 
'CKDIV8 = unchecked
 
'CKOUT = unchecked
 
'SUT_CKSEL = EXTFSXTAL_1KCK_14CK_4MS1
 
 
$regfile = "m168def.dat"      'ATMEGA168A CPU
 
$crystal = 11059200
 
$baud = 57600
 
$hwstack = 32
 
$swstack = 20
 
$framesize = 40
 
 
Const _pcicr = &B00000101      'Bit0 = PCIE0 = Port B0..B7
 
                                'Bit2 = PCIE2 = Port D0..D7
 
 
Const Numhall = 3      '<<<<<<<<<< TEST, Normalerweise = 4
 
Const Pclink = 1      '<<<<<<<<<< TEST, Normalerweise = 0, Sie Delphi
 
 
Declare Sub Setspeed
 
Declare Sub Pwm_start
 
Declare Sub Pwm_stop
 
 
Config Portb.0 = Input      'Hall_D
 
Config Portb.1 = Output      'B-
 
Config Portb.2 = Output      'B+
 
Config Portb.3 = Output      'A-(MOSI)
 
Config Portb.4 = Output      'LED2 (MISO)
 
Config Portb.5 = Input      'SCK
 
'      PortB.6                XTAL
 
'      PortB.7                XTAL
 
 
Config Portc.0 = Input      'UBatterie
 
Config Portc.1 = Input      'I-Ist
 
Config Portc.2 = Input      'Kühlkörper Temperatur
 
Config Portc.3 = Output      'LED1
 
Config Portc.4 = Output      'Lüfter
 
Config Portc.5 = Input      'Adress Jumper
 
'      PortC.6                Reset
 
'      PortC.7                nicht rausgeführt
 
 
'      PortD.0                RxD
 
'      PortD.1                TxD
 
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
 
 
Hall_a Alias Pind.7
 
Hall_b Alias Pind.4
 
Hall_c Alias Pind.2
 
Hall_d Alias Pinb.0
 
Led1 Alias Portc.3
 
Led2 Alias Portb.4
 
Fan Alias Portc.4
 
Adrjumper Alias Pinc.5
 
 
'A-Werte stellen die Rotorposition in Abhängigkeit der Halleingänge dar
 
'Siehe Exceltabelle "Rotorposition Array A().xls"
 
Dim A(15) As Byte At $100
 
 
'S-Werte stellen die aktuelle Soll PWM-Breite dar
 
Dim S(12) As Byte At $10f
 
 
'1 = Links,  2 = Leerlauf,  3 = Not Aus
 
Dim Richtung(255) As Byte At $11b
 
 
'IstRichtung-Werte stellen den 0..2, siehe Zeile oberhalb
 
Dim Istrichtung As Integer At $21a
 
 
'Ticks-Werte stellen die Anzahl verbrauchter Ticks während eine Do..Loop dar
 
Dim Ticks As Integer At $221
 
 
'Anzahl Kommutierungen zwischen seriellen Telegrammen
 
Dim Uzu As Integer      'Netzspannung
 
Dim M1 As Byte At Uzu + 0 Overlay
 
Dim M2 As Byte At Uzu + 1 Overlay
 
 
Dim Izu As Integer      'Motorstrom
 
Dim M3 As Byte At Izu + 0 Overlay
 
Dim M4 As Byte At Izu + 1 Overlay
 
 
Dim Ausgabeticks As Integer      'Anzahl Ticks für ein Do ... Loop
 
Dim M5 As Byte At Ausgabeticks + 0 Overlay
 
Dim M6 As Byte At Ausgabeticks + 1 Overlay
 
 
Dim Temperatur As Integer      'Kühlkörpertemperatur
 
Dim M7 As Byte At Temperatur + 0 Overlay
 
Dim M8 As Byte At Temperatur + 1 Overlay
 
 
Dim Drehzahl As Integer      'Drehzahl
 
Dim M9 As Byte At Drehzahl + 0 Overlay
 
Dim M10 As Byte At Drehzahl + 1 Overlay
 
 
Dim Kalibrierwert As Integer
 
Dim Kal(2) As Byte At Kalibrierwert + 0 Overlay
 
 
Dim Sinus(12) As Byte
 
Dim Motorposition As Byte
 
Dim Altrichtung As Integer
 
Dim Aposition As Byte
 
Dim Zposition As Byte
 
Dim Zwangskommutieren As Byte
 
Dim Temp As Word
 
Dim Motoradresse As Byte
 
Dim Vwinkel As Byte
 
Dim Rwinkel As Byte
 
Dim N As Byte
 
Dim Notaus As Byte
 
Dim Loopcount As Word
 
Dim Sollrichtung As Byte
 
Dim Altsollrichtung As Byte
 
Dim Sollspeed As Byte
 
Dim Altsollspeed As Byte
 
Dim Bdummy As Byte
 
Dim Intbdummy As Byte
 
Dim Intidummy As Integer
 
Dim Sdummy As Single
 
Dim Idummy1 As Integer
 
Dim Idummy2 As Integer
 
Dim Uw As Word
 
Dim Iw As Word
 
Dim Uwsum As Long
 
Dim Iwsum As Long
 
Dim Wcount As Long
 
Dim Fancount As Long
 
Dim Uoffset As Single
 
Dim Ufaktor As Single
 
Dim Ioffset As Single
 
Dim Ifaktor As Single
 
Dim Empfpuffer(6) As Byte      'Empfangspuffer
 
Dim Ta As Byte
 
Dim Tb As Byte
 
Dim Tc As Byte
 
Dim Fehler As Byte
 
 
Dim Errorword As Word
 
Dim Errorword1 As Byte At Errorword + 0 Overlay
 
Dim Errorword2 As Byte At Errorword + 1 Overlay
 
 
'Integer bzw. Word (2Byte) = %
 
'Single (4Byte)            = !
 
'Double (8Byte)            = #
 
'Long (4Byte)              = & ==> 32Bit Integer
 
'Byte (1Byte)              = ohne Zusatz
 
 
$eeprom      'wird nicht benutzt
 
U_offset:
 
  Data 0.0!      'Single
 
U_faktor:
 
  Data 1.0!      'Single
 
I_offset:
 
  Data 0.0!      'Single
 
I_faktor:
 
  Data 1.0!      'Single
 
V_winkel:
 
  Data 0      'Byte
 
R_winkel:
 
  Data 0      'Byte
 
Sinus_12:      'Sinus mit 4 Hallgebern
 
  Data 0 , 0 , 33 , 66 , 100 , 100 , 100 , 100 , 66 , 33 , 0 , 0
 
Sinus_6:      'Sinus mit 3 Hallgebern
 
  Data 0 , 33 , 66 , 100 , 66 , 33
 
$data
 
 
Sollspeed = 0
 
Pwm_stop      'Erstmal alles auschalten
 
 
For N = 1 To 15
 
A(n) = 0
 
Next
 
 
'Variablen für die Richtungserkennung vorbelegen
 
'Diese Variante frisst zwar viel Arbeitsspeicher, ist aber sehr schnell
 
For N = 1 To 255
 
Richtung(n) = 2
 
Next
 
 
If Adrjumper = 0 Then      'Rechter Motor
 
Motoradresse = 82
 
#if Numhall = 3      'Anzahl Hallsensoren
 
  A(5) = 1
 
  A(1) = 2
 
  A(3) = 3
 
  A(2) = 4
 
  A(6) = 5
 
  A(4) = 6
 
 
  Richtung(21) = 3
 
  Richtung(49) = 3
 
  Richtung(35) = 3
 
  Richtung(98) = 3
 
  Richtung(70) = 3
 
  Richtung(84) = 3
 
 
  Richtung(69) = 1
 
  Richtung(81) = 1
 
  Richtung(19) = 1
 
  Richtung(50) = 1
 
  Richtung(38) = 1
 
  Richtung(100) = 1
 
 
#else
 
  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
 
#endif
 
Else
 
Motoradresse = 76      'Linker Motor
 
#if Numhall = 3      'Anzahl Hallsensoren
 
  A(3) = 1
 
  A(1) = 2
 
  A(5) = 3
 
  A(4) = 4
 
  A(6) = 5
 
  A(2) = 6
 
 
  Richtung(35) = 3
 
  Richtung(49) = 3
 
  Richtung(21) = 3
 
  Richtung(84) = 3
 
  Richtung(70) = 3
 
  Richtung(98) = 3
 
 
  Richtung(19) = 1
 
  Richtung(81) = 1
 
  Richtung(69) = 1
 
  Richtung(100) = 1
 
  Richtung(38) = 1
 
  Richtung(50) = 1
 
#else
 
  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
 
#endif
 
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
 
#if Numhall = 3      'Anzahl Hallsensoren
 
  Motorposition.3 = 0
 
#else
 
  Motorposition.3 = Hall_d
 
#endif
 
If Motorposition = 0 Then Fehler = 1      'Stecker nicht gesteckt
 
If Motorposition > 0 Then
 
  'Das währe eine Motorposition die es nicht gibt
 
  If A(motorposition) = 0 Then Fehler = 1
 
End If
 
If Fehler = 1 Then
 
  Toggle Led1
 
  Toggle Led2
 
  Waitms 250      '==> 2Hz
 
End If
 
Wend
 
'</Test Hallsensoren>
 
 
On Timer2 Update_pwm Nosave
 
 
'Pin-Change Interrupt einstellen: (Hall Impulse)
 
Pcmsk2 = &B10010100      'Hall A, B, C
 
Pcmsk1 = &B00000000
 
Pcmsk0 = &B00000001      'Hall D
 
Pcicr = _pcicr
 
 
'Wenn sich das Hallsignal ändert, wird kommutiert
 
On Pcint2 Kommutieren Nosave
 
On Pcint0 Kommutieren Nosave
 
 
'EEPROM mit dem Programm Motorcontroller_EEPROM.bas vorbesetzen
 
' Datenreihenfolge dort ist ab Byte(1):
 
'    U_offset, U_faktor, I_offset, I_faktor im Single Format
 
'    Voreilwinkel, Nacheilwinkel im Byte Format
 
'Sinuskurve 12 Werte im Byte Format für 4 Hall Sensoren
 
'Sinuskurve 6 Werte im Byte Format für 3 Hall Sensoren
 
 
'Readeeprom Uoffset , 1
 
Uoffset = 0
 
 
'Readeeprom Ufaktor , 5
 
Ufaktor = 5.37109375      'Siehe Hardwarezeichnung für Berechnung
 
 
'Readeeprom Ioffset , 9
 
Ioffset = 512      '2,5V
 
 
'Readeeprom Ifaktor , 13
 
Ifaktor = 7.8125      'Siehe Hardwarezeichnung für Berechnung
 
 
'Voreilwinkel:
 
'Readeeprom Vwinkel , 17
 
Vwinkel = 0
 
 
'Readeeprom Rwinkel , 18
 
Rwinkel = 0
 
 
If Ufaktor = 0 Then Ufaktor = 1.0
 
If Ifaktor = 0 Then Ifaktor = 1.0
 
 
'Angepasste Sinuskurve aus dem EEprom laden
 
#if Numhall = 3      'Anzahl Hallsensoren
 
'  For N = 1 To 6
 
'  Bdummy = N + 30
 
'  Readeeprom Sinus(n) , Bdummy
 
'  Next
 
  Sinus(1) = 0
 
  Sinus(2) = 33
 
  Sinus(3) = 66
 
  Sinus(4) = 100
 
  Sinus(5) = 66
 
  Sinus(6) = 33
 
#else      'Anzahl Hallsensoren = 4
 
'  For N = 1 To 12
 
'  Bdummy = N + 18
 
'  Readeeprom Sinus(n) , Bdummy
 
'  Next
 
  Sinus(1) = 0
 
  Sinus(2) = 0
 
  Sinus(3) = 33
 
  Sinus(4) = 66
 
  Sinus(5) = 100
 
  Sinus(6) = 100
 
  Sinus(7) = 100
 
  Sinus(8) = 100
 
  Sinus(9) = 66
 
  Sinus(10) = 33
 
  Sinus(11) = 0
 
  Sinus(12) = 0
 
#endif
 
 
Fan = 1      'Lüfter kurz einschalten damit die Lager nicht fest werden
 
For N = 1 To 3      '3 sekunden
 
Led1 = 1
 
Led2 = 0
 
Waitms 500
 
Toggle Led1
 
Toggle Led2
 
Waitms 500
 
Next
 
Led2 = 0
 
Fan = 0
 
 
On Urxc Datenempfang Nosave
 
Enable Urxc      'serielles UART. No parity, 1 stop bit, 8 data bits
 
Enable Interrupts
 
 
Do
 
Led1 = 0
 
'<Messen>
 
Uw = Getadc(0) + 14      'Versorgungsspannung. Siehe Hardwarezeichnung
 
Uwsum = Uwsum + Uw
 
Iw = Getadc(1)      'Gesamtstrom
 
Iwsum = Iwsum + Iw
 
Incr Wcount
 
'Kühkörpertemperatur in counts. Siehe Datenblätter\10K_NTC_Kennlinie.odt
 
Temp = Getadc(2)
 
'</Messen>
 
'<Serielle Telegramme abarbeiten>
 
' Empfpuffer(1) Empfpuffer(2)  Empfpuffer(3) Empfpuffer(4) Empfpuffer(5) Empfpuffer(6)
 
' <CR>          Contr.Adresse      Richtung      PWM        Checksum        <CR>
 
If Empfpuffer(1) = 13 Then      'Das letzte im Ring verschobene empfangene CR
 
  If Empfpuffer(6) = 13 Then
 
  Led1 = 1
 
  If Empfpuffer(2) = Motoradresse Then      '"R" oder "L"
 
    Disable Urxc
 
    'BCC für Empfangsmessage berechnen
 
    !lds R24,{Empfpuffer(2)}      'Adresse. Load Direct from data space @address xxx
 
    !LDs R25,{Empfpuffer(3)}      'Richtung.Load Direct from data space @address xxx
 
    !add R24,R25
 
    !LDs R25,{Empfpuffer(4)}      'PWM. Load Direct from data space @address xxx
 
    !add R24,R25
 
    !STS {Bdummy},R24      'Write Rxx to address loaction
 
    If Bdummy = Empfpuffer(5) Then      'Die Prüfsumme stimmt
 
    'Kommutieren deaktivieren, weil sonst die Ticks während dem Zugriff
 
    'geändert werden könnten
 
    Pcicr = &B00000000
 
    Ausgabeticks = Ticks
 
    Ticks = 0
 
    Pcicr = _pcicr
 
    'BCC für Sendemessage berechnen
 
    !lds R24,{M1}      'Load Direct from data space @address xxx into Rxx
 
    !LDs R25,{M2}      'Load Direct from data space @address xxx into Rxx
 
    !add R24,R25      'Add Rxx + Ryy, Result in Rxx
 
    !LDs R25,{M3}      'Load Direct from data space @address xxx into Rxx
 
    !add R24,R25      'Add Rxx + Ryy, Result in Rxx
 
    !LDs R25,{M4}      'Load Direct from data space @address xxx into Rxx
 
    !add R24,R25      'Add Rxx + Ryy, Result in Rxx
 
    !LDs R25,{M5}      'Load Direct from data space @address xxx into Rxx
 
    !add R24,R25      'Add Rxx + Ryy, Result in Rxx
 
    !LDs R25,{M6}      'Load Direct from data space @address xxx into Rxx
 
    !add R24,R25      'Add Rxx + Ryy, Result in Rxx
 
    !STS {Bdummy},R24      'Write Rxx to address loaction
 
    'Antwort am UART ausgeben
 
    'M1/M2=Spg  M3/M4=Strom M5/M6=Loop Ticks Bdummy=Checksum
 
    'Print M1 ; M2 ; M3 ; M4 ; M5 ; M6 ; Bdummy ; 13
 
    'in Assembler geht das so...
 
    !LdS    R24,{M1}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten1:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten1
 
    !LDS    R24,{M2}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten2:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten2
 
    !lds    R24,{M3}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten3:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten3
 
    !LDS    R24,{M4}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten4:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten4
 
    !LDS    R24,{M5}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten5:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten5
 
    !LDS    R24,{M6}      'Load Direct from data space @address xxx into Rxx
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten6:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten6
 
    !LDS    R24,{bdummy}
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten7:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten7
 
    !LDi    R24,13
 
    !STS    udr,R24      'Write Rxx to address loaction
 
    Warten8:
 
    !LDS    R24,UCSR0A      'Load Direct from data space @address xxx into Rxx
 
    !BST    R24,5      'Store bit x of Rxx in T Flag
 
    !Brtc warten8
 
    If Empfpuffer(3) < 3 Then      'Richtung
 
      Notaus = 0
 
      Loopcount = 0
 
      Sollrichtung = Empfpuffer(3)      'Richtung
 
      Sollspeed = Empfpuffer(4)      'PWM Breite
 
      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      'wird nie erreicht weil weder Hauptsteuerung noch Display diese
 
                'Werte senden
 
      Select Case Empfpuffer(3)
 
      Case 3      'Sinus(1) empfangen
 
        Sinus(1) = Empfpuffer(4)
 
        Writeeeprom Sinus(1) , 17
 
      Case 4      'Sinus(2) empfangen
 
        Sinus(2) = Empfpuffer(4)
 
        Writeeeprom Sinus(2) , 18
 
      Case 5      'Sinus(3) empfangen
 
        Sinus(3) = Empfpuffer(4)
 
        Writeeeprom Sinus(3) , 19
 
      Case 6      'Sinus(4) empfangen
 
        Sinus(4) = Empfpuffer(4)
 
        Writeeeprom Sinus(4) , 20
 
      Case 7      'Sinus(5) empfangen
 
        Sinus(5) = Empfpuffer(4)
 
        Writeeeprom Sinus(5) , 21
 
      Case 8      'Sinus(6) empfangen
 
        Sinus(6) = Empfpuffer(4)
 
        Writeeeprom Sinus(6) , 22
 
      Case 9      'Sinus(7) empfangen
 
        Sinus(7) = Empfpuffer(4)
 
        Writeeeprom Sinus(7) , 23
 
      Case 10      'Sinus(8) empfangen
 
        Sinus(8) = Empfpuffer(4)
 
        Writeeeprom Sinus(8) , 24
 
      Case 11      'Sinus(9) empfangen
 
        Sinus(9) = Empfpuffer(4)
 
        Writeeeprom Sinus(9) , 25
 
      Case 12      'Sinus(10) empfangen
 
        Sinus(10) = Empfpuffer(4)
 
        Writeeeprom Sinus(10) , 26
 
      Case 13      'Sinus(11) empfangen
 
        Sinus(11) = Empfpuffer(4)
 
        Writeeeprom Sinus(11) , 27
 
      Case 14      'Sinus(12) empfangen
 
        Sinus(12) = Empfpuffer(4)
 
        Writeeeprom Sinus(12) , 28
 
      Case 15      'Spannung Kalibrieren (Byte 1)
 
        Kal(1) = Empfpuffer(4)
 
      Case 16      'Spannung Kalibrieren (Byte 2)
 
        Kal(2) = Empfpuffer(4)
 
        Sdummy = Uwsum / Wcount
 
        Ufaktor = Kalibrierwert / Sdummy
 
        Writeeeprom Ufaktor , 5
 
        Uoffset = 0      'Schaltungsbedingt
 
        Writeeeprom Uoffset , 1
 
      Case 17      'Strom Kalibrieren (Byte 1)
 
        Kal(1) = Empfpuffer(4)
 
      Case 18      'Strom Kalibrieren Byte (2)
 
        Kal(2) = Empfpuffer(4)
 
        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 = Empfpuffer(4)
 
        Writeeeprom Vwinkel , 29
 
      Case 20
 
        Rwinkel = Empfpuffer(4)
 
        Writeeeprom Rwinkel , 30
 
      End Select
 
    End If
 
    !LDI    R24,0
 
    !sTS    {Empfpuffer(1)},R24      'Write Rxx to address loaction
 
    !sTS    {Empfpuffer(2)},R24      'Write Rxx to address loaction
 
    !sTS    {Empfpuffer(3)},R24      'Write Rxx to address loaction
 
    !sTS    {Empfpuffer(4)},R24      'Write Rxx to address loaction
 
    !sTS    {Empfpuffer(5)},R24      'Write Rxx to address loaction
 
    End If
 
    Enable Urxc
 
  End If
 
  End If
 
End If
 
'</Serielle Telegramme abarbeiten>
 
 
'Lüfter einschalten wenn Temperatur > 57 GradC
 
'Lüfter ausschalten wenn Temperatur < 45 GradC
 
If Temp < 350 Then
 
  Fan = 1
 
  Fancount = 120000      'Nachlaufzeit, Zykluszeit 1/100 Sekunde = 150 Sekunden
 
Else
 
  If Temp > 532 Then
 
  If Fancount = 0 Then      'Nachlaufzeit beendet
 
    Fan = 0
 
  End If
 
  End If
 
End If
 
If Fancount > 0 Then Decr Fancount
 
 
'Notaus mit Freilauf wenn keine Nachricht von Seriell
 
If Loopcount < 50 Then      'Das sind schätzungsweise 0.1s
 
  Notaus = 0
 
  Incr Loopcount
 
Else
 
  Notaus = 1
 
  Sollspeed = 0
 
  Setspeed
 
End If
 
Loop
 
 
Kommutieren:
 
!push    R10      'Rxx sichern
 
!PUSH    R11      'Rxx sichern
 
!PUSH    R16      'Rxx sichern
 
!PUSH    R17      'Rxx sichern
 
!PUSH    R20      'Rxx sichern
 
!PUSH    R21      'Rxx sichern
 
!PUSH    R24      'Rxx sichern
 
!PUSH    R26      'Rxx sichern
 
!PUSH    R27      'Rxx sichern
 
!IN      R24,sreg
 
!PUSH    R24
 
!clr R16      'Clear Rxx
 
#if Numhall = 3
 
  !andi R17,&B01110111      'Clear Hall-D Bits
 
#else
 
  !lds R17, $0023      'Port B input pins address. Hall D
 
  !BST R17,0      'Store bit x of Rxx in T Flag. Hall D-Bit
 
  !BLD R16,3      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
#endif
 
!LDS R17, $0029      'Port D input pins address. Hall A,B,C
 
!BST R17,2      'Store bit x of Rxx in T Flag. Hall C-Bit
 
!bld R16,2      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
!BST R17,4      'Store bit x of Rxx in T Flag. Hall B-Bit
 
!bld R16,1      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
!BST R17,7      'Store bit x of Rxx in T Flag. Hall A-Bit
 
!bld R16,0      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
'R16 hat nun 0000DCBA Hall Signale
 
!lds R17,{aposition}      'Load Direct from data space @address xxx
 
!Swap R17      'R17 hat nun DCBA0000 Hall Signale
 
!andi R17,&B11110000      'Bit-And of Rxx with a constant value. Die 4 Bit sind Hall A...D
 
'R17 hat nun nur noch die oberen 4 Bit
 
!add R17,R16      'Rxx + Ryy. Ergebnis in Rxx
 
!STS {aposition},R17      'Write Rxx to address loaction
 
!CLR    R17
 
!LDI    R26,$FF      'Startadresse von A() - 1
 
!LDI    R27,$00
 
!ADD    R26,R16
 
!ADC    R27,R17
 
!LD      R24,X      'Load Direct from address xxx
 
!LDS    R16,{Sollrichtung} 'Load Direct from data space @address xxx
 
!CPI    R16,0
 
!BREQ    Sollrichtungnull      'Branch out if equal
 
!Jmp    Sollrichtungnichtnull
 
Sollrichtungnull:
 
!LDS    R20,{Vwinkel}  'Load Direct from data space @address xxx
 
!Add    R24,R20
 
!JMP    Richtunggesetzt
 
Sollrichtungnichtnull:
 
!LDS    R20,{Rwinkel}
 
!Add    R24,R20
 
Richtunggesetzt:
 
#if Numhall = 3
 
  !CPI    R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
#else
 
  !CPI    R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
#endif
 
!BRCC    Istgroesser13_1
 
!JMP    Istkleiner13_1
 
Istgroesser13_1:
 
#if Numhall = 3
 
  !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
#else
 
  !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
#endif
 
Istkleiner13_1:
 
!CLR    R20
 
!Ldi    R26,$0E      'Startadresse von S() - 1
 
!LDI    R27,$01      'Startadresse von S() - 1
 
!ADD    R26,R24
 
!ADC    R27,R20
 
!LD      R16,X      'Load Direct from address xxx
 
!STS    {Ta},R16      'Write Rxx to address loaction
 
!subi    R24,$fc
 
#if Numhall = 3
 
  !CPI R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
#else
 
  !CPI R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
#endif
 
!BRCC    Istgroesser13_2
 
!JMP    Istkleiner13_2
 
Istgroesser13_2:
 
#if Numhall = 3
 
  !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
#else
 
  !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
#endif
 
Istkleiner13_2:
 
!CLR    R20
 
!Ldi    R26,$0E      'Startadresse von S() - 1
 
!LDI    R27,$01      'Startadresse von S() - 1
 
!ADD    R26,R24
 
!ADC    R27,R20
 
!LD      R16,X    'Load Direct from address xxx
 
!STS    {Tc},R16 'Write Rxx to address loaction
 
!subi    R24,$fc
 
#if Numhall = 3
 
  !CPI    R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
#else
 
  !CPI    R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
#endif
 
!BRCC    Istgroesser13_3
 
!JMP    Istkleiner13_3
 
Istgroesser13_3:
 
#if Numhall = 3
 
  !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
#else
 
  !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
#endif
 
Istkleiner13_3:
 
!CLR    R20
 
!Ldi    R26,$0E      'Startadresse von S() - 1
 
!LDI    R27,$01      'Startadresse von S() - 1
 
!ADD    R26,R24
 
!ADC    R27,R20
 
!LD      R16,X    'Load Direct from address xxx
 
!STS    {Tb},R16 'Write Rxx to address loaction
 
!lds    R10,{aposition}
 
!CLR    R11      'Clear Rxx
 
!LDI    R26,$1A      'Startadresse von Richtung() - 1
 
!LDI    R27,$01      'Startadresse von Richtung() - 1
 
!ADD    R26,R10      'move Ptr by {aposition} innnerhalb Richtung()
 
!ADC    R27,R11      'Add Zero
 
!LD      R16,X+      'Load Rxx with data from address in X Register(R26, R27) and increment Ptr
 
'R16 hat Inhalt von Richtung(X+)
 
!CLR    R17      'Clear Rxx
 
!LDI    R20,$02      '2 Byte
 
!LDI    R21,$00
 
!Sub R16 , R20      'Werte von einander abziehen
 
!SBC    R17,R21      'Werte von einander abziehen
 
!LDI    R26,$1A      'Startadresse von IstRichtung()
 
!LDI    R27,$02      'Startadresse von IstRichtung()
 
!ST      X+,R16      'Store Rxx in address in X + 1 Register
 
!ST      X,R17
 
!LDI    R26,$41      'Startadresse von Ticks()
 
!LDI    R27,$02      'Startadresse von Ticks()
 
!LD      R16,X+      'Load Rxx with data from address in X Register
 
!LD      R17,X
 
!LDI    R26,$1A      'Startadresse von IstRichtung()
 
!LDI    R27,$02      'Startadresse von IstRichtung()
 
!LD      R20,X+      'Load Rxx with data from address in X Register
 
!LD      R21,X
 
!ADD    R16,R20
 
!ADC    R17,R21
 
!LDI    R26,$41      'Startadresse von Ticks()
 
!LDI    R27,$02      'Startadresse von Ticks()
 
!ST      X+,R16      'Store Rxx in address in X + 1 Register
 
!ST      X,R17
 
!LDS    R24,timsk2
 
!ORI    R24,$01
 
!STS    timsk2,R24 'Write Rxx to address loaction
 
!POP    R24
 
!Out Sreg , R24
 
!POP    R27 'Rxx wieder herstellen
 
!POP    R26'Rxx wieder herstellen
 
!POP    R24'Rxx wieder herstellen
 
!POP    R21 'Rxx wieder herstellen
 
!POP    R20 'Rxx wieder herstellen
 
!POP    R17'Rxx wieder herstellen
 
!POP    R16 'Rxx wieder herstellen
 
!POP    R11 'Rxx wieder herstellen
 
!POP    R10      'Rxx wieder herstellen
 
Return
 
 
Update_pwm:
 
'Ta, Tb und Tc sind die Amplituden der 3 Phasen
 
!PUSH    R24
 
!IN      R24,sreg
 
!PUSH    R24
 
!lds    R24,{Ta}
 
!STS    ocr2a,R24 'Write Rxx to address loaction
 
!STS    ocr2b,R24
 
!LDS    R24,{Tb}
 
!STS    ocr1al,R24 'Write Rxx to address loaction
 
!STS    ocr1bl,R24
 
!lds    R24,{Tc}
 
!Out Ocr0a , R24
 
!Out Ocr0b , R24
 
!LDS    R24,timsk2
 
!ANDI    R24,$FE
 
!STS    timsk2,R24 'Write Rxx to address loaction
 
!POP    R24 'Rxx wieder herstellen
 
!Out Sreg , R24
 
!POP    R24 'Rxx wieder herstellen
 
Return
 
 
Datenempfang:
 
'Die empfangenen Zeichen im nach links laufenden Umlauf in Empfpuffer(1)..Empfpuffer(6) geschrieben
 
'Dadurch wir sichergestellt, dass das Startzeichen (CR) irgendwann in EP0 steht
 
!PUSH R24      'Rxx sichern
 
!IN R24, SREG      'Statusregistr sichern
 
!PUSH R24
 
'Zeichen im Puffer nach links schieben
 
!LDS R24,{Empfpuffer(2)}      'Load Direct from data space @address xxx
 
!STS {Empfpuffer(1)},R24      'Write Rxx to address loaction
 
!LDS R24,{Empfpuffer(3)}      'Load Direct from data space @address xxx
 
!STS {Empfpuffer(2)},R24      'Write Rxx to address loaction
 
!LDS R24,{Empfpuffer(4)}      'Load Direct from data space @address xxx
 
!STS {Empfpuffer(3)},R24      'Write Rxx to address loaction
 
!LDS R24,{Empfpuffer(5)}      'Load Direct from data space @address xxx
 
!STS {Empfpuffer(4)},R24      'Write Rxx to address loaction
 
!LDS R24,{Empfpuffer(6)}      'Load Direct from data space @address xxx
 
!STS {Empfpuffer(5)},R24      'Write Rxx to address loaction
 
'neues Zeichen einlesen
 
!IN  R24,UDR      'Load an I/O Location to Rxx
 
!STs {Empfpuffer(6)},R24      'Write Rxx to address loaction
 
!POP R24      'Rxx wieder herstellen
 
!Out Sreg , R24      'Statusregister wieder herstellen
 
!POP R24      'Rxx wieder herstellen
 
Return
 
 
Sub Setspeed
 
If Notaus = 1 Then
 
  Pwm_stop
 
  Sollspeed = 0
 
  For N = 1 To 12
 
  S(n) = 0
 
  Next
 
Else
 
  #if Numhall = 3      'Anzahl Hallsensoren
 
    For N = 1 To 6
 
    Idummy1 = Sollspeed * Sinus(n)
 
    Idummy1 = Idummy1 / 100
 
    S(n) = Idummy1
 
    Next
 
  #else
 
    For N = 1 To 12
 
    Idummy1 = Sollspeed * Sinus(n)
 
    Idummy1 = Idummy1 / 100
 
    S(n) = Idummy1
 
    Next
 
  #endif
 
 
  If Tccr0a = 0 Then Pwm_start      'Wenn die PWM aus ist
 
 
  '<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
 
  !clr R16      'Clear Register 16
 
  !lds R17, $0023      'Load Direct from data space @address xxx
 
  !BST R17,0      'Store bit x of Rxx in T Flag
 
  !BLD R16,3      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
  !LDS R17, $0029      'Load Direct from data space @address xxx
 
  !BST R17,2      'Store bit x of Rxx in T Flag
 
  !bld R16,2      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
  !BST R17,4      'Store bit x of Rxx in T Flag
 
  !bld R16,1      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
  !BST R17,7      'Store bit x of Rxx in T Flag
 
  !bld R16,0      'Copy T Flag in the SREG (Status Register) to Bit x in Rxx
 
  !lds R17,{aposition}      'Load Direct from data space @address xxx
 
  !Swap R17      'Swap high and low nibbles in Rxx. aposition is now in the upper nibble
 
  !andi R17,&B11110000      'Logical AND Rxx and a constant, Result in Rxx. Clear lower nibble
 
  !add R17,R16      'Add Rxx + Ryy, Result in Rxx
 
  !STS {aposition},R17      'Write Rxx to address loaction
 
  !CLR    R17      'Clear Rxx
 
  !LDI    R26,$FF      'Startadresse von A() - 1
 
  !LDI    R27,$00      'Startadresse von A() - 1
 
  !ADD    R26,R16      'Add Rxx + Ryy without carry, Result in Rxx
 
  !ADC    R27,R17      'Add Rxx + Ryy with carry, Result in Rxx
 
  !LD      R24,X      'Load Indirect Rxx with address in X Register
 
  !LDS    R16,{Sollrichtung}      'Load Direct from data space @address xxx
 
  !CPI    R16,0      'Compare Rxx with constant
 
  !BREQ    Sollrichtungnullz      'Branch if Equal
 
  !Jmp    Sollrichtungnichtnullz      'Relative Jump
 
  Sollrichtungnullz:
 
  !LDS    R20,{Vwinkel}      'Load Direct from data space @address xxx
 
  !Add    R24,R20      'Add Rxx + Ryy, Result in Rxx
 
  !JMP    Richtunggesetztz
 
  Sollrichtungnichtnullz:
 
  !LDS    R20,{Rwinkel}      'Load Direct from data space @address xxx
 
  !Add    R24,R20      'Add Rxx + Ryy without carry, Result in Rxx
 
  Richtunggesetztz:
 
  #if Numhall = 3
 
    !CPI    R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
  #else
 
    !CPI    R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
  #endif
 
  !BRCC    Istgroesser13_1z      'Branch if Carry Cleared
 
  !JMP    Istkleiner13_1z      'Relative Jump
 
  Istgroesser13_1z:
 
  #if Numhall = 3
 
    !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
  #else
 
    !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
  #endif
 
  Istkleiner13_1z:
 
  !CLR    R20      'Clear Rxx
 
  !Ldi    R26,$0E      'Startadresse von S() - 1
 
  !LDI    R27,$01      'Startadresse von S() - 1
 
  !ADD    R26,R24      'Add Rxx + Ryy without carry, Result in Rxx
 
  !ADC    R27,R20      'Add Rxx + Ryy with carry, Result in Rxx
 
  !LD      R16,X      'Load Rxx with data from address in X Register
 
  !STS    {Ta},R16      'Write Rxx to address loaction
 
  !subi    R24,$fc      'Subtract constant from Rxx, result in Rxx
 
  #if Numhall = 3
 
    !CPI    R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
  #else
 
    !CPI    R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
  #endif
 
  !BRCC    Istgroesser13_2z      'Branch if Carry Cleared
 
  !JMP    Istkleiner13_2z      'Relative Jump
 
  Istgroesser13_2z:
 
  #if Numhall = 3
 
    !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
  #else
 
    !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
  #endif
 
  Istkleiner13_2z:
 
  !CLR    R20      'Clear Rxx
 
  !Ldi    R26,$1a      'Startadresse von S() - 1
 
  !LDI    R27,$01      'Startadresse von S() - 1
 
  !ADD    R26,R24      'Add Rxx + Ryy without carry, Result in Rxx
 
  !ADC    R27,R20      'Add Rxx + Ryy with carry, Result in Rxx
 
  !LD      R16,X      'Load Rxx with data from address in X Register
 
  !STS    {Tc},R16      'Write Rxx to address loaction
 
  !subi    R24,$fc      'Subtract constant from Rxx, result in Rxx
 
  #if Numhall = 3
 
    !CPI    R24,$07      'Compare Rxx with constant 6 + 1 Sinusschritte
 
  #else
 
    !CPI    R24,$0D      'Compare Rxx with constant 12 + 1 Sinusschritte
 
  #endif
 
  !BRCC    Istgroesser13_3z      'Branch if Carry Cleared
 
  !JMP    Istkleiner13_3z      'Relative Jump
 
  Istgroesser13_3z:
 
  #if Numhall = 3
 
    !SUBI    R24,$06      'Subtract constant from Rxx, result in Rxx. 6 Sinusschritte
 
  #else
 
    !SUBI    R24,$0C      'Subtract constant from Rxx, result in Rxx. 12 Sinusschritte
 
  #endif
 
  Istkleiner13_3z:
 
  !CLR    R20      'Clear Rxx
 
  !Ldi    R26,$1a      'Startadresse von S() - 1
 
  !LDI    R27,$01      'Startadresse von S() - 1
 
  !ADD    R26,R24      'Add Rxx + Ryy without carry , Result in Rxx
 
  !ADC    R27,R20      'Add Rxx + Ryy with carry, Result in Rxx
 
  !LD      R16,X      'Load Rxx with data from address in X Register
 
  !STS    {Tb},R16      'Write Rxx to address loaction
 
  Pcicr = _pcicr      'Den eigentlichen Kommutierinterrupt einschalten
 
  Timsk2.toie2 = 1      'Timer2 Overflow Interrupt aktivieren
 
  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  'Timer Counter Control Register A
 
Tccr0b = 1      'Timer Counter Control Register B
 
Ocr0a = 0      'Set output compare Ctr 0, Register A, continuously compared with TCNT0
 
Ocr0b = 0      'Set output compare Ctr 0, Register B, continuously compared with TCNT0
 
Tccr1a = 161      'Timer Counter Control Register 1A
 
Tccr1b = 1      'Timer Counter Control Register 1B
 
Ocr1ah = 0      'Output A compare value in H and L Bytes
 
Ocr1al = 0
 
Ocr1bh = 0      'Output B compare value in H and L Bytes
 
Ocr1bl = 0
 
Tccr2a = 161    'Timer Counter Control Register 2A
 
Tccr2b = 1      'Timer Counter Control Register 2B
 
Ocr2a = 0        'Set output compare Ctr 2, Register A, continuously compared with TCNT0
 
Ocr2b = 0      'Set output compare Ctr 2, Register B, continuously compared with TCNT0
 
Tcnt0 = 0      'Timer Startwert
 
Tcnt1 = 6      'Timer Startwert, Wert anders damit sie alle synchron laufen
 
Tcnt2 = 9      'Timer Startwert, Wert anders damit sie alle synchron laufen
 
Enable Interrupts
 
End Sub
 
 
Sub Pwm_stop
 
Tccr0a = 0      'Timer Counter Control Register A
 
Tccr0b = 0      'Timer Counter Control Register B
 
Ocr0a = 0      'Set output compare Ctr 0, Register A, continuously compared with TCNT0
 
Ocr0b = 0      'Set output compare Ctr 0, Register B, continuously compared with TCNT0
 
Tccr1a = 0      'Timer Counter Control Register 1A
 
Tccr1b = 0      'Timer Counter Control Register 1B
 
Ocr1ah = 0      'Output A compare value in H and L Bytes
 
Ocr1al = 0
 
Ocr1bh = 0      'Output B compare value in H and L Bytes
 
Ocr1bl = 0
 
Tccr2a = 0      'Timer Counter Control Register 2A
 
Tccr2b = 0      'Timer Counter Control Register 2B
 
Ocr2a = 0      'Set output compare Ctr 2, Register A, continuously compared with TCNT0
 
Ocr2b = 0      'Set output compare Ctr 2, Register B, continuously compared with TCNT0
 
'alle Phasen 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
 
</pre>
 
 
'''Hauptsteuerung.bas (BASCOM)'''
 
<pre>
 
'( ******************Listrik01 Hauptsteuerung, Version 01 ******************
 
 
1. LED1 blinkt mit 1 Hz wenn alles OK
 
 
2. LED1 und LED2 blinken mit 5Hz wenn I2c-Bus gestört ist
 
 
3. LED1 und LED2 blinken mit bis zu 10Hz wenn U-Batt zu klein ist. Frequenz hängt
 
  von der Anzahl Interrups ab, die während der Wartezeit auflaufen, z.B. von COM
 
 
4. Lade-LEDs
 
    - blinken mit 4Hz wenn Gyro nicht auf Null ist
 
    - blinken mit 5Hz wenn Reset button gedrückt wird und Gyrosignale groß sind
 
    - machen Lichtorgel wenn Kopplung zum Motorcontroler gestört ist. Siehe Punkt 6
 
 
5. Gyro wird nur zur Initialisierung benutzt. Fahrzeug muss still stehen beim START
 
 
6. Kommunikation zum Motorcontroller ist gestört (Timeout) wenn der Hallstecker
 
  am Motorcontroller nicht steckt sind! Dadurch antwortet der Motorcontroller dem
 
  Hauptcontroller nicht. Er sendet z.B. keine Spannungsinfo an den Hauptcontroller.
 
  Dadurch macht Dieser ständig einen Restart. Viele Werte werden dann nicht zum
 
  Dashboard übertragen!
 
 
LockBit, FuseBit , FuseBitHigh , FuseBitExtended
 
$prog &HFF , &HE7 , &HD9 , &HFF      'Fusebits für Atmega644PA 20MHz
 
 
Use AMTEL Studio / Fuses Menu instead to set fusebits
 
BODLEVEL = disabled
 
OCDEN = Disabled
 
JTAGEN = Disabled
 
SPIEN = Checked
 
WDTON = Disabled
 
EESAVE = Disabled
 
BOOTSZ = 4096W_7000
 
BOOTRST = Disabled
 
CKDIV8 = Disabled
 
CKOUT = Disabled
 
SUT_CKSEL = FSOSZ_16KCK_4MS1_XOSC_FASTPWR
 
')
 
 
$regfile = "m644def.dat"      'ATMEGA644PA CPU
 
$lib "i2c_twi.lbx"
 
$framesize = 64
 
$swstack = 64
 
$hwstack = 64
 
$crystal = 20000000
 
$baud = 57600      'No parity, 1 stop bit, 8 data bits
 
 
Declare Sub Onresetbtn
 
Declare Sub Logtext(byval Adresse As Word , Text As String )
 
Declare Sub Akkugrenzen
 
Declare Sub Unfalldatenschreiber
 
Declare Sub Betriebsdatenschreiber
 
Declare Sub Flashled(byval Which As Byte , Byval Dauer_ms As Byte)
 
Declare Sub Resetdata
 
 
'      Porta.0 = ADC
 
'      Porta.1 = ADC
 
Config Porta.2 = Input      'not used
 
Config Porta.3 = Input      'not used
 
Config Porta.4 = Input      'not used
 
Config Porta.5 = Input      'not used
 
Config Porta.6 = Input      'not used
 
Config Porta.7 = Input      'not used
 
'Pull up Widerstände der unbenutzten Eingänge einschalten
 
Porta = 1
 
 
Config Portb.0 = Input      'not used
 
Config Portb.1 = Output      'Gyro Self Test
 
Config Portb.2 = Output      'Gyro Reset
 
Config Portb.3 = Output      'Led 2
 
Config Portb.4 = Output      'LED 1
 
'      PORTB.5              'MOSI
 
'      PORTB.6              'MISO
 
'      PORTB.7              'SCK
 
 
Config Scl = Portc.0
 
Config Sda = Portc.1
 
 
Config Portc.2 = Input      'Fussschalter 1
 
Config Portc.3 = Input      'Fussschalter 2
 
Config Portc.4 = Input      'not used
 
Config Portc.5 = Input      'not used
 
Config Portc.6 = Input      'not used
 
Config Portc.7 = Output      'Beeper
 
'Pull up Widerstände der Eingänge Ein/Ausschalten
 
Portc.2 = 0
 
Portc.3 = 0
 
Portc.4 = 1
 
Portc.5 = 1
 
Portc.6 = 1
 
 
'      PORTD.0 =            'RXD
 
'      PORTD.1 =            'TXD
 
Config Portd.2 = Input      'Reset Button vom Akku-Display
 
Config Portd.3 = Output      'Batterieanzeige
 
Config Portd.4 = Output      'Batterieanzeige
 
Config Portd.5 = Output      'Batterieanzeige
 
Config Portd.6 = Output      'Batterieanzeige
 
Config Portd.7 = Output      'Batterieanzeige
 
'Pull up Widerstände einschalten
 
Portd.2 = 1
 
 
Led1 Alias Portb.4
 
Led2 Alias Portb.3
 
Led3 Alias Portd.4      'Batterieladezustandsanzeige 0..20%
 
Led4 Alias Portd.5      'Batterieladezustandsanzeige 21..40%
 
Led5 Alias Portd.6      'Batterieladezustandsanzeige 41..60%
 
Led6 Alias Portd.3      'Batterieladezustandsanzeige 61..80%
 
Led7 Alias Portd.7      'Batterieladezustandsanzeige 81..100%
 
 
Beeper Alias Portc.7
 
Resetbtn Alias Pind.2
 
 
'Sensortest gibt es bei I2C Gyro nicht
 
'Sensor_aus Alias Portb.2        '1=Aus        0=Ein
 
'Sensor_test Alias Portb.1      '1=Self-Test. 0=Normalbetrieb
 
 
Config Debounce = 100      '[mS] when the config statement is not used a
 
'                              default of 25mS will be used
 
'******************************Gyro über I2C ********************************
 
'##### 7 - Bit Adresses Gyro ########
 
Const Who_am_i = &H0F      'auch V2
 
Const Ctrl_reg1 = &H20      'auch V2
 
Const Ctrl_reg2 = &H21      'auch V2
 
Const Ctrl_reg3 = &H22      'auch V2
 
Const Ctrl_reg4 = &H23      'auch V2
 
Const Ctrl_reg5 = &H24      'auch V2
 
Const Out_temp = &H26      'auch V2
 
Const Status_reg = &H27      'auch V2
 
Const Out_x_l = &H28      'auch V2
 
Const Out_x_h = &H29      'auch V2
 
Const Out_y_l = &H2A      'auch V2
 
Const Out_y_h = &H2B      'auch V2
 
Const Out_z_l = &H2C      'auch V2
 
Const Out_z_h = &H2D      'auch V2
 
'##### 7-Bit Adresses Accelerometer ########
 
Const Ctrl_reg1_a = &H20      'auch V2
 
Const Ctrl_reg2_a = &H21      'auch V2
 
Const Ctrl_reg3_a = &H22      'auch V2
 
Const Ctrl_reg4_a = &H23      'auch V2
 
Const Ctrl_reg5_a = &H24      'auch V2
 
Const Status_reg_a = &H27      'auch V2
 
Const Out_x_l_a = &H28      'auch V2
 
Const Out_x_h_a = &H29      'auch V2
 
Const Out_y_l_a = &H2A      'auch V2
 
Const Out_y_h_a = &H2B      'auch V2
 
Const Out_z_l_a = &H2C      'auch V2
 
Const Out_z_h_a = &H2D      'auch V2
 
'##### 7-Bit Adresses Magnetometer ########
 
'Const Cra_reg_m = &H00      'auch V2
 
'Const Crb_reg_m = &H01      'auch V2
 
'Const Mr_reg_m = &H02      'auch V2
 
'Const Out_x_h_m = &H03      'auch V2
 
 
'Immer *2 weil Adresse bei Bit1 beginnt. Bit 0 ist für Read/Write
 
Const Gyroadress_w = 210      '=105*2, =107d*2 bei V2. Gyro slave adress for write
 
Const Gyroadress_r = 211      '=(105*2) + 1, =107d*2 bei V2. Gyro slave adress for write
 
Const Accadress_w = 48      '=24*2, auch bei V2 Accelerometer slave adress for write
 
Const Accadress_r = 49      '=(24*2) + 1, auch bei V2 Accelerometer slave adress for write
 
 
'Const Magadress_w = 60      '=30*2, auch bei V2 Magnetometer slave adress for write
 
'Const Magadress_r = 61      '=(30*2) + 1, auch bei V2 Magnetometer slave adress for write
 
'--------------------------------------------------------------------
 
 
'>>>>>>>>>>>>>>>> DEFAULT WERTE <<<<<<<<<<<<<<<<<<
 
 
Const Fussschalterschwelle = 750      'ADC Wert
 
 
'Konstanten für die Geschwindigkeits und Streckenmessung
 
Const Kom_pro_u = 276      '276*Kommutieren für eine Umdrehung.
 
Const Radumpfang = 139      'RaduMPFang in Zentimeter
 
'Maximalwert bis zu dem die Abweichung in y aufaddiert wird
 
Const Max_mit_acc_nick_s = 1024
 
Const Min_mit_acc_nick_s = -1024
 
Const Max_lenk = 128
 
Const Min_lenk = -128
 
'Konstanten für die Leistungsbegrenzung, Geschwindigkeitsbegrenzung
 
'Maximalleistung
 
Const Maxpwm = 255
 
Const Minpwm = -255
 
'PWM ab der automatisch gebremst wird um blos nie an die Grenze zu kommen
 
Const Spwm = 128
 
Const Spwmr = -128
 
'Offsetwerte für die Mittellage
 
Const Offset_roll = 67700
 
Const Offset_nick = 65400
 
Const O_roll_u = 66200
 
Const O_roll_o = 69200
 
Const O_nick_u = 63900
 
Const O_nick_o = 66900
 
Const O_nick_oo = 67700
 
 
Const Vmax = 120      '12kmh Vmax Vorwärts in km/h*10
 
Const Vmaxr = -120      '-12Kmh Vmax Rückwärts in km/h*10
 
 
Const Systemvoltage = 14      '14, 24, 36, 48V
 
 
'Konstanten für die Akkus
 
#if Systemvoltage = 14      'Nur zum Test mit Netzteil
 
Const Akkuleer = 1300
 
Const Akkufastleer = 1330
 
#endif
 
 
#if Systemvoltage = 24
 
'24V, 12V pro Akku * 2 Akku
 
Const Akkuleer = 2400
 
Const Akkufastleer = 2500
 
#endif
 
 
#if Systemvoltage = 36
 
'36V, 12V pro Akku * 3 Akku
 
Const Akkuleer = 3600
 
Const Akkufastleer = 3750
 
#endif
 
 
#if Systemvoltage = 48
 
'48V, 12V pro Akku * 4 Akku
 
Const Akkuleer = 4800
 
Const Akkufastleer = 4950
 
#endif
 
 
'Konstanten für die Signalaufbereitung
 
Const Gyro_anz = 10      'war 10000
 
Const Acc_anz = 5      'Anzahl der Messungen zur Mittelwertbildung
 
Const Gyro_faktor = 1      'war 91
 
'****************************************************************************
 
 
Dim Ugemessen As Long      'Batteriespannung in V*100, kommt vom Motorcontr.
 
Dim Igemessen As Long      'Gesamter Motorstrom in mA, kommt vom Motorcontr.
 
 
Dim U As Integer
 
Dim I As Integer At U + 2
 
Dim K As Integer At U + 4
 
Dim Checksumme As Byte At U + 6
 
Dim Ende As Byte At U + 7
 
Dim Motormeldung(8) As Byte At U + 0 Overlay
 
 
Dim M1 As Byte At U + 0 Overlay
 
Dim M2 As Byte At U + 1 Overlay
 
Dim M3 As Byte At I + 0 Overlay
 
Dim M4 As Byte At I + 1 Overlay
 
Dim M5 As Byte At K + 0 Overlay
 
Dim M6 As Byte At K + 1 Overlay
 
Dim M7 As Byte At Checksumme Overlay
 
Dim M8 As Byte At Ende Overlay
 
 
'Variablen für die Telegramme an die Motorregler
 
Dim Checksum_rechts As Byte
 
Dim Checksum_links As Byte
 
Dim Richtung_rechts As Byte
 
Dim Richtung_links As Byte
 
Dim Pwm_rechts As Byte
 
Dim Pwm_links As Byte
 
Dim Zeiger_meldung As Byte
 
Dim Ta As Byte      'Interruptdauer. Wenn lang, dann ist der Zählwert nahe 255
 
Dim U_links As Integer      'Motorspannung linker Motor
 
Dim U_rechts As Integer      'Motorspannung rechter Motor
 
Dim I_links As Integer      'Motorstrom linker Motor
 
Dim I_rechts As Integer      'Motorstrom rechter Motor
 
Dim K_links As Integer      'Anzahl Kommutierungen linker Motor
 
Dim K_rechts As Integer      'Anzahl Kommutierungen rechter Motor
 
Dim B(5) As Byte
 
 
Dim Kilometer As Word
 
Dim Kilometermeldung(2) As Byte At Kilometer Overlay
 
 
Dim Akkustand As Integer
 
Dim Akkumeldung(2) As Byte At Akkustand Overlay
 
 
Dim Kmh As Integer
 
Dim Kmhmeldung(2) As Byte At Kmh Overlay
 
 
Dim Meter As Integer
 
Dim Metermeldung(2) As Byte At Meter Overlay
 
 
Dim Di As Single      'Distanz pro Kommutieren
 
Dim Kmhfaktor As Single
 
Dim Zentimeter As Single
 
Dim Strecke As Single      'Gefahrene Strecke während 1/100s
 
Dim Kx As Single      'Anzahl Kommutierungen für Streckenberechnung
 
Dim Kv As Single      'Anzahl Kommutierungen für Geschw.Berechnung
 
Dim Vbrems As Long      'Bremse bei Überlast oder zu hoher Geschw.
 
Dim Lbrems As Long
 
Dim Brems As Long
 
 
Dim P_faktor As Single
 
Dim Pf1 As Byte At P_faktor + 0 Overlay
 
Dim Pf2 As Byte At P_faktor + 1 Overlay
 
Dim Pf3 As Byte At P_faktor + 2 Overlay
 
Dim Pf4 As Byte At P_faktor + 3 Overlay
 
 
Dim I_faktor As Single
 
Dim If1 As Byte At I_faktor + 0 Overlay
 
Dim If2 As Byte At I_faktor + 1 Overlay
 
Dim If3 As Byte At I_faktor + 2 Overlay
 
Dim If4 As Byte At I_faktor + 3 Overlay
 
 
Dim D_faktor As Single
 
Dim Df1 As Byte At D_faktor + 0 Overlay
 
Dim Df2 As Byte At D_faktor + 1 Overlay
 
Dim Df3 As Byte At D_faktor + 2 Overlay
 
Dim Df4 As Byte At D_faktor + 3 Overlay
 
 
Dim Gyro_nick As Integer      'war word
 
Dim Gyro_nick1 As Byte At Gyro_nick + 0 Overlay
 
Dim Gyro_nick2 As Byte At Gyro_nick + 1 Overlay
 
 
Dim Gyro_roll As Integer      'war word
 
Dim Gyro_roll1 As Byte At Gyro_roll + 0 Overlay
 
Dim Gyro_roll2 As Byte At Gyro_roll + 1 Overlay
 
 
Dim Gyro_gier As Integer      'war word
 
Dim Gyro_gier1 As Byte At Gyro_gier + 0 Overlay
 
Dim Gyro_gier2 As Byte At Gyro_gier + 1 Overlay
 
 
Dim Gyro_roll_alt As Integer      'war word
 
Dim Gyro_nick_alt As Integer      'war word
 
 
Dim Acc_nick As Long
 
Dim Acc_nick1 As Byte At Acc_nick + 0 Overlay
 
Dim Acc_nick2 As Byte At Acc_nick + 1 Overlay
 
 
Dim Accnick As Integer
 
Dim Accnick_l As Byte At Accnick + 0 Overlay
 
Dim Accnick_h As Byte At Accnick + 1 Overlay
 
 
Dim Acc_roll As Long
 
Dim Acc_roll1 As Byte At Acc_roll + 0 Overlay
 
Dim Acc_roll2 As Byte At Acc_roll + 1 Overlay
 
 
Dim Accroll As Integer
 
Dim Accroll_l As Byte At Accroll + 0 Overlay
 
Dim Accroll_h As Byte At Accroll + 1 Overlay
 
 
Dim Acc_gier As Long
 
Dim Acc_gier1 As Byte At Acc_gier + 0 Overlay
 
Dim Acc_gier2 As Byte At Acc_gier + 1 Overlay
 
 
Dim Accgier As Integer
 
Dim Accgier_l As Byte At Accgier + 0 Overlay
 
Dim Accgier_h As Byte At Accgier + 1 Overlay
 
 
Dim Sum_acc_roll As Long
 
Dim Sum_acc_nick As Long
 
Dim Sum_gyro_roll As Long
 
Dim Sum_gyro_nick As Long
 
Dim Korr_acc_roll As Long
 
Dim Korr_acc_nick As Long
 
 
'Long ==> Long Integer
 
Dim Mit_acc_nick_s As Long      'Summierter Neigung vorwärts Mittelwert
 
Dim Mit_gyro_roll As Long
 
Dim Mit_gyro_nick As Long
 
Dim Sig_gyro_roll As Long
 
Dim Sig_gyro_nick As Long
 
 
Dim Stellwert As Single
 
Dim Stellwert1 As Byte At Stellwert + 0 Overlay
 
Dim Stellwert2 As Byte At Stellwert + 1 Overlay
 
Dim Stellwert3 As Byte At Stellwert + 2 Overlay
 
Dim Stellwert4 As Byte At Stellwert + 3 Overlay
 
 
Dim Mrg As Single
 
Dim Mrg1 As Byte At Mrg + 0 Overlay
 
Dim Mrg2 As Byte At Mrg + 1 Overlay
 
Dim Mrg3 As Byte At Mrg + 2 Overlay
 
Dim Mrg4 As Byte At Mrg + 3 Overlay
 
 
Dim Mra As Single
 
Dim Mra1 As Byte At Mra + 0 Overlay
 
Dim Mra2 As Byte At Mra + 1 Overlay
 
Dim Mra3 As Byte At Mra + 2 Overlay
 
Dim Mra4 As Byte At Mra + 3 Overlay
 
 
Dim Kksum As Single
 
Dim Kksum1 As Byte At Kksum + 0 Overlay
 
Dim Kksum2 As Byte At Kksum + 1 Overlay
 
Dim Kksum3 As Byte At Kksum + 2 Overlay
 
Dim Kksum4 As Byte At Kksum + 3 Overlay
 
 
Dim Gyronick As Long
 
Dim Gyronick1 As Byte At Gyronick + 0 Overlay
 
Dim Gyronick2 As Byte At Gyronick + 1 Overlay
 
Dim Gyronick3 As Byte At Gyronick + 2 Overlay
 
Dim Gyronick4 As Byte At Gyronick + 3 Overlay
 
 
Dim Mp_faktor As Single
 
Dim Mpf1 As Byte At Mp_faktor + 0 Overlay
 
Dim Mpf2 As Byte At Mp_faktor + 1 Overlay
 
Dim Mpf3 As Byte At Mp_faktor + 2 Overlay
 
Dim Mpf4 As Byte At Mp_faktor + 3 Overlay
 
 
Dim Mv_faktor As Single
 
Dim Mvf1 As Byte At Mv_faktor + 0 Overlay
 
Dim Mvf2 As Byte At Mv_faktor + 1 Overlay
 
Dim Mvf3 As Byte At Mv_faktor + 2 Overlay
 
Dim Mvf4 As Byte At Mv_faktor + 3 Overlay
 
 
Dim Mpl_faktor As Single
 
Dim Mplf1 As Byte At Mpl_faktor + 0 Overlay
 
Dim Mplf2 As Byte At Mpl_faktor + 1 Overlay
 
Dim Mplf3 As Byte At Mpl_faktor + 2 Overlay
 
Dim Mplf4 As Byte At Mpl_faktor + 3 Overlay
 
 
Dim Mvl_faktor As Single
 
Dim Mvlf1 As Byte At Mvl_faktor + 0 Overlay
 
Dim Mvlf2 As Byte At Mvl_faktor + 1 Overlay
 
Dim Mvlf3 As Byte At Mvl_faktor + 2 Overlay
 
Dim Mvlf4 As Byte At Mvl_faktor + 3 Overlay
 
 
Dim P_tacho As Single
 
Dim Tachomeldung(30) As Byte At P_tacho Overlay
 
Dim T1 As Byte At P_tacho + 0 Overlay
 
Dim T2 As Byte At P_tacho + 1 Overlay
 
Dim T3 As Byte At P_tacho + 2 Overlay
 
Dim T4 As Byte At P_tacho + 3 Overlay
 
 
Dim T5 As Byte At P_tacho + 4 Overlay
 
Dim T6 As Byte At P_tacho + 5 Overlay
 
Dim T7 As Byte At P_tacho + 6 Overlay
 
Dim T8 As Byte At P_tacho + 7 Overlay
 
Dim I_tacho As Single At P_tacho + 4 Overlay
 
 
Dim T9 As Byte At P_tacho + 8 Overlay
 
Dim T10 As Byte At P_tacho + 9 Overlay
 
Dim T11 As Byte At P_tacho + 10 Overlay
 
Dim T12 As Byte At P_tacho + 11 Overlay
 
Dim D_tacho As Single At P_tacho + 8 Overlay
 
 
Dim T13 As Byte At P_tacho + 12 Overlay
 
Dim T14 As Byte At P_tacho + 13 Overlay
 
Dim T15 As Byte At P_tacho + 14 Overlay
 
Dim T16 As Byte At P_tacho + 15 Overlay
 
Dim Mp_tacho As Single At P_tacho + 12 Overlay
 
 
Dim T17 As Byte At P_tacho + 16 Overlay
 
Dim T18 As Byte At P_tacho + 17 Overlay
 
Dim T19 As Byte At P_tacho + 18 Overlay
 
Dim T20 As Byte At P_tacho + 19 Overlay
 
Dim Mv_tacho As Single At P_tacho + 16 Overlay
 
 
Dim T21 As Byte At P_tacho + 20 Overlay
 
Dim T22 As Byte At P_tacho + 21 Overlay
 
Dim T23 As Byte At P_tacho + 22 Overlay
 
Dim T24 As Byte At P_tacho + 23 Overlay
 
Dim Mpl_tacho As Single At P_tacho + 20 Overlay
 
 
Dim T25 As Byte At P_tacho + 24 Overlay
 
Dim T26 As Byte At P_tacho + 25 Overlay
 
Dim T27 As Byte At P_tacho + 26 Overlay
 
Dim T28 As Byte At P_tacho + 27 Overlay
 
Dim Mvl_tacho As Single At P_tacho + 24 Overlay
 
 
Dim T29 As Byte At P_tacho + 28 Overlay
 
Dim T30 As Byte At P_tacho + 29 Overlay
 
Dim Tdummy As Integer At P_tacho + 28 Overlay
 
 
Dim Wwert As Word
 
Dim Wwert1 As Byte At Wwert + 0 Overlay
 
Dim Wwert2 As Byte At Wwert + 1 Overlay
 
 
Dim Gyro_gier_alt As Integer      'war word
 
Dim Sum_gyro_gier As Long
 
Dim Mit_gyro_gier As Long
 
Dim Sig_gyro_gier As Long
 
 
Dim Werteneu As Byte
 
 
Dim Mit_acc_roll As Long      'Neigungsmittelwert seitwärts
 
Dim Mit_acc_roll1 As Byte At Mit_acc_roll + 0 Overlay
 
Dim Mit_acc_roll2 As Byte At Mit_acc_roll + 1 Overlay
 
Dim Mit_acc_roll3 As Byte At Mit_acc_roll + 2 Overlay
 
Dim Mit_acc_roll4 As Byte At Mit_acc_roll + 3 Overlay
 
 
Dim Mit_acc_nick As Long      'Neigungsmittelwert vorwärts
 
Dim Mit_acc_nick1 As Byte At Mit_acc_nick + 0 Overlay
 
Dim Mit_acc_nick2 As Byte At Mit_acc_nick + 1 Overlay
 
Dim Mit_acc_nick3 As Byte At Mit_acc_nick + 2 Overlay
 
Dim Mit_acc_nick4 As Byte At Mit_acc_nick + 3 Overlay
 
 
Dim Null_roll As Long
 
Dim Null_roll1 As Byte At Null_roll + 0 Overlay
 
Dim Null_roll2 As Byte At Null_roll + 1 Overlay
 
Dim Null_roll3 As Byte At Null_roll + 2 Overlay
 
Dim Null_roll4 As Byte At Null_roll + 3 Overlay
 
 
Dim Null_nick As Long
 
Dim Null_nick1 As Byte At Null_nick + 0 Overlay
 
Dim Null_nick2 As Byte At Null_nick + 1 Overlay
 
Dim Null_nick3 As Byte At Null_nick + 2 Overlay
 
Dim Null_nick4 As Byte At Null_nick + 3 Overlay
 
 
Dim Mit_regelzeit_ges As Single
 
 
Dim Lagefehler As Long
 
'Die Zeit in 1/100s die benötigt wird bis die Nullage erreicht ist
 
Dim Regelzeit As Word
 
Dim Regelzeitmax As Word
 
Dim Mit_acc_roll_max As Long
 
Dim Mit_acc_nick_max As Long
 
Dim Mit_acc_roll_min As Long
 
Dim Mit_acc_nick_min As Long
 
 
Dim Pwm_gesamt As Single
 
Dim Pwm_rechts_max As Byte
 
Dim Pwm_links_max As Byte
 
Dim Intcount As Byte
 
Dim K_diff As Single
 
Dim K_sum As Single
 
Dim K_diff_min As Single
 
Dim K_diff_max As Single
 
Dim Pwm_lenk_rechts As Integer
 
Dim Pwm_lenk_links As Integer
 
 
Dim Lenkvorgabe As Single
 
Dim Mp_anpassung As Single
 
Dim Mv_anpassung As Single
 
Dim Mpl_anpassung As Single
 
Dim Mvl_anpassung As Single
 
Dim K_sum_anpassung As Single
 
 
Dim Wdummy1 As Word
 
Dim Ldummyi As Long
 
Dim Ldummy1 As Long
 
Dim Ldummy2 As Long
 
Dim Bdummy1 As Byte
 
Dim Idummy1 As Integer
 
Dim Sdummy1 As Single
 
 
Dim Antriebaus As Byte
 
Dim Notaus As Byte
 
Dim Sensor_ok As Byte      'Zeigt an ob die Mittelwerte der Gyros stabil stehen
 
Dim Sensor_ok_count As Byte
 
Dim Ltest As Byte
 
 
Dim Imin As Long      'Kleinster gemessener Motorstrom (größte Rückspeisung)
 
Dim Imax As Long      'größter gemessener Motorstrom
 
Dim Summe_as_entladen As Long
 
Dim Summe_mah_entladen As Long
 
Dim Summe_as_laden As Long
 
Dim Summe_mah_laden As Long
 
Dim Akkukap As Long      'Akkukapazität 0...100 %
 
Dim Akku1 As Long      '80% Grenze
 
Dim Akku2 As Long      '60% Grenze
 
Dim Akku3 As Long      '40% Grenze
 
Dim Akku4 As Long      '20% Grenze
 
Dim Akku5 As Long      '0% Grenze
 
Dim Erzeugt As Long      'Erzeugte Ladung in mA-Stunden
 
Dim Verbraucht As Long      'Verbrauchte Ladung in mA-Stunden
 
 
'Single Variablen um die Prozente rechnen zu können
 
Dim Akkuinhalt As Single      'wie AkkuKap
 
Dim Akkuverbrauch As Single
 
Dim Akkuprozent As Single
 
 
Dim Bzeit As Long      'Beruhigungszeit von Gyro und Accelerometer
 
Dim Bstate As Byte      'Status der Beruhigungszeit von Gyro und Accelerometer
 
Dim Frei As Byte      'hat es etwas mit Gyro und Acc zu tun?
 
Dim Timeout As Byte
 
Dim S_err As Byte      'Serielle Schnittstellen Error
 
Dim Seriell_err_links As Word      'COM error links
 
Dim Seriell_err_rechts As Word      'COM error rechts
 
Dim Tamax As Byte      'Maximalwert von Ta
 
Dim Fusscount As Word      'Fusschalter nicht betätigt ==> zeitverzögerung
 
Dim Blinkcount As Byte      'verschiedene Blinkraten
 
Dim Lenkerstellung As Single
 
Dim Lenkstellwert As Single
 
Dim Lenkfehler As Single
 
 
'Texte für den Unfalldatenschreiber (als Text im eeprom)
 
Dim Utext As String * 32
 
 
Dim Ugrund As String * 32      'Auslösegrund
 
Dim Text As String * 16      'Allg. Ttext
 
Dim Min_v As Integer      'Minimalwert der Geschwindigkeit
 
Dim Max_v As Integer      'Maximalwert der Geschwindigkeit
 
 
Dim Tachocount As Byte      'Schleifenzähler um Werte an Display zu schicken
 
Dim Fussschalter As Byte      'Die beiden Fussschalter
 
Dim Adc0 As Word      'Analogwert Fussschalter 1
 
Dim Adc1 As Word      'Analogwert Fussschalter 2
 
 
Dim Slaveadress As Byte      'Adress of the I2C slave to read or write
 
Dim Subadress As Byte      'the I2C register to read or write
 
Dim Databyte As Byte      'I2C Byte to read or write
 
 
Dim Resetbtndone As Byte
 
 
Dim Nummotors As Byte      '1 oder 2
 
Dim Errorword As Word      'See Delphi Dashboard.prj
 
Dim Errorword1 As Byte At Errorword + 0 Overlay
 
Dim Errorword2 As Byte At Errorword + 1 Overlay
 
 
Led1 = 0
 
Led2 = 0
 
 
Led3 = 1
 
Led4 = 1
 
Led5 = 1
 
Led6 = 1
 
Led7 = 1
 
 
'***************** Check! *********************
 
Nummotors = 1
 
'***************** Check! *********************
 
 
'Ein paar feste Werte vorab berechnen:
 
Di = Radumpfang / Kom_pro_u
 
'Eigentlich 3.6 aber bei der Mittelwertbildung entsteht der 4-Fache Wert,
 
'darum 9, und es ergibt sich automateisch V in 0.1km/h
 
'Unbenutzte Pins auf Masse legen
 
Kmhfaktor = Di * 9
 
 
'Sensorboard Schalten
 
'Sensor_aus = 0
 
'Sensor_test = 0
 
 
Config Adc = Single , Prescaler = Auto , Reference = Internal_2.56      'Avcc
 
'Start Adc not required because ADC will start immediately after Config ADC
 
 
'Inititialise I2C-Bus
 
I2cinit
 
Config Twi = 200000      ' wanted clock frequency in Hertz
 
'will set TWBR and TWSR
 
'Twbr = 12 'bit rate register
 
'Twsr = 0 'pre scaler bits
 
 
'TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart !
 
Twcr = &B00000100
 
 
Gosub Init_gyro
 
Gosub Init_acc
 
 
'Wartezeit bis die Motorregler soweit sind
 
Readeeprom Max_v , $2f0
 
Readeeprom Min_v , $2f2
 
Readeeprom Summe_as_entladen , $300      'Entnommene Wh und Ws aus EEPROM lesen
 
Led3 = 0
 
Waitms 150
 
Readeeprom Summe_mah_entladen , $310
 
Led4 = 0
 
Waitms 150
 
Readeeprom Summe_as_laden , $320
 
Led5 = 0
 
Waitms 150
 
Readeeprom Summe_mah_laden , $330
 
Led6 = 0
 
Waitms 150
 
Readeeprom Akkukap , $340
 
Led7 = 0
 
Waitms 150
 
Readeeprom Kilometer , $350
 
Readeeprom Meter , $360
 
Readeeprom Zentimeter , $370
 
 
'<Faktoren für den PID-Regler einlesen>
 
P_faktor = 0.0033      'Readeeprom P_faktor , $380
 
I_faktor = 0.00006      'Readeeprom I_faktor , $384
 
D_faktor = 0.08      'Readeeprom D_faktor , $388
 
Mp_faktor = 0.006      'Readeeprom Mp_faktor , $38c
 
Mv_faktor = 0      'Readeeprom Mv_faktor , $390
 
Mpl_faktor = 0      'Readeeprom Mpl_faktor , $394
 
Mvl_faktor = 0      'Readeeprom Mvl_faktor , $398
 
 
'Sinnvolle Werte vorbelegen
 
If P_faktor < 0 Or P_faktor > 1 Then P_faktor = 0.0033
 
If I_faktor < 0 Or I_faktor > 1 Then I_faktor = 0.00006
 
If D_faktor < 0 Or D_faktor > 1 Then D_faktor = 0.08
 
If Mp_faktor < 0 Or Mp_faktor > 1 Then Mp_faktor = 0.006
 
 
If Mv_faktor < 0 Or Mv_faktor > 1 Then Mv_faktor = 0
 
If Mpl_faktor < 0 Or Mpl_faktor > 1 Then Mpl_faktor = 0
 
If Mvl_faktor < 0 Or Mvl_faktor > 1 Then Mvl_faktor = 0
 
 
'</Faktoren für den PID-Regler einlesen>
 
If Kilometer = $ffff Then      'Kommt bei frischem EEPROM vor
 
Zentimeter = 0
 
Meter = 0
 
Kilometer = 0
 
Min_v = 0
 
Max_v = 0
 
End If
 
'Bei Fehlerhaften Werten aus dem EEPROM einfach 10000mAh als Vorgabe
 
If Akkukap <= 0 Then Akkukap = 10000
 
 
#if Systemvoltage = 14      'Nur zum Test mit Netzteil
 
If Akkukap > 32000 Then Akkukap = 100
 
#endif
 
 
#if Systemvoltage = 24
 
If Akkukap > 32000 Then Akkukap = 100
 
#endif
 
 
#if Systemvoltage = 36
 
If Akkukap > 32000 Then Akkukap = 100
 
#endif
 
 
#if Systemvoltage = 48
 
If Akkukap > 32000 Then Akkukap = 100
 
#endif
 
 
Call Akkugrenzen
 
Fusscount = 0
 
Notaus = 0
 
Readeeprom Max_v , $2f0
 
Readeeprom Min_v , $2f4
 
Config Watchdog = 128      'mSec
 
 
'Maximalwerte für Datenschreiber/Notauserkennung auf 0 setzen
 
Regelzeit = 0
 
Regelzeitmax = 0
 
Mit_acc_nick_max = 0
 
Mit_acc_roll_max = 0
 
Pwm_rechts_max = 0
 
Pwm_links_max = 0
 
K_diff_min = 0
 
K_diff_max = 0
 
Richtung_links = 2      'Leerlauf
 
Richtung_rechts = 2      'Leerlauf
 
Pwm_links = 0
 
Pwm_rechts = 0
 
Pwm_gesamt = 0
 
Mit_acc_nick_s = 0
 
Lenkerstellung = 0
 
 
K_rechts = 0
 
K_links = 0
 
Seriell_err_links = 0
 
Seriell_err_rechts = 0
 
'Vrbelegen um zu sehen ob es einen Notaus ohne Grund gibt
 
Ugrund = "----------------"
 
 
Disable Interrupts
 
 
'Timer wird vorgeladen um die gewünschte Zykluszeit nach
 
'Timerüberlauf zu erreichen
 
'Nachteil: Timer Count ist nicht exakt gleich der Zykluszeit
 
On Timer0 Regel_interrupt
 
Config Timer0 = Timer , Prescale = 1024      ' (1/20MHz) * 1024 = 51,2uS pro Tick
 
Enable Timer0
 
 
Antriebaus = 1      'Beim Start ist immer alles aus
 
Enable Interrupts
 
Waitms 100
 
 
'< Sicherheitstest. CPU will Reset if one of these conditions are met
 
Start Watchdog      'nach 128mS wird CPU Reset ausgelöst
 
If Resetbtn = 0 Then Wait 10
 
If Antriebaus = 0 Then Wait 10
 
'If Ugemessen < 1000 Then Wait 10      '10V
 
'If Ugemessen > 5500 Then Wait 10      '55V
 
Stop Watchdog
 
'< Sicherheitstest
 
 
'Prüfung ob Akku gerade geladen:
 
#if Systemvoltage = 14
 
'Sensoren ausschalten wenn am Ladegerät oder zu Testzwecken
 
'If Ugemessen < 2200 Then
 
' Sensor_aus = 1
 
'Else
 
' Sensor_aus = 0
 
'End If
 
Errorword.0 = 1
 
 
While Ugemessen < 1100      'Unterspannung oder am Ladegerät
 
  Call Flashled(0 , 50)
 
Wend
 
If Ugemessen > 1520 Then      'Akku ist ganzgeladen
 
#endif
 
 
#if Systemvoltage = 24
 
'Sensoren ausschalten wenn am Ladegerät oder zu Testzwecken
 
'If Ugemessen < 2200 Then
 
' Sensor_aus = 1
 
'Else
 
' Sensor_aus = 0
 
'End If
 
Errorword.1 = 1
 
While Ugemessen < 2200      'Unterspannung oder am Ladegerät
 
  Call Flashled(0 , 50)
 
Wend
 
If Ugemessen > 2650 Then      'Akku ist ganzgeladen
 
#endif
 
 
#if Systemvoltage = 36
 
'Sensoren ausschalten wenn am Ladegerät oder zu Testzwecken
 
'If Ugemessen < 3300 Then
 
' Sensor_aus = 1
 
'Else
 
' Sensor_aus = 0
 
'End If
 
Errorword.2 = 1
 
While Ugemessen < 3300      'Unterspannung oder am Ladegerät
 
  Call Flashled(0 , 50)
 
Wend
 
If Ugemessen > 4350 Then      'Akku ist ganzgeladen
 
#endif
 
 
#if Systemvoltage = 48
 
'Sensoren ausschalten wenn am Ladegerät oder zu Testzwecken
 
'If Ugemessen < 2400 Then
 
' Sensor_aus = 1
 
'Else
 
' Sensor_aus = 0
 
'End If
 
Errorword.3 = 1
 
While Ugemessen < 4300      'Unterspannung oder am Ladegerät
 
  Call Flashled(0 , 50)
 
Wend
 
If Ugemessen > 5280 Then      'Akku ist ganzgeladen
 
#endif
 
 
  'Interruts abschalten damit die folgenden Zeilen nicht gerade jetzt vom
 
  'Interrupt unterbrochen werden.
 
  Disable Interrupts
 
  Waitms 50
 
  Summe_as_entladen = 0
 
  Summe_mah_entladen = 0
 
  Summe_as_laden = 0
 
  Summe_mah_laden = 0
 
  Enable Interrupts
 
End If
 
 
Led3 = 0
 
Led4 = 0
 
Led5 = 0
 
Led6 = 0
 
Led7 = 0
 
 
Goto Jp
 
 
'Summen_vorbelegen:
 
Do
 
Errorword.4 = 1
 
' Acc_roll = Acc_roll * 100
 
' Acc_nick = Acc_nick * 100
 
 
'Sum_gyro_roll = Gyro_roll * Gyro_anz
 
'Sum_gyro_nick = Gyro_nick * Gyro_anz
 
'Sum_gyro_gier = Gyro_gier * Gyro_anz
 
 
Gyro_roll_alt = Gyro_roll
 
Gyro_nick_alt = Gyro_nick
 
Gyro_gier_alt = Gyro_gier
 
 
Mit_gyro_roll = Gyro_roll
 
Mit_gyro_nick = Gyro_nick
 
Mit_gyro_gier = Gyro_gier
 
 
Sum_acc_roll = Acc_roll * Acc_anz
 
Sum_acc_nick = Acc_nick * Acc_anz
 
 
Waitms 200
 
Toggle Led5
 
Toggle Led6
 
Waitms 200
 
Toggle Led5
 
Toggle Led6
 
Loop Until Sig_gyro_nick >= -3 And Sig_gyro_nick <= 3 And Sig_gyro_roll >= -3 And Sig_gyro_roll <= 3 And Sig_gyro_gier >= -3 And Sig_gyro_gier <= 3
 
Errorword.4 = 0
 
 
Jp:
 
 
Call Resetdata      'and Enable Interrupt
 
Resetbtndone = 0
 
 
Do
 
Errorword.5 = 1
 
'<Sicherheitstest Sensoren>
 
If Antriebaus = 1 Then
 
  If Intcount <> Ltest Then
 
  Ltest = Intcount
 
  Sensor_ok = 0
 
  If Sensor_ok_count > 0 Then Decr Sensor_ok_count
 
  '1. Es darf keine nennenswerte Drehbewegung erkannt werden!
 
 
  If Sig_gyro_nick < -3 Then Sensor_ok_count = 50
 
  If Sig_gyro_nick > 3 Then Sensor_ok_count = 50
 
  If Sig_gyro_roll < -3 Then Sensor_ok_count = 50
 
  If Sig_gyro_roll > 3 Then Sensor_ok_count = 50
 
  'Nach mehrfachen Drehungen könnte der Mittelwert etwas
 
  'verschoben sein. Darum hier 12
 
  If Sig_gyro_gier < -15 Then Sensor_ok_count = 50
 
  If Sig_gyro_gier > 15 Then Sensor_ok_count = 50
 
 
  '2. Die Werte dürfen nicht verrauscht sein
 
  Ldummy2 = Mit_acc_nick + 500
 
  If Acc_nick > Ldummy2 Then Sensor_ok_count = 50
 
  Ldummy2 = Mit_acc_nick - 500
 
  If Acc_nick < Ldummy2 Then Sensor_ok_count = 50
 
  Ldummy2 = Mit_acc_roll + 500
 
  If Acc_roll > Ldummy2 Then Sensor_ok_count = 50
 
  Ldummy2 = Mit_acc_roll - 500
 
  If Acc_roll < Ldummy2 Then Sensor_ok_count = 50
 
 
  '3. Die Werte müssen ungefähr in einer legalen Nullage sein.
 
  If Null_roll < O_roll_u Then Sensor_ok_count = 50
 
  If Null_roll > O_roll_o Then Sensor_ok_count = 50
 
  If Null_nick < O_nick_u Then Sensor_ok_count = 50
 
  If Null_nick > O_nick_o Then Sensor_ok_count = 50
 
 
  'Bedingungen während 50 Messungen (0.5s) eingehalten
 
  If Sensor_ok_count = 0 Then Sensor_ok = 1
 
  End If
 
Else
 
  Sensor_ok = 0
 
End If
 
'</Sicherheitstest Sensoren>
 
 
'<Batterieanzeige>
 
'alles unter 36V Leerlaufspannung ist LEER
 
If Ugemessen > Akkufastleer Then
 
  If Verbraucht > Akkukap Then
 
  'Einfach mal annehmen daß noch mehr als angezeigt im Akku ist
 
  Akkukap = Verbraucht + 1
 
  Call Akkugrenzen
 
  End If
 
End If
 
 
If Antriebaus = 1 Then
 
  Errorword.6 = 1
 
Else
 
  Errorword.6 = 0
 
End If
 
 
If Notaus = 1 Then
 
  Errorword.7 = 1
 
Else
 
  Errorword.7 = 0
 
End If
 
 
'Blinken wenn Gyros nicht bereit
 
If Antriebaus = 1 Then
 
  If Ugemessen > Akkuleer Then
 
  If Verbraucht > Akkukap Then
 
    'annehmen dass noch mehr als angezeigt im Akku ist
 
    Akkukap = Verbraucht + 20
 
    Call Akkugrenzen
 
  End If
 
  End If
 
  If Sensor_ok = 1 Then
 
  If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1
 
  If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1
 
  If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1
 
  If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1
 
  If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1
 
  Else
 
  If Frei = 1 Then      'ca. 2 Hz
 
    Blinkcount = Intcount
 
    If Blinkcount > 50 Then Blinkcount = Blinkcount - 50
 
  Else
 
    Blinkcount = Intcount / 2
 
  End If
 
  If Blinkcount > 40 Then      'ca. 1 Hz
 
    If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1
 
    If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1
 
    If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1
 
    If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1
 
    If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1
 
  Else
 
    Led7 = 1
 
    Led6 = 1
 
    Led5 = 1
 
    Led4 = 1
 
    Led3 = 1
 
  End If
 
  End If
 
Else
 
  Errorword.6 = 0
 
  If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1
 
  If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1
 
  If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1
 
  If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1
 
  If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1
 
End If
 
'</Batterieanzeige>
 
 
'< Maximalwerte Für Betriebsdatenschreiber>
 
If Igemessen < Imin Then Imin = Igemessen      'Nur zur Information
 
If Igemessen > Imax Then Imax = Igemessen      'Nur zur Information
 
If Regelzeit > Regelzeitmax Then Regelzeitmax = Regelzeit
 
If Mit_acc_nick > Mit_acc_nick_max Then Mit_acc_nick_max = Mit_acc_nick
 
If Mit_acc_roll > Mit_acc_roll_max Then Mit_acc_roll_max = Mit_acc_roll
 
If Mit_acc_nick < Mit_acc_nick_min Then Mit_acc_nick_min = Mit_acc_nick
 
If Mit_acc_roll < Mit_acc_roll_min Then Mit_acc_roll_min = Mit_acc_roll
 
If Pwm_links > Pwm_links_max Then Pwm_links_max = Pwm_links
 
If Pwm_rechts > Pwm_rechts_max Then Pwm_rechts_max = Pwm_rechts
 
If K_diff > K_diff_max Then K_diff_max = K_diff
 
If K_diff < K_diff_min Then K_diff_min = K_diff
 
If Ta > Tamax Then Tamax = Ta
 
'</Maximalwerte für Betriebsdatenschreiber>
 
 
'Debounce macht dasselbe, allerdings stockt der Programmfluss
 
Debounce Resetbtn , 0 , Onresetbtn , Sub
 
 
Goto Skipit
 
 
If Resetbtndone = 0 Then
 
  If Resetbtn = 0 Then
 
  Resetbtndone = 1
 
  Call Onresetbtn
 
  Resetbtndone = 2
 
  Else
 
  End If
 
Else
 
  If Resetbtndone = 2 Then Resetbtndone = 0
 
End If
 
Skipit:
 
 
If Intcount > 80 Then Led1 = 1 Else Led1 = 0      'Sekundenblinken
 
'Daran lässt sich leicht erkennen ob noch alles normal läuft.
 
Loop
 
End
 
 
'**********************************************************************
 
'Ab hier Subroutinen und  Interrupts
 
'**********************************************************************
 
Sub Akkugrenzen
 
'Grenzwerte für die Akku-LEDs berechnen
 
Ldummy1 = Akkukap / 5
 
Akku1 = Ldummy1
 
Akku2 = 2 * Ldummy1
 
Akku3 = 3 * Ldummy1
 
Akku4 = 4 * Ldummy1
 
Akku5 = 5 * Ldummy1
 
End Sub
 
 
Sub Unfalldatenschreiber
 
Waitms 10
 
Utext = Str(regelzeit)
 
Utext = "Rz=" + Utext
 
Logtext 0 , Utext
 
Utext = Str(mit_acc_nick_max)
 
Utext = "Nick max=" + Utext
 
Logtext $10 , Utext
 
Utext = Str(mit_acc_nick)
 
Utext = "Nick=" + Utext
 
Logtext $20 , Utext
 
Utext = Str(mit_acc_nick_min)
 
Utext = "Nick min=" + Utext
 
Logtext $30 , Utext
 
Utext = Str(mit_acc_roll_max)
 
Utext = "Roll max=" + Utext
 
Logtext $40 , Utext
 
Utext = Str(mit_acc_roll)
 
Utext = "Roll=" + Utext
 
Logtext $50 , Utext
 
Utext = Str(mit_acc_roll_min)
 
Utext = "Roll min=" + Utext
 
Logtext $60 , Utext
 
Utext = Str(pwm_rechts)
 
Utext = "PWM re=" + Utext
 
Logtext $70 , Utext
 
Utext = Str(pwm_links)
 
Utext = "PWM li=" + Utext
 
Logtext $80 , Utext
 
Utext = Str(u_rechts)
 
Utext = "U re=" + Utext
 
Logtext $90 , Utext
 
Utext = Str(u_links)
 
Utext = "U li=" + Utext
 
Logtext $a0 , Utext
 
Utext = Str(ta)
 
Utext = "Ta=" + Utext
 
Logtext $b0 , Utext
 
Utext = Str(seriell_err_links)
 
Utext = Utext + "|"
 
Utext = Utext + Str(seriell_err_rechts)
 
Utext = "S =" + Utext
 
Logtext $c0 , Utext
 
Utext = Ugrund
 
Logtext $d0 , Utext
 
End Sub
 
 
Sub Betriebsdatenschreiber
 
'Ob die Wartezeiten beim EEprom schreiben nötig sind ist nicht sicher.
 
'Mit den Wartezeiten treten aber keine Fehler bei den Werten mehr auf.
 
'Möglich, daß dies auch durch eine andere Änderung bewirkt wurde.
 
Writeeeprom Max_v , $2f0
 
Writeeeprom Min_v , $2f2
 
Zentimeter = Int(zentimeter)      'Keine Millimeter schreiben
 
Writeeeprom Summe_as_entladen , $300
 
Writeeeprom Summe_mah_entladen , $310
 
Writeeeprom Summe_as_laden , $320
 
Writeeeprom Summe_mah_laden , $330
 
Writeeeprom Akkukap , $340
 
Writeeeprom Kilometer , $350
 
Writeeeprom Meter , $360
 
Writeeeprom Zentimeter , $370
 
If Werteneu = 1 Then      'Nur wenn das Einstellklavier gesteckt ist.
 
  Writeeeprom P_faktor , $380
 
  Writeeeprom I_faktor , $384
 
  Writeeeprom D_faktor , $388
 
  Writeeeprom Mp_faktor , $38c
 
  Writeeeprom Mv_faktor , $390
 
  Writeeeprom Mpl_faktor , $394
 
  Writeeeprom Mvl_faktor , $398
 
  Werteneu = 0
 
End If
 
 
Utext = Str(pwm_rechts_max)
 
Utext = "PWM r max=" + Utext
 
Logtext $e0 , Utext
 
Utext = Str(pwm_links_max)
 
Utext = "PWM l max=" + Utext
 
Logtext $f0 , Utext
 
Utext = Str(ugemessen)
 
Utext = "U=" + Utext
 
Logtext $100 , Utext
 
Utext = Str(imin)
 
Utext = "Imin=" + Utext
 
Logtext $110 , Utext
 
Utext = Str(imax)
 
Utext = "Imax=" + Utext
 
Logtext $120 , Utext
 
Utext = Str(summe_mah_entladen)
 
Utext = "-mAh" + Utext
 
Logtext $130 , Utext
 
Utext = Str(summe_mah_laden)
 
Utext = "+mAh=" + Utext
 
Logtext $140 , Utext
 
Utext = Str(verbraucht)
 
Utext = "    =" + Utext
 
Logtext $150 , Utext
 
Utext = Str(akkukap)
 
Utext = "Kap=" + Utext
 
Logtext $160 , Utext
 
Utext = Str(kilometer)
 
Utext = "Km=" + Utext
 
Logtext $170 , Utext
 
Utext = Str(meter)
 
Utext = "M=" + Utext
 
Logtext $180 , Utext
 
Utext = Str(zentimeter)
 
Utext = "cm=" + Utext
 
Logtext $190 , Utext
 
Utext = Str(regelzeitmax)
 
Utext = "Rz Max=" + Utext
 
Logtext $1a0 , Utext
 
Utext = Str(null_roll)
 
Utext = "Null_R=" + Utext
 
Logtext $1b0 , Utext
 
Utext = Str(null_nick)
 
Utext = "null_N=" + Utext
 
Logtext $1c0 , Utext
 
Utext = Str(p_faktor)
 
Utext = "P=" + Utext
 
Logtext $1d0 , Utext
 
Utext = Str(i_faktor)
 
Utext = "I=" + Utext
 
Logtext $1e0 , Utext
 
Utext = Str(d_faktor)
 
Utext = "D=" + Utext
 
Logtext $1f0 , Utext
 
Utext = Str(mp_faktor)
 
Utext = "M=" + Utext
 
Logtext $200 , Utext
 
Utext = Str(k_diff_min)
 
Utext = "K min=" + Utext
 
Logtext $210 , Utext
 
Utext = Str(k_diff_max)
 
Utext = "K max=" + Utext
 
Logtext $220 , Utext
 
Utext = Str(seriell_err_links)
 
Utext = "S l=" + Utext
 
Logtext $230 , Utext
 
Utext = Str(seriell_err_rechts)
 
Utext = "S r=" + Utext
 
Logtext $240 , Utext
 
Utext = Str(tamax)
 
Utext = "Ta_Max=" + Utext
 
Logtext $250 , Utext
 
Utext = Str(max_v)
 
Utext = "V_Max=" + Utext
 
Logtext $260 , Utext
 
Utext = Str(min_v)
 
Utext = "V_Min=" + Utext
 
Logtext $270 , Utext
 
End Sub
 
 
Sub Onresetbtn
 
If Antriebaus = 1 Then
 
  'alles unter 36V Leerlaufspannung ist LEER
 
  If Ugemessen > Akkuleer Then
 
  If Sensor_ok = 1 Then      'Prüfen ob Gyros noch driften
 
    'Interupts abschalten damit Fusscount nicht gerade jetzt
 
    'decrementiert wird
 
    Call Resetdata
 
  Else
 
    If Null_nick > O_nick_o And Null_nick < O_nick_oo Then
 
    If Bzeit = 500 Then
 
      Bstate = 1
 
      Bzeit = 0
 
    Else
 
      If Bstate = 1 Then
 
      If Bzeit < 50 Then
 
        Disable Interrupts
 
        Utext = "                "
 
        Logtext $00 , Utext
 
        Logtext $10 , Utext
 
        Logtext $20 , Utext
 
        Logtext $30 , Utext
 
        Logtext $40 , Utext
 
        Logtext $50 , Utext
 
        Logtext $60 , Utext
 
        Logtext $70 , Utext
 
        Logtext $80 , Utext
 
        Logtext $90 , Utext
 
        Logtext $a0 , Utext
 
        Logtext $b0 , Utext
 
        Logtext $c0 , Utext
 
        Logtext $d0 , Utext
 
        Logtext $e0 , Utext
 
        Logtext $f0 , Utext
 
        Logtext $100 , Utext
 
        Logtext $110 , Utext
 
        Logtext $120 , Utext
 
        Logtext $130 , Utext
 
        Logtext $140 , Utext
 
        Logtext $150 , Utext
 
        Logtext $160 , Utext
 
        Logtext $170 , Utext
 
        Logtext $180 , Utext
 
        Logtext $190 , Utext
 
        Logtext $1a0 , Utext
 
        Logtext $1b0 , Utext
 
        Logtext $1c0 , Utext
 
        Logtext $1d0 , Utext
 
        Logtext $1e0 , Utext
 
        Logtext $1f0 , Utext
 
        Logtext $200 , Utext
 
        Logtext $210 , Utext
 
        Logtext $220 , Utext
 
        Logtext $230 , Utext
 
        Logtext $240 , Utext
 
        Logtext $250 , Utext
 
        Logtext $260 , Utext
 
        Summe_as_entladen = 0
 
        Summe_mah_entladen = 0
 
        Summe_as_laden = 0
 
        Summe_mah_laden = 0
 
        Writeeeprom Summe_as_entladen , $300
 
        Writeeeprom Summe_mah_entladen , $310
 
        Writeeeprom Summe_as_laden , $320
 
        Writeeeprom Summe_mah_laden , $330
 
        Frei = 0
 
        For Bzeit = 1 To 10
 
        Led3 = 1
 
        Led4 = 1
 
        Led5 = 1
 
        Led6 = 1
 
        Led7 = 1
 
        Waitms 100
 
        Led3 = 0
 
        Led4 = 0
 
        Led5 = 0
 
        Led6 = 0
 
        Led7 = 0
 
        Waitms 100
 
        Next
 
        Bzeit = 500
 
        Enable Interrupts
 
        Waitms 100
 
      End If
 
      If Bzeit > 250 And Bzeit < 350 Then
 
        Frei = 1
 
        Bzeit = 500
 
      Else
 
        Frei = 0
 
        Bzeit = 500
 
      End If
 
      End If
 
    End If
 
    Else
 
    Frei = 0
 
    Bzeit = 500
 
    End If
 
  End If
 
  Else
 
  If Verbraucht < Akkukap Then      'Akku ist laut Spannung leer!
 
    'Einfach mal annehmen daß zuviel entnommen wurde
 
    Akkukap = Verbraucht * 0.95
 
    Akkugrenzen
 
  End If
 
  'Disable Interrupts
 
  'Betriebsdatenschreiber
 
  'Enable Interrupts
 
  End If
 
Else
 
  Antriebaus = 1
 
  Waitms 100
 
  Frei = 0
 
 
  'Disable Interrupts
 
  'Betriebsdatenschreiber
 
  'Enable Interrupts
 
End If
 
End Sub
 
 
Sub Logtext(adresse , Text)
 
If Len(text) > 16 Then Text = Mid(text , 1 , 16)
 
While Len(text) < 16
 
  Text = Text + " "
 
Wend
 
Writeeeprom Text , Adresse
 
End Sub
 
 
Regel_interrupt:
 
'*****************************************************************************
 
'Eigentlich ist das kein typischer Interrupt. Der Interrupt wird hier nur
 
'verwendet um der Regelung einen 100Hz Takt zu geben.
 
'Andere Timer Interrupts werden für diese Zeit blockiert
 
'*****************************************************************************
 
'Timer zählt ab diesem Wert aufwärts bis 256 und macht dann einen Interrupt
 
'==> je höher die Startzahl, umso kürzer das Intervall
 
' 20 MHz / 1024 (Prescaler) = 15,625 KHz / 256 = 61Hz
 
' (61/100) * 256 = 156
 
' 256 - 156 = 100 Der Timer selbst braucht auch etwas Zeit, d.h. 100 ist tatsächlich 61
 
Timer0 = 61
 
 
Bdummy1 = Udr
 
 
Gosub Readfussschalter
 
Gosub Read_gyro
 
Gosub Read_acc
 
 
'Acc_roll = Acc_roll      '*100, war früher -512...+512 jetzt -30000...+30000
 
'Acc_nick = Acc_nick      '*100, war früher -512...+512 jetzt -30000...+30000
 
 
'<Mittellage ausgleichen>
 
'Die Offsetwerte werden langsam an eine früher ermittelte Waagerechte
 
'Position angeglichen.
 
Null_roll = Null_roll * 99
 
Null_nick = Null_nick * 99
 
Null_roll = Null_roll + Offset_roll      'Mittellage
 
Null_nick = Null_nick + Offset_nick      'Mittellage
 
Null_roll = Null_roll / 100
 
Null_nick = Null_nick / 100
 
'</Mittellage ausgleichen>
 
 
'Offsetwerte der Beschleunigungssensoren sofort abziehen
 
'Diese werden nicht laufend ermittelt
 
'Acc_roll = Acc_roll - Null_roll
 
'Acc_nick = Acc_nick - Null_nick
 
'<Geschwindikgeitsbegrenzung>
 
'Bei Der Geschwindigkeitsbegrenzung Wird die Nullage Der Plattform Verändert.
 
'Beim Vorwärtsbremsen wird nach hinten geneigt, beim Rückwärtsbremsen nach vorne.
 
 
Vbrems = 0
 
Lbrems = 0
 
If Frei = 0 Then
 
If Kmh > Vmax Then Vbrems = Vmax - Kmh
 
If Kmh < Vmaxr Then Vbrems = Vmaxr - Kmh
 
End If
 
 
'Lastabhängige Bremse
 
'Es muss immer genug Reserve sein um noch zu Bremsen oder zu Balancieren
 
Ldummyi = Int(pwm_gesamt)
 
If Ldummyi > Spwm Then Lbrems = Spwm - Ldummyi
 
If Ldummyi < Spwmr Then Lbrems = Spwmr - Ldummyi
 
Brems = Lbrems + Vbrems
 
Brems = Brems * 50
 
'Nicht zu heftig Bremsen
 
If Brems < -2000 Then Brems = -2000
 
If Brems > 2000 Then Brems = 2000
 
Acc_nick = Acc_nick + Brems
 
'</Geschwindikgeitsbegrenzung>
 
 
'<Signalaufbereitung der Sensorsignale>
 
K_diff = K_rechts - K_links
 
K_sum = K_sum * 0.84
 
K_sum = K_sum + K_diff
 
'Gleitender Mittelwert der Gyros berechnen um damit den Offset bei
 
'Stillstand zu haben. Dieser ist leider Temperaturabhängig.
 
'Sum_gyro_gier = Sum_gyro_gier - Mit_gyro_gier
 
'Sum_gyro_gier = Sum_gyro_gier + Gyro_gier
 
'Mit_gyro_gier = Sum_gyro_gier / Gyro_anz
 
Sig_gyro_gier = Gyro_gier      '- Mit_gyro_gier      'Polarität
 
 
'Sum_gyro_roll = Sum_gyro_roll - Mit_gyro_roll
 
'Sum_gyro_roll = Sum_gyro_roll + Gyro_roll
 
'Mit_gyro_roll = Sum_gyro_roll / Gyro_anz
 
Sig_gyro_roll = Gyro_roll      '- Mit_gyro_roll      'Polarität
 
 
'Korr_acc_roll = Sig_gyro_roll * Gyro_faktor
 
Sum_acc_roll = Sum_acc_roll - Mit_acc_roll
 
Sum_acc_roll = Sum_acc_roll + Acc_roll
 
'Sum_acc_roll = Sum_acc_roll + Korr_acc_roll      'Gyrowert hinzu
 
'Mittelwert bilden
 
Mit_acc_roll = Sum_acc_roll / Acc_anz
 
Mit_acc_roll = Sum_acc_roll
 
 
'*************************************************************************
 
'Das soll ausgleichen, daß die Gyros bei gekippten Sensoren eine Drehung
 
'um die falsche Achse registrieren.
 
'Sdummy1 = Mit_acc_roll * Sig_gyro_gier
 
'Die Sensorplatine muss dazu absolut Waagerecht montiert sein.
 
'Sdummy1 = Sdummy1 / 20000
 
'Lagefehler = Int(sdummy1)
 
'Das soll den Fehler ausgleichen, der durch die geänderte Lage des
 
'Gyros auftritt.
 
'Gyro_nick = Gyro_nick + Lagefehler
 
'************************************************************************
 
Sum_gyro_nick = Sum_gyro_nick - Mit_gyro_nick
 
Sum_gyro_nick = Sum_gyro_nick + Gyro_nick
 
Mit_gyro_nick = Sum_gyro_nick / Gyro_anz
 
Sig_gyro_nick = Gyro_nick - Mit_gyro_nick
 
 
'Gyro = Beschleunigung
 
'Accelerometer = Neigung
 
 
'Korr_acc_nick = Sig_gyro_nick * Gyro_faktor
 
Sum_acc_nick = Sum_acc_nick - Mit_acc_nick
 
Sum_acc_nick = Sum_acc_nick + Acc_nick
 
'Sum_acc_nick = Sum_acc_nick - Korr_acc_nick      'Gyrowert hinzu
 
Mit_acc_nick = Sum_acc_nick / Acc_anz
 
'</Signalaufbereitung der Sensorsignale>
 
 
'<PID-Regler>
 
Stellwert = 0
 
'< P-Anteil>
 
Sdummy1 = Mit_acc_nick
 
Sdummy1 = Sdummy1 * P_faktor
 
Stellwert = Stellwert - Sdummy1
 
 
'<I-Anteil>
 
Mit_acc_nick_s = Mit_acc_nick_s + Mit_acc_nick
 
'Überlauf/unsinnige Werte verhindern
 
If Mit_acc_nick_s > Max_mit_acc_nick_s Then
 
  Mit_acc_nick_s = Max_mit_acc_nick_s
 
End If
 
If Mit_acc_nick_s < Min_mit_acc_nick_s Then
 
  Mit_acc_nick_s = Min_mit_acc_nick_s
 
End If
 
Sdummy1 = Mit_acc_nick_s
 
Sdummy1 = Sdummy1 * I_faktor
 
Stellwert = Stellwert - Sdummy1
 
 
'<D-Anteil>
 
Sdummy1 = Sig_gyro_nick
 
Sdummy1 = Sdummy1 * D_faktor
 
'Stellwert ==> Stromsollwert
 
Stellwert = Stellwert + Sdummy1
 
 
'<Anpassungsfaktoren berechnen>
 
K_sum_anpassung = K_rechts + K_links
 
K_sum_anpassung = Abs(k_sum_anpassung)
 
 
Mp_anpassung = Pwm_gesamt * Mp_faktor
 
Mp_anpassung = Abs(mp_anpassung)
 
Mp_anpassung = Mp_anpassung + 0.95
 
 
Mv_anpassung = K_sum_anpassung * Mv_faktor
 
Mv_anpassung = Abs(mv_anpassung)
 
Mv_anpassung = Mv_anpassung + 1
 
 
Mpl_anpassung = Pwm_gesamt * Mpl_faktor
 
Mpl_anpassung = Abs(mpl_anpassung)
 
Mpl_anpassung = Mpl_anpassung + 1
 
 
Mvl_anpassung = K_sum_anpassung * Mvl_faktor
 
Mvl_anpassung = Abs(mvl_anpassung)
 
Mvl_anpassung = Mvl_anpassung + 1
 
'</Anpassungsfaktoren berechnen>
 
 
'<Verstärkte Regelung bei hoher Leistung>
 
Stellwert = Stellwert * Mp_anpassung
 
Stellwert = Stellwert * Mv_anpassung
 
'<Verstärkte Regelung bei hoher Leistung>
 
 
'<Abgeschwächte Regelung im Stand>
 
If K_sum_anpassung < 8 Then Stellwert = Stellwert * 0.8
 
If K_sum_anpassung < 6 Then Stellwert = Stellwert * 0.8
 
If K_sum_anpassung < 4 Then Stellwert = Stellwert * 0.8
 
 
'</Abgeschwächte Regelung in Stand>
 
Pwm_gesamt = Pwm_gesamt + Stellwert
 
 
'</PID-Regler>
 
 
'<Bremsvibrator einmischen>
 
'Der Bremsvibrator signalisiert dem Fahrer, daß wegen irgend einem
 
'Grenzwert gebremst wird. Das kann V-Max oder P-Max sein.
 
If Brems <> 0 Then
 
Bdummy1 = Intcount / 2
 
Bdummy1 = Bdummy1 Mod 2
 
If Bdummy1 = 0 Then
 
  Pwm_gesamt = Pwm_gesamt + 5
 
Else
 
  Pwm_gesamt = Pwm_gesamt - 5
 
End If
 
End If
 
'<Bremsvibrator einmischen>
 
 
'<Lenkung>
 
Lenkvorgabe = Mit_acc_roll / 80
 
 
Sdummy1 = Abs(lenkvorgabe)
 
If Sdummy1 <= 6 Then
 
Sdummy1 = Sdummy1 / 12
 
Lenkerstellung = Lenkvorgabe * Sdummy1
 
Else
 
If Lenkvorgabe < 0 Then
 
  Lenkerstellung = Lenkvorgabe + 3
 
Else
 
  Lenkerstellung = Lenkvorgabe - 3
 
End If
 
End If
 
 
'Lenkfehler berechnen und zum Stellwert hinzu.
 
Sdummy1 = Sig_gyro_gier
 
Sdummy1 = Sdummy1 / 5
 
Lenkfehler = Lenkerstellung - Sdummy1
 
Lenkfehler = Lenkfehler * Mpl_anpassung
 
Lenkfehler = Lenkfehler * Mvl_anpassung
 
 
Lenkstellwert = Lenkerstellung + Lenkfehler
 
 
If Lenkstellwert > Max_lenk Then Lenkstellwert = Max_lenk
 
If Lenkstellwert < Min_lenk Then Lenkstellwert = Min_lenk
 
 
Pwm_lenk_links = Pwm_gesamt + Lenkstellwert
 
Pwm_lenk_rechts = Pwm_gesamt - Lenkstellwert
 
 
If Pwm_lenk_links > 0 Then Richtung_links = 1 Else Richtung_links = 0
 
If Pwm_lenk_rechts > 0 Then Richtung_rechts = 1 Else Richtung_rechts = 0
 
 
Pwm_lenk_links = Abs(pwm_lenk_links)
 
Pwm_lenk_rechts = Abs(pwm_lenk_rechts)
 
 
If Pwm_lenk_links > Maxpwm Then Pwm_lenk_links = Maxpwm
 
If Pwm_lenk_rechts > Maxpwm Then Pwm_lenk_rechts = Maxpwm
 
 
If Pwm_lenk_links < Minpwm Then Pwm_lenk_links = Minpwm
 
If Pwm_lenk_rechts < Minpwm Then Pwm_lenk_rechts = Minpwm
 
 
Pwm_links = Pwm_lenk_links
 
Pwm_rechts = Pwm_lenk_rechts
 
'</Lenkung>
 
 
If Antriebaus = 1 Then
 
If Notaus = 1 Then
 
  'Unfalldatenschreiber: *************************************************
 
  'Dauert zwar Lange, macht aber nix. Bei Notaus muss nix geregelt werden.
 
  ' call Unfalldatenschreiber
 
  ' call Betriebsdatenschreiber
 
  Notaus = 0
 
  '***********************************************************************
 
End If
 
'Auf 0 setzen was sonst geregelt wird
 
Richtung_links = 2      'Leerlauf
 
Richtung_rechts = 2      'Leerlauf
 
Pwm_links = 0
 
Pwm_rechts = 0
 
Pwm_gesamt = 0
 
Mit_acc_nick_s = 0
 
Lenkerstellung = 0
 
K_rechts = 0
 
K_links = 0
 
'Waagerechte Positoion setzen wenn Zustand Antriebaus:
 
Wdummy1 = Acc_roll
 
Null_roll = Wdummy1 * 100
 
Wdummy1 = Acc_nick
 
Null_nick = Wdummy1 * 100
 
'Mittelwert der Beschleunigungssensoren auf aktuellen Wert stellen
 
'Der Mittelwert braucht sonst zu lange bis er sich eingeregelt hat
 
Sum_acc_roll = Acc_roll * Acc_anz
 
Sum_acc_nick = Acc_nick * Acc_anz
 
If Intcount = 0 Then T30 = 1      'Regelparameter vom Tacho anfordern
 
If Intcount = 50 Then T30 = 1      'Regelparameter vom Tacho anfordern
 
End If
 
 
'******************************************************************************
 
If T30 = 1 Then      'Regelparameter vom Tacho anfordern
 
K_links = 0
 
K_rechts = 0
 
Zeiger_meldung = 1
 
Bdummy1 = Udr
 
T30 = 0      'Damit keine alte Rückmeldung ausgewertet wird
 
Timeout = Timer0
 
Timeout = Timeout + 100
 
'Anforderung an Display senden
 
Print Chr(255) ; Chr(0) ; Chr(0) ; Chr(255) ; Chr(13)
 
While Zeiger_meldung < 31
 
  If Ucsr0a.rxc0 = 1 Then      'Warten bis ein Byte eingetroffen ist
 
  Tachomeldung(zeiger_meldung) = Udr
 
  Incr Zeiger_meldung
 
  Timeout = Timer0
 
  Timeout = Timeout + 20
 
  End If
 
  If Timer0 > Timeout Then
 
  T30 = 0
 
  Exit While      'Timeout
 
  End If
 
Wend
 
If T30 = 13 Then      'Jetzt BCC berechnen
 
  !lds R24,{t1}
 
  !LDs R25,{t2}
 
  !add R24,R25
 
  !LDs R25,{t3}
 
  !add R24,R25
 
  !LDs R25,{t4}
 
  !add R24,R25
 
  !LDs R25,{t5}
 
  !add R24,R25
 
  !LDs R25,{t6}
 
  !add R24,R25
 
  !LDs R25,{t7}
 
  !add R24,R25
 
  !LDs R25,{t8}
 
  !add R24,R25
 
  !LDs R25,{t9}
 
  !add R24,R25
 
  !LDs R25,{t10}
 
  !add R24,R25
 
  !LDs R25,{t11}
 
  !add R24,R25
 
  !LDs R25,{t12}
 
  !add R24,R25
 
  !LDs R25,{t13}
 
  !add R24,R25
 
  !LDs R25,{t14}
 
  !add R24,R25
 
  !LDs R25,{t15}
 
  !add R24,R25
 
  !LDs R25,{t16}
 
  !add R24,R25
 
  !LDs R25,{t17}
 
  !add R24,R25
 
  !LDs R25,{t18}
 
  !add R24,R25
 
  !LDs R25,{t19}
 
  !add R24,R25
 
  !LDs R25,{t20}
 
  !add R24,R25
 
  !LDs R25,{t21}
 
  !add R24,R25
 
  !LDs R25,{t22}
 
  !add R24,R25
 
  !LDs R25,{t23}
 
  !add R24,R25
 
  !LDs R25,{t24}
 
  !add R24,R25
 
  !LDs R25,{t25}
 
  !add R24,R25
 
  !LDs R25,{t26}
 
  !add R24,R25
 
  !LDs R25,{t27}
 
  !add R24,R25
 
  !LDs R25,{t28}
 
  !add R24,R25
 
  !STS {Bdummy1},R24
 
 
  If Bdummy1 = T29 Then
 
  P_faktor = P_tacho
 
  I_faktor = I_tacho
 
  D_faktor = D_tacho
 
  Mp_faktor = Mp_tacho
 
  Mv_faktor = Mv_tacho
 
  Mpl_faktor = Mpl_tacho
 
  Mvl_faktor = Mvl_tacho
 
  Werteneu = 1
 
  End If
 
End If
 
Else
 
'Errechnete Geschwindigkeiten an Motoren Senden:
 
'Rechter Motor:
 
If Nummotors = 2 Then
 
  Checksum_rechts = 82
 
  Checksum_rechts = Checksum_rechts + Richtung_rechts
 
  Checksum_rechts = Checksum_rechts + Pwm_rechts
 
  'Geschwindigkeit an Motorregler senden
 
  Bdummy1 = Udr      'Puffer leeren
 
  'Print Chr(82); Chr(richtung_rechts); Chr(pwm_rechts); Chr(checksum_rechts); Chr(13);
 
  'In Assembler geht das so:
 
  !Ldi R24 , 82
 
  !STS    udr,R24
 
  Warten1:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten1
 
  !LDS    R24,{Richtung_rechts}
 
  !STS    udr,R24
 
  Warten2:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten2
 
  !lds    R24,{Pwm_rechts}  'PWM Wert
 
  !STS    udr,R24
 
  Warten3:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten3
 
  !LDS    R24,{Checksum_rechts}
 
  !STS    udr,R24
 
  Warten4:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten4
 
  !LDI    R24,13
 
  !STS    udr,R24
 
  Warten5:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten5
 
 
  Motormeldung(8) = 0      'Damit keine alte Rückmeldung ausgewertet wird
 
 
  'Vom Motorcontroller lesen
 
  Timeout = Timer0
 
  Zeiger_meldung = 1
 
  '80 Ticks * 51,2uS pro Tick = 4mS Wartezeit auf Antwort
 
  'COM benötigt ca. 1,5mS für 9 Byte
 
  Errorword.8 = 0
 
  Timeout = Timeout + 80
 
  While Zeiger_meldung < 9
 
  If Ucsr0a.rxc0 = 1 Then      'Warten bis ein Byte eingetroffen ist
 
    Motormeldung(zeiger_meldung) = Udr
 
    Incr Zeiger_meldung
 
  End If
 
  If Timer0 > Timeout Then
 
    Ende = 0
 
    Errorword.8 = 1
 
    Exit While      'Timeout
 
  End If
 
  Wend
 
 
  !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 {Bdummy1},R24
 
 
  If Bdummy1 <> Checksumme Then Ende = 0
 
  If Ende = 13 Then
 
  U_rechts = U
 
  I_rechts = I
 
  K_rechts = K
 
  Else
 
  Incr Seriell_err_rechts
 
  S_err = 1
 
  End If
 
End If
 
 
'Linker Motor:
 
Checksum_links = 76      'Adresse
 
Checksum_links = Checksum_links + Richtung_links
 
Checksum_links = Checksum_links + Pwm_links
 
Zeiger_meldung = 1
 
Bdummy1 = Udr      'Puffer leeren
 
'Print Chr(76); Chr(richtung_links); Chr(pwm_links); Chr(checksum_links); Chr(13);
 
'>>>>>>>>>>>> Message an Motorcontroller senden <<<<<<<<<<<<<<
 
'In Assembler geht das so:
 
  !Ldi    R24 , 76      'Adresse
 
  !STS    udr,R24
 
  Warten6:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten6
 
  !LDS    R24,{Richtung_links}
 
  !STS    udr,R24
 
  Warten7:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten7
 
  !lds    R24,{Pwm_links}
 
  !STS    udr,R24
 
  Warten8:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten8
 
  !LDS    R24,{Checksum_links}
 
  !STS    udr,R24
 
  Warten9:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten9
 
  !LDI    R24,13
 
  !STS    udr,R24
 
  Warten10:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten10
 
Motormeldung(8) = 0      'Damit keine alte Rückmeldung ausgewertet wird
 
Timeout = Timer0
 
Timeout = Timeout + 80      'Wartezeit auf Antwort
 
'>>>>>>>>>>>> Message vom Motorcontroller empfangen <<<<<<<<<<<<<<
 
While Zeiger_meldung < 9
 
  If Ucsr0a.rxc0 = 1 Then      'Warten bis ein Byte eingetroffen ist
 
  Motormeldung(zeiger_meldung) = Udr
 
  Incr Zeiger_meldung
 
  End If
 
  If Timer0 > Timeout Then
 
  Ende = 0
 
  Errorword.8 = 1
 
  Exit While      'Timeout
 
  End If
 
Wend
 
 
!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 {Bdummy1},R24
 
 
If Bdummy1 <> Checksumme Then Ende = 0
 
  If Ende = 13 Then
 
  U_links = U
 
  I_links = I
 
  K_links = K
 
  Else
 
  Incr Seriell_err_links
 
  S_err = 1
 
  End If
 
  If S_err = 1 Then      'Sicherheitshalber, damit der Lenkausgleich nicht überreagiert.
 
  K_links = 0
 
  K_rechts = 0
 
  S_err = 0
 
  End If
 
End If
 
 
If Antriebaus = 0 Then
 
  '<Not-Aus Kriterien ermitteln>
 
  If Mit_acc_nick > -300 Then If Mit_acc_nick < 300 Then Regelzeit = 0
 
  Incr Regelzeit
 
  '</Not-Aus Kriterien ermitteln>
 
 
  '<Not-Aus Kriterien abprüfen>
 
  If Regelzeit > 250 Then      'Wenn nach 2,5s waagerechte Lage nicht erreicht
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(regelzeit)
 
  Ugrund = "*Rz " + Ugrund
 
  End If
 
  Ldummyi = 4000 + Brems
 
  If Mit_acc_nick > Ldummyi Then      'zu weit nach hinten gekippt
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(mit_acc_nick)
 
  Ugrund = "*Nick " + Ugrund
 
  End If
 
  Ldummyi = -4000 + Brems
 
  If Mit_acc_nick < Ldummyi Then      'zu weit nach vorn gekippt
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(mit_acc_nick)
 
  Ugrund = "*Nick " + Ugrund
 
  End If
 
  If Mit_acc_roll > 5000 Then      'Lenker zu weit nach rechts
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(mit_acc_roll)
 
  Ugrund = "*Roll " + Ugrund
 
  End If
 
  If Mit_acc_roll < -5000 Then      'Lenker zu weit nach links
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(mit_acc_roll)
 
  Ugrund = "*Roll " + Ugrund
 
  End If
 
  If K_diff > 10 Then      'Plattform rotiert zu schnell
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(k_diff)
 
  Ugrund = "*Gier " + Ugrund
 
  End If
 
  If K_diff < -10 Then      'Plattform rotiert zu schnell
 
  Notaus = 1
 
  Antriebaus = 1
 
  Ugrund = Str(k_diff)
 
  Ugrund = "*Gier " + Ugrund
 
  End If
 
  '</Not-Aus Kriterien abprüfen>
 
Else
 
  If Fusscount > 0 Then Antriebaus = 0
 
End If
 
 
'<Akkuspannung berechnen>
 
If Nummotors = 2 Then
 
  Ugemessen = U_links + U_rechts
 
  Shift Ugemessen , Right , 1 , Signed      'Div by 2 weil 2 Motoren
 
Else
 
  Ugemessen = U_links
 
End If
 
'</Akkuspannung berechnen>
 
 
'<Gesamtstrom berechnen>
 
If Nummotors = 2 Then
 
  Igemessen = I_links + I_rechts
 
Else
 
  Igemessen = I_links
 
End If
 
'</Gesamtstrom berechnen>
 
 
'<verbrauchte Amperestunden berechnen>
 
If Igemessen > 0 Then
 
  Summe_as_entladen = Summe_as_entladen + Igemessen      'Verbrauchte
 
End If
 
If Igemessen < 0 Then
 
  Summe_as_laden = Summe_as_laden - Igemessen      'Rückgespeiste
 
End If
 
'mAh aus den Amperestunden rausholen um Überläufe zu verhindern
 
'Die 360000 setzen sich zusammen aus:
 
    'Igemessen in mA -> Faktor 1
 
    '100 Messungen pro Sekunde -> mal 100
 
    '1 mAh = 60 Sekunden * 60 mAsekunden -> 3600
 
'360000 = 1 * 100 * 3600
 
If Summe_as_entladen > 360000 Then
 
  Incr Summe_mah_entladen
 
  Summe_as_entladen = Summe_as_entladen - 360000
 
End If
 
If Summe_as_laden > 360000 Then      'Das kann passieren wenns den Berg runter geht
 
  Incr Summe_mah_laden
 
  Summe_as_laden = Summe_as_laden - 360000
 
End If
 
Erzeugt = Summe_mah_laden
 
Verbraucht = Summe_mah_entladen
 
Erzeugt = Erzeugt * 0.7      'Das ist der Akku-Wirkungsgrad 0.7 (0.85) bezogen auf den Stom
 
Verbraucht = Verbraucht - Erzeugt
 
Akkuinhalt = Akkukap
 
Akkuverbrauch = Verbraucht
 
Akkuprozent = Akkuverbrauch / Akkuinhalt
 
Akkuprozent = Akkuprozent * 1000
 
Akkuprozent = Int(akkuprozent)
 
Akkustand = Akkuprozent
 
'</verbrauchte As berechnen>
 
 
'<Strecke berechnen>
 
Kx = K_links + K_rechts
 
Kx = Kx / 2
 
Strecke = Kx * Di
 
Zentimeter = Zentimeter + Strecke
 
If Zentimeter >= 100 Then
 
  Incr Meter
 
  Zentimeter = Zentimeter - 100
 
End If
 
If Zentimeter < 0 Then
 
  Decr Meter
 
  Zentimeter = Zentimeter + 100
 
End If
 
If Meter >= 1000 Then
 
  Incr Kilometer
 
  Meter = Meter - 1000
 
End If
 
If Meter < 0 Then
 
  Decr Kilometer
 
  Meter = Meter + 1000
 
End If
 
'</Strecke berechnen>
 
 
'<Geschwindigkeit berechnen>
 
Kv = Kv + Kx
 
Kmh = Kv * Kmhfaktor
 
Kv = Kv * 0.75      'Bei Änderung auch den kmhfaktor neu berechnen
 
If Kmh > Max_v Then Max_v = Kmh
 
If Kmh < Min_v Then Min_v = Kmh
 
'</Geschwindigkeit berechnen>
 
 
If Bzeit < 500 Then Incr Bzeit
 
Incr Intcount
 
'******************************************************************************
 
'ADiverse Werte werden an den Tacho geschickt. Manche für die Funktion
 
'des Tachos, andere um die Steuerung zu optimieren.
 
'******************************************************************************
 
Incr Tachocount
 
 
Select Case Tachocount
 
Case 0
 
  B(1) = 40      'Error Word
 
  B(2) = Errorword1
 
  B(3) = Errorword2
 
  B(5) = 1
 
Case 1
 
  B(1) = 1      'U
 
  U = Ugemessen
 
  B(2) = Motormeldung(1)
 
  B(3) = Motormeldung(2)
 
  B(5) = 1
 
Case 2
 
  B(1) = 2      'I
 
  I = Igemessen / 10
 
  B(2) = Motormeldung(3)
 
  B(3) = Motormeldung(4)
 
  B(5) = 1
 
Case 3
 
  B(1) = 3      'Km/h
 
  B(2) = Kmhmeldung(1)
 
  B(3) = Kmhmeldung(2)
 
  B(5) = 1
 
Case 4
 
  B(1) = 5      'Akkuprozente
 
  B(2) = Akkumeldung(1)
 
  B(3) = Akkumeldung(2)
 
  B(5) = 1
 
Case 5
 
  B(1) = 7      'Meter
 
  B(2) = Metermeldung(1)
 
  B(3) = Metermeldung(2)
 
  B(5) = 1
 
Case 6
 
  B(1) = 6      'Kilometer
 
  B(2) = Kilometermeldung(1)
 
  B(3) = Kilometermeldung(2)
 
  B(5) = 1
 
Case 7
 
  If Antriebaus = 0 Then
 
  B(1) = 8      'Low
 
  B(2) = Mit_acc_roll1
 
  B(3) = Mit_acc_roll2
 
  B(5) = 1
 
  Else
 
  B(1) = 12      'Low
 
  B(2) = Null_roll1
 
  B(3) = Null_roll2
 
  B(5) = 1
 
End If
 
Case 8
 
  If Antriebaus = 0 Then
 
  B(1) = 9      'High
 
  B(2) = Mit_acc_roll3
 
  B(3) = Mit_acc_roll4
 
  B(5) = 1
 
  Else
 
  B(1) = 13      'High
 
  B(2) = Null_roll3
 
  B(3) = Null_roll4
 
  B(5) = 1
 
  End If
 
Case 9
 
  B(1) = 4      'Status
 
  B(2) = Antriebaus
 
  B(3) = Ta
 
  B(5) = 1
 
Case 10
 
  If Antriebaus = 0 Then
 
  B(1) = 10      'acc_Nick
 
  B(2) = Mit_acc_nick1
 
  B(3) = Mit_acc_nick2
 
  B(5) = 1
 
  Else
 
  B(1) = 14
 
  B(2) = Null_nick1
 
  B(3) = Null_nick2
 
  B(5) = 1
 
  End If
 
Case 11      'Nick und Roll
 
  If Antriebaus = 0 Then
 
  B(1) = 11      'acc_Nick
 
  B(2) = Mit_acc_nick3
 
  B(3) = Mit_acc_nick4
 
  B(5) = 1
 
  Else
 
  B(1) = 15
 
  B(2) = Null_nick3
 
  B(3) = Null_nick4
 
  B(5) = 1
 
  End If
 
Case 12
 
  B(1) = 16      'Stellwert
 
  B(2) = Stellwert1
 
  B(3) = Stellwert2
 
  B(5) = 1
 
Case 13
 
  B(1) = 17      'Stellwert
 
  B(2) = Stellwert3
 
  B(3) = Stellwert4
 
  B(5) = 1
 
Case 14
 
  Gyronick = Sig_gyro_nick
 
  B(1) = 18      'Gyro Nick_l
 
  B(2) = Gyronick1
 
  B(3) = Gyronick2
 
  B(5) = 1
 
Case 15
 
  B(1) = 19      'Gyro Nick_h
 
  B(2) = Gyronick3
 
  B(3) = Gyronick4
 
  B(5) = 1
 
Case 16
 
  Kksum = K_sum
 
  B(1) = 20      '??_l
 
  B(2) = Kksum1
 
  B(3) = Kksum2
 
  B(5) = 1
 
Case 17
 
  B(1) = 21      '??_h
 
  B(2) = Kksum3
 
  B(3) = Kksum4
 
  B(5) = 1
 
  If Antriebaus = 0 Then Tachocount = 255      'Gleich zu 0 überlaufen lassen
 
Case 18
 
  B(1) = 22
 
  B(2) = Pf1
 
  B(3) = Pf2
 
  B(5) = 1
 
Case 19
 
  B(1) = 23
 
  B(2) = Pf3
 
  B(3) = Pf4
 
  B(5) = 1
 
Case 20
 
  B(1) = 24
 
  B(2) = If1
 
  B(3) = If2
 
  B(5) = 1
 
Case 21
 
  B(1) = 25
 
  B(2) = If3
 
  B(3) = If4
 
  B(5) = 1
 
Case 22
 
  B(1) = 26
 
  B(2) = Df1
 
  B(3) = Df2
 
  B(5) = 1
 
Case 23
 
  B(1) = 27
 
  B(2) = Df3
 
  B(3) = Df4
 
  B(5) = 1
 
Case 24
 
  B(1) = 28
 
  B(2) = Mpf1
 
  B(3) = Mpf2
 
  B(5) = 1
 
Case 25
 
  B(1) = 29
 
  B(2) = Mpf3
 
  B(3) = Mpf4
 
  B(5) = 1
 
Case 26
 
  B(1) = 30
 
  B(2) = Mvf1
 
  B(3) = Mvf2
 
  B(5) = 1
 
Case 27
 
  B(1) = 31
 
  B(2) = Mvf3
 
  B(3) = Mvf4
 
  B(5) = 1
 
Case 28
 
  B(1) = 32
 
  B(2) = Mplf1
 
  B(3) = Mplf2
 
  B(5) = 1
 
Case 29
 
  B(1) = 33
 
  B(2) = Mplf3
 
  B(3) = Mplf4
 
  B(5) = 1
 
Case 30
 
  B(1) = 34
 
  B(2) = Mvlf1
 
  B(3) = Mvlf2
 
  B(5) = 1
 
Case 31
 
  B(1) = 35
 
  B(2) = Mvlf3
 
  B(3) = Mvlf4
 
  B(5) = 1
 
Case 32
 
  B(1) = 36      'Port Status
 
  B(2) = Portc
 
  B(3) = Porta
 
  B(5) = 1
 
Case 33
 
  B(1) = 37      'Fussschalter 1
 
  Wwert = Adc0      'Word
 
  B(2) = Wwert1
 
  B(3) = Wwert2
 
  B(5) = 1
 
Case 34
 
  B(1) = 38      'Fussschalter 2
 
  Wwert = Adc1      'Word
 
  B(2) = Wwert1
 
  B(3) = Wwert2
 
  B(5) = 1
 
Case 35
 
  B(1) = 39      'Fussschalter gesamt
 
  B(2) = Fussschalter
 
  B(3) = 0
 
  B(5) = 1
 
  Tachocount = 255
 
Case Else
 
  B(5) = 0      'Nichts ausgeben
 
End Select
 
 
If Intcount = 99 Then Intcount = 255
 
 
If B(5) = 1 Then
 
'Checksumme berechnen
 
B(4) = B(1)
 
B(4) = B(4) + B(2)
 
B(4) = B(4) + B(3)
 
'Print Chr(b(1)) ; Chr(b(2)) ; Chr(b(3)) ; Chr(b(4)) ; Chr(13);
 
'Print geht so in Assembler:
 
  !LDS    R24,{B(1)}      'Adresse von b(1)
 
  !STS    udr,R24
 
Warten11:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten11
 
  !LDS    R24,{B(2)}      'Adresse von b(2)
 
  !STS    udr,R24
 
Warten12:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten12
 
  !lds    R24,{B(3)}      'Adresse von B(3)
 
  !STS    udr,R24
 
Warten13:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten13
 
  !LDS    R24,{B(4)}      'Adresse von B(4)
 
  !STS    udr,R24
 
Warten14:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten14
 
  !LDI    R24,13      'CR
 
  !STS    udr,R24
 
Warten15:
 
  !LDS    R24,UCSR0A
 
  !BST    R24,5
 
  !Brtc warten15
 
 
Ta = Timer0      'Um festzustellen ob der Interrupt zu lange dauert
 
                  'Wenn Ja, ist der Zählwert nahe 255
 
End If
 
Return
 
 
Sub Flashled(byval Which As Byte , Byval Dauer_ms As Byte)
 
Dim Done As Byte
 
Dim Waitstarttime As Byte
 
Dim Xx As Byte
 
 
Select Case Which
 
  Case 0      'Both
 
  Led1 = 1
 
  Led2 = 1
 
  Waitms Dauer_ms
 
  Led1 = 0
 
  Led2 = 0
 
  Waitms Dauer_ms
 
  Case 1      'LED1
 
  Led1 = 1
 
  Waitms Dauer_ms
 
  Led1 = 0
 
  Waitms Dauer_ms
 
  Case 2      'LED2
 
  Led2 = 1
 
  Waitms Dauer_ms
 
  Led2 = 0
 
  Waitms Dauer_ms
 
End Select
 
End Sub
 
 
Readfussschalter:
 
Adc0 = Getadc(0)
 
If Adc0 > Fussschalterschwelle Then
 
  Fussschalter.0 = 1
 
Else
 
  Fussschalter.0 = 0
 
End If
 
 
Adc1 = Getadc(1)
 
If Adc1 > Fussschalterschwelle Then
 
  Fussschalter.1 = 1
 
Else
 
  Fussschalter.1 = 0
 
End If
 
 
If Fussschalter = 0 Then      'Max 0.5 Sekunden ohne Fussschalter
 
  If Fusscount > 0 Then Decr Fusscount
 
Else
 
  Fusscount = 50      'alles OK
 
End If
 
 
If Fusscount = 0 Then
 
  If Antriebaus = 0 Then
 
  Antriebaus = 1
 
  Waitms 100      'Damit der Regel_interrupt auch was davon mitbekommt
 
  'Disable Interrupts
 
  'Betriebsdatenschreiber
 
  'Enable Interrupts
 
  End If
 
End If
 
Return
 
 
Read_gyro:      'Beschleunigung
 
I2cstart
 
I2cwbyte Gyroadress_w
 
'Start address for Read
 
I2cwbyte &B10101000      'Out_x_l AND &B10000000
 
I2cstart
 
I2cwbyte Gyroadress_r
 
'I2crbyte Temperatur , Ack
 
'I2crbyte Status , Ack
 
 
I2crbyte Gyro_roll1 , Ack
 
I2crbyte Gyro_roll2 , Ack
 
 
I2crbyte Gyro_nick1 , Ack
 
I2crbyte Gyro_nick2 , Ack
 
 
I2crbyte Gyro_gier1 , Ack
 
I2crbyte Gyro_gier2 , Nack
 
I2cstop
 
Return
 
 
Read_acc:      'Neigung
 
I2cstart
 
I2cwbyte Accadress_w
 
'Start address for Read
 
I2cwbyte &B10101000      'Out_x_l_a AND &B10000000
 
I2cstart
 
I2cwbyte Accadress_r
 
 
'I2crbyte Status_a , Ack
 
 
I2crbyte Accroll_l , Ack
 
I2crbyte Accroll_h , Ack
 
Acc_roll = Accroll
 
Acc_roll = Acc_roll / 2      'Divisor = Empfindlichkeit
 
 
I2crbyte Accnick_l , Ack
 
I2crbyte Accnick_h , Ack
 
Acc_nick = Accnick
 
Acc_nick = Acc_nick / 10      'Divisor = Empfindlichkeit
 
 
I2crbyte Accgier_l , Ack
 
I2crbyte Accgier_h , Nack
 
Acc_gier = Accgier
 
Acc_gier = Acc_gier / 10      'Divisor = Empfindlichkeit
 
I2cstop
 
Return
 
 
'Get_mag_data:
 
' Slaveadress = Magadress
 
' Subadress = Out_x_h_m
 
' Gosub Read_6_mag
 
 
' Xmag = Dataarray(1)
 
' Shift Xmag , Left , 8
 
' Xmag = Xmag + Dataarray(2)
 
 
' Ymag = Dataarray(3)
 
' Shift Ymag , Left , 8
 
' Ymag = Ymag + Dataarray(4)
 
 
' Zmag = Dataarray(5)
 
' Shift Zmag , Left , 8
 
' Zmag = Zmag + Dataarray(6)
 
 
' Xmag = Xmag - Xmagoff
 
' Ymag = Ymag - Ymagoff
 
'Return
 
 
Init_gyro:
 
'refer to MiniMu9 L3G4200D_Gyro.pdf, page 29
 
Slaveadress = Gyroadress_w
 
Subadress = Ctrl_reg1
 
'01            ==> 200Hz
 
'  11          ==> Bandwidth = 70
 
'    0          ==> Power Down Mode
 
'    1        ==> Z-Axis enable
 
'      1        ==> Y-Axis enable
 
'      1      ==> X-Axis enable
 
Databyte = &B00001111      'Enable x, y, z and turn off power down
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
Subadress = Ctrl_reg2
 
 
Databyte = &B0010_1001      'adjust/use the HPF
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
 
Subadress = Ctrl_reg3
 
Databyte = &B0000_1000
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
 
Subadress = Ctrl_reg4
 
'1            ==> Block Data Update
 
' 0            ==> BLE
 
'  00          ==> 250 dps
 
'    0        ==> not used
 
'    00      ==> Self Test 0=Normal Mode
 
'      0      ==> SIM 0=4-wire interface
 
Databyte = &B10000000
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
 
Subadress = Ctrl_reg5
 
Databyte = &B0000_0000      'high-pass filtering of outputs
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
Return
 
 
Init_acc:
 
Slaveadress = Accadress_w
 
Subadress = Ctrl_reg1_a
 
'001            ==> Normal Mode
 
'  01          ==> 100Hz, Bandwith=74
 
'    1        ==> Z-Axis enable
 
'      1        ==> Y-Axis enable
 
'      1      ==> X-Axis enable
 
Databyte = &B00101111
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
 
Slaveadress = Accadress_w
 
Subadress = Ctrl_reg4_a
 
'1            ==> Continuous, update when finished
 
' 0            ==> BLE
 
'  00          ==> FSE = 2g
 
'    0        ==> Self Test Sign
 
'    0        ==> not used
 
'      0      ==> Self Test Enable
 
'      0      ==> not used
 
Databyte = &B10000000      'Block Data Update, LSB low, Scale +-2g
 
I2cstart
 
I2cwbyte Slaveadress
 
I2cwbyte Subadress
 
I2cwbyte Databyte
 
I2cstop
 
Return
 
 
'Init_mag:
 
'  Slaveadress = Magadress
 
'  Subadress = Cra_reg_m
 
'  Databyte = &B00011000                                    '75Hz Output
 
'  I2cstart
 
'  I2cwbyte Slaveadress
 
'  I2cwbyte Subadress
 
'  I2cwbyte Databyte
 
'  I2cstop
 
 
'  Slaveadress = Magadress
 
'  Subadress = Crb_reg_m
 
'  Databyte = &B01000000                                    'range +-1.9Gauss
 
'  I2cstart
 
'  I2cwbyte Slaveadress
 
'  I2cwbyte Subadress
 
'  I2cwbyte Databyte
 
'  I2cstop
 
 
'  Slaveadress = Magadress
 
'  Subadress = Mr_reg_m
 
'  Databyte = &B00000000                                    'continious mode
 
'  I2cstart
 
'  I2cwbyte Slaveadress
 
'  I2cwbyte Subadress
 
'  I2cwbyte Databyte
 
'  I2cstop
 
'Return
 
 
Sub Resetdata
 
Disable Interrupts
 
Regelzeit = 0
 
Regelzeitmax = 0
 
Mit_acc_nick_max = 0
 
Mit_acc_roll_max = 0
 
Mit_acc_nick_min = 0
 
Mit_acc_roll_min = 0
 
Pwm_rechts_max = 0
 
Pwm_links_max = 0
 
Seriell_err_rechts = 0
 
Seriell_err_links = 0
 
K_diff_min = 0
 
K_diff_max = 0
 
Antriebaus = 0
 
Fusscount = 50      '0,5 Sekunden
 
Enable Interrupts
 
End Sub
 
</pre>
 
 
'''Display3000.bas (BASCOM)'''
 
<pre>
 
 
'****************Listrik01 LCD Display Steuerung Version 01 *****************
 
$hwstack = 256
 
$swstack = 256
 
$framesize = 64
 
$regfile = "m2561def.dat"
 
$crystal = 16000000      'microcontroller crystal frequency
 
$baud1 = 57600
 
 
'(start block comment
 
  ---------------------
 
|                    |
 
|  ---------------  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  |
 
|  |              |  | Port D.0 = Tageskilometerzähler Reset
 
|  |              |  |
 
|  |              |  |
 
|  | --------------|  | Display:
 
|  | 1| 2|      |3|  |  1 = Zyklusdauer (0..255)
 
|  ---------------  |  2 = Motorleistung links
 
|                    |  3 = Motorleistung rechts
 
|                    |
 
|  O1            O2  |
 
|          O5        | Taster:
 
|                    |  1: PinD.7 Edit: Zeile abwärts
 
|      O7    O8      |  2: PinD.4 Edit: Zeile aufwärts
 
|                    |  3: PinE.5 Blättern
 
|          O6        |  4: PinE.7 SD-Karte aktivieren
 
|  O3            O4  |  5: PinG.0 Edit: Werte übernehmen
 
|                    |  6: PinG.3 unbenutzt
 
|                    |  7: PinG.1 Edit: Zahl kleiner
 
|                    |  8: PinD.5 Edit: Zahl größer
 
|                    |  9: Cpu Reset
 
|                    |
 
|                    |  Extern1: PinD.0 Reset Tageskilometerzähler (J3 zu, interner Pullup)
 
|                O9  |  Extern1: PinD.1 unbenutzt (J3 zu, interner Pullup)
 
  ---------------------
 
')end block comment
 
 
'####################### LCD-Routines ######################################
 
 
'Definition of used ports and pull up resistors.
 
'We are using Port B for the SPI-communication to the LCD Display.
 
 
Ddra = &B00000000      'switch all 8 Ports of Port A to input (0),
 
                        'Pin (PA.0 - PA.7)
 
Porta = &B11111111      'All port pins have individually selectable pull-up
 
                        'resistors. Here we enable these pull-up-resisitors,
 
                        'so these Pins are always at logical 1
 
                        'You Need To Pull These Pins Against Ground(gnd)
 
 
'Select Port B as to an output port (data output to the display)
 
Ddrb = &B01110110      'DDR = Data direction register; Port B1, B2, B4, B5, B6
 
                        'switched to output (1) as needed by the display
 
Portb = &B10001001      'the other ports of Port B are inputs with
 
                        'switched on pull up resistors
 
 
Ddrc = &B00000000      'switch all Ports of Port C to input
 
Portc = &B11111111      'all pull-up-Resistors turned on
 
 
Ddrd = &B00000000      'switchall Ports of Port D to input
 
Portd = &B11110011      'almost all pull-up-Resistors turned on
 
 
Ddre = &B10000000      'E7=Output (SD card activate), all other Input
 
Porte = &B11111111      'all pull-up-Resistors turned on
 
 
Ddrf = &B00000000      'switch all Ports of Port F to input
 
Portf = &B11111111      'all pull-up-Resistors turned on
 
 
Ddrg = &B00000000      'switch all Ports of Port G to input
 
Portg = &B11111111      'all pull-up-Resistors turned on
 
'#############################################################################
 
 
Declare Sub Activate_display_bus
 
Declare Sub Activate_sd_bus()
 
Declare Sub Minmax()
 
Declare Function Trimtext(t As String) As String * 22
 
Declare Sub Drawpagestatics
 
 
Const Titel = "Tacho 0.1            "
 
 
Dim Ep0 As Byte At $0201
 
Dim Ep1 As Byte At $0202
 
Dim Ep2 As Byte At $0203
 
Dim Ep3 As Byte At $0204
 
Dim Ep4 As Byte At $0205
 
Dim Ep5 As Byte At $0206
 
Dim Iwert As Integer At $0203 Overlay
 
Dim Wwert As Integer At $0203 Overlay
 
Dim Index As Byte At $202 Overlay
 
 
Dim Maccx As Long At $0207
 
Dim Maccx1 As Byte At $0207 Overlay
 
Dim Maccx2 As Byte At $0208 Overlay
 
Dim Maccx3 As Byte At $0209 Overlay
 
Dim Maccx4 As Byte At $020a Overlay
 
Dim Maccy As Long At $020b
 
Dim Maccy1 As Byte At $020b Overlay
 
Dim Maccy2 As Byte At $020c Overlay
 
Dim Maccy3 As Byte At $020d Overlay
 
Dim Maccy4 As Byte At $020e Overlay
 
 
Dim Nullx As Long At $020f
 
Dim Nullx1 As Byte At $020f Overlay
 
Dim Nullx2 As Byte At $0210 Overlay
 
Dim Nullx3 As Byte At $0211 Overlay
 
Dim Nullx4 As Byte At $0212 Overlay
 
Dim Nully As Long At $0213
 
Dim Nully1 As Byte At $0213 Overlay
 
Dim Nully2 As Byte At $0214 Overlay
 
Dim Nully3 As Byte At $0215 Overlay
 
Dim Nully4 As Byte At $0216 Overlay
 
Dim Sw As Single At $00217
 
 
Dim Sw1 As Byte At $0217 Overlay
 
Dim Sw2 As Byte At $0218 Overlay
 
Dim Sw3 As Byte At $0219 Overlay
 
Dim Sw4 As Byte At $021a Overlay
 
 
Dim Gyronick As Long At $0021b
 
Dim Gyronick1 As Byte At $021b Overlay
 
Dim Gyronick2 As Byte At $021c Overlay
 
Dim Gyronick3 As Byte At $021d Overlay
 
Dim Gyronick4 As Byte At $021e Overlay
 
 
Dim Kksum As Single At $0021f
 
Dim Kksum1 As Byte At $021f Overlay
 
Dim Kksum2 As Byte At $0220 Overlay
 
Dim Kksum3 As Byte At $0221 Overlay
 
Dim Kksum4 As Byte At $0222 Overlay
 
 
Dim P_faktor As Single At $0223
 
Dim P_f1 As Byte At $0223 Overlay
 
Dim P_f2 As Byte At $0224 Overlay
 
Dim P_f3 As Byte At $0225 Overlay
 
Dim P_f4 As Byte At $0226 Overlay
 
 
Dim I_faktor As Single At $0227
 
Dim I_f1 As Byte At $0227 Overlay
 
Dim I_f2 As Byte At $0228 Overlay
 
Dim I_f3 As Byte At $0229 Overlay
 
Dim I_f4 As Byte At $022a Overlay
 
 
Dim D_faktor As Single At $022b
 
Dim D_f1 As Byte At $022b Overlay
 
Dim D_f2 As Byte At $022c Overlay
 
Dim D_f3 As Byte At $022d Overlay
 
Dim D_f4 As Byte At $022e Overlay
 
 
Dim Mp_faktor As Single At $022f
 
Dim Mp_f1 As Byte At $022f Overlay
 
Dim Mp_f2 As Byte At $0230 Overlay
 
Dim Mp_f3 As Byte At $0231 Overlay
 
Dim Mp_f4 As Byte At $0232 Overlay
 
 
Dim Mv_faktor As Single At $0233
 
Dim Mv_f1 As Byte At $0233 Overlay
 
Dim Mv_f2 As Byte At $0234 Overlay
 
Dim Mv_f3 As Byte At $0235 Overlay
 
Dim Mv_f4 As Byte At $0236 Overlay
 
 
Dim Mpl_faktor As Single At $0237
 
Dim Mpl_f1 As Byte At $0237 Overlay
 
Dim Mpl_f2 As Byte At $0238 Overlay
 
Dim Mpl_f3 As Byte At $0239 Overlay
 
Dim Mpl_f4 As Byte At $023a Overlay
 
 
Dim Mvl_faktor As Single At $023b
 
Dim Mvl_f1 As Byte At $023b Overlay
 
Dim Mvl_f2 As Byte At $023c Overlay
 
Dim Mvl_f3 As Byte At $023d Overlay
 
Dim Mvl_f4 As Byte At $023e Overlay
 
 
Dim Pfaktor As Long
 
Dim Ifaktor As Long
 
Dim Dfaktor As Long
 
Dim Mpfaktor As Long
 
Dim Mvfaktor As Long
 
Dim Mplfaktor As Long
 
Dim Mvlfaktor As Long
 
 
Dim Stellwert As Single
 
Dim Gyro_nick As Long
 
Dim Null_y As Long
 
Dim Null_x As Long
 
Dim Mit_acc_y As Long
 
Dim Mit_acc_x As Long
 
Dim K_sum As Single
 
Dim K_summax As Single
 
Dim K_summin As Single
 
 
Dim Bdummy As Byte
 
Dim Singdummy As Single
 
Dim Wdummy As Word
 
Dim Ldummy As Long
 
Dim Idummy As Integer
 
Dim Kilometer As Word
 
Dim Meter As Integer
 
Dim Akkuprozente As Integer
 
Dim Kmh As Integer
 
Dim Kmhmax As Integer
 
Dim Kmhmin As Integer
 
 
Dim I As Integer
 
Dim Imax As Integer
 
Dim Imin As Integer
 
 
Dim U As Integer
 
Dim Umax As Integer
 
Dim Umin As Integer
 
Dim Ml As Integer
 
Dim Mlmax As Integer
 
Dim Mrmax As Integer
 
Dim Mr As Integer
 
Dim Mlmin As Integer
 
Dim Mrmin As Integer
 
Dim Modus As Byte
 
Dim Editzeile As Byte
 
Dim Utext As String * 22
 
Dim Itext As String * 22
 
Dim Ltext As String * 22
 
Dim L1 As Byte
 
Dim L2 As Byte
 
Dim L3 As Byte
 
Dim Text As String * 22
 
Dim Farbe As Word
 
Dim X1 As Byte
 
Dim Y1 As Byte
 
Dim X2 As Byte
 
Dim Y2 As Byte
 
Dim Startkilometer As Single
 
Dim Ta As Byte
 
Dim Tamax As Byte
 
 
Dim Antriebaus As Byte
 
 
Dim Xoffset As Long
 
Dim Yoffset As Long
 
Dim Ya As Byte
 
Dim Xa As Byte
 
 
Dim Lname As Long
 
Dim Dateiname As String * 12
 
Dim Dateilaenge As Long
 
Dim Dateiaktuell As Byte
 
Dim Gbdriveerror As Byte
 
Dim Ulog As Single
 
Dim Ilog As Single
 
Dim Kmhlog As Single
 
Dim Kmlog As Single
 
Dim Akkuprozentelog As Single
 
Dim Loopcount As Word
 
Dim Aloopcount As Word
 
Dim Logtext As String * 255
 
Dim Zeit As String * 8
 
Dim Sichern As Byte
 
Dim Transferok As Byte
 
 
Dim Hexstr As String * 2
 
 
Dim Hauptstportc As Byte
 
Dim Hauptstporta As Byte
 
Dim Ad0 As Word      'AD value 0...1024
 
Dim Ad1 As Word      'AD value 0...1024
 
Dim Fussschalter As Byte      'Bit0 und Bit1
 
Dim Dummybyte As Byte
 
 
Config Clock = User
 
Config Date = Dmy , Separator = .
 
 
'No need to call here because Init21_display3000.bas has already done this
 
Call Activate_display_bus
 
 
$include "Y:\Programme\Tools\BASCOM-AVR\Display 3000\Displaymodul\Bascom Programme\für Include\Init21_display3000.bas"
 
 
'If Porte.7 = 0 Then Activate_sd_bus
 
'Gbdriveerror = Driveinit()      'Init MMC/SD Card
 
'If Gbdriveerror = 0 Then
 
' Include AVR-DOS Configuration and library
 
' $include "Y:\Programme\Tools\BASCOM-AVR\Display 3000\SD Speicherkartenmodul P001\Bascom Basic\Config_AVR-DOS.BAS"
 
' Bdummy = Initfilesystem(1)      ' Partition 1
 
' Ldummy = Disksize()
 
' Ldummy = Ldummy / 1024
 
' Utext = Str(ldummy)
 
' Utext = "Size: " + Utext
 
' Utext = Utext + " mb"
 
' Ldummy = Diskfree()
 
' Ldummy = Ldummy / 1024
 
' Itext = Str(ldummy)
 
' Itext = "Free: " + Itext
 
' Itext = Itext + " mb"
 
' If Porte.7 = 1 Then call Activate_display_bus
 
'  gosub Lcd_cls
 
'  call Lcd_print(Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue)
 
'  call Lcd_print ("SD-Karte init" , 0 , 18 , 1 , 1 , 1 , Black , White)
 
'  call Lcd_print (Utext , 0 , 27 , 1 , 1 , 1 , Black , White)
 
'  Lcd_print Itext , 0 , 36 , 1 , 1 , 1 , Black , White
 
'  Wait 7
 
' Else
 
'  If Porte.7 = 1 Then call Activate_display_bus
 
'  Ltext = Str(gbdriveerror)
 
'  Ltext = "Fehler: " + Ltext
 
'  gosub Lcd_cls
 
'  call Lcd_print (Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue)
 
'  call Lcd_print ("SD-Karte init" , 0 , 18 , 1 , 1 , 1 , Black , White)
 
'  call Lcd_print (Ltext , 0 , 27 , 1 , 1 , 1 , Black , White)
 
'  Wait 7
 
' End If
 
 
Readeeprom Startkilometer , 1
 
Readeeprom Xoffset , 5
 
Readeeprom Yoffset , 9
 
 
'Einige Werte vorbelegen um fehlerhafte Grafik zu vermeiden falls keine
 
'serielle Verbindung besteht
 
Xa = 74
 
Ya = 130
 
Antriebaus = 1
 
Null_x = Xoffset
 
Null_y = Yoffset
 
 
'If Porte.7 = 1 Then call Activate_display_bus
 
Orientation = Portrait180      'landscape mode
 
Graphics_mode = 65k_uncompressed      'select the needed color mode, here 65.536 colors
 
Call Lcd_cls
 
 
Call Drawpagestatics
 
 
Config Timer2 = Timer , Prescale = 128
 
Assr.exclk = 0
 
Assr.as2 = 1
 
 
On Timer2 Tick
 
Enable Timer2
 
Start Timer2
 
 
On Urxc1 Datenempfang
 
Enable Urxc1
 
Enable Interrupts
 
Minmax
 
Do
 
If Pine.5 = 0 Then
 
  While Pine.5 = 0 : Wend      'Debounce Button
 
  Incr Modus
 
  If Gbdriveerror <> 0 Then      'Logging nicht zulassen wenn DriveError
 
  If Modus > 3 Then
 
    Modus = 0
 
  End If
 
  Else
 
  If Modus > 4 Then
 
    Modus = 0
 
  End If
 
  end If
 
 
  If Modus <> 3 Then      'nur berechnen wenn die Werte nicht editiert werden
 
  Singdummy = P_faktor * 10000
 
  Singdummy = Round(Singdummy)
 
  Pfaktor = Singdummy
 
 
  Singdummy = I_faktor * 1000000
 
  Singdummy = Round(Singdummy)
 
  Ifaktor = Singdummy
 
 
  Singdummy = D_faktor * 1000
 
  Singdummy = Round(Singdummy)
 
  Dfaktor = Singdummy
 
 
  Singdummy = Mp_faktor * 10000
 
  Singdummy = Round(Singdummy)
 
  Mpfaktor = Singdummy
 
 
  Singdummy = Mv_faktor * 1000
 
  Singdummy = Round(Singdummy)
 
  Mvfaktor = Singdummy
 
 
  Singdummy = Mpl_faktor * 10000
 
  Singdummy = Round(Singdummy)
 
  Mplfaktor = Singdummy
 
 
  Singdummy = Mvl_faktor * 1000
 
  Singdummy = Round(Singdummy)
 
  Mvlfaktor = Singdummy
 
  End If
 
 
  'If Porte.7 = 1 Then call Activate_display_bus
 
  Call Lcd_cls
 
  Call Drawpagestatics
 
End If
 
If Modus <> 4 Then      'Nur wenn nicht geloggt wird
 
  If U <> 0 Then      'Nur wenn auch schon eine Spannung übertragen wurde
 
  If Ta <> 0 Then
 
    Idummy = U      'Nur wenn auch schon ein Ta übertragen wurde
 
    If Idummy > Umax Then Umax = Idummy
 
    If Idummy < Umin Then Umin = Idummy
 
    Idummy = I
 
    If Idummy > Imax Then Imax = Idummy
 
    If Idummy < Imin Then Imin = Idummy
 
    Idummy = Kmh
 
    If Idummy > Kmhmax Then Kmhmax = Idummy
 
    If Idummy < Kmhmin Then Kmhmin = Idummy
 
    Bdummy = Ta
 
    If Bdummy > Tamax Then Tamax = Bdummy
 
    Idummy = Ml
 
    If Idummy > Mlmax Then Mlmax = Idummy
 
    If Idummy < Mlmin Then Mlmin = Idummy
 
    Idummy = Mr
 
    If Idummy > Mrmax Then Mrmax = Idummy
 
    If Idummy < Mrmin Then Mrmin = Idummy
 
  End If
 
  End If
 
End If
 
 
Select Case Modus
 
Case 0
 
  'If Dateiaktuell = 1 Then
 
  ' If Porte.7 = 0 Then Activate_sd_bus
 
  ' Close #2
 
  ' Dateiaktuell = 0
 
  'End If
 
  'If Porte.7 = 1 Then call Activate_display_bus      'Standard Anzeige
 
  If Pind.0 = 0 Then
 
  Waitms 3
 
  If Pind.0 = 0 Then
 
    While Pind.0 = 0 : Wend
 
    Singdummy = Meter / 1000
 
    Singdummy = Singdummy + Kilometer
 
    Startkilometer = Singdummy
 
    Writeeeprom Startkilometer , 1
 
  End If
 
  End If
 
 
  'Spannung und Strom
 
  Singdummy = U / 100
 
  Utext = Fusing(singdummy , "#.#")
 
  Utext = Utext + "V"
 
  Utext = " " + Utext
 
  Singdummy = I / 100
 
  Itext = Fusing(singdummy , "#.#")
 
  Itext = Itext + "A "
 
  L1 = Len(utext)
 
  L2 = Len(itext)
 
  L1 = L1 + L2
 
  L2 = 22 - L1
 
  Ltext = String(l2 , 32)
 
  Text = Utext + Ltext
 
  Text = Text + Itext
 
  Lcd_print Text , 0 , 75 , 1 , 1 , 1 , Black , White
 
 
  'Akku in Prozent
 
  Singdummy = Akkuprozente / 10
 
  Singdummy = 100 - Singdummy
 
  Text = Fusing(singdummy , "#.#" )
 
  Text = " " + Text + "% "
 
  If Singdummy > 66 Then
 
  Farbe = Green
 
  Elseif Singdummy > 33 Then
 
  Farbe = Yellow
 
  Else
 
  Farbe = Red
 
  End If
 
  Singdummy = Singdummy * 1.14      '124 - 8 - 1 - 1 = 114 / 100% = 1.14
 
  X2 = Singdummy      'Type cast
 
  X2 = X2 + 10      '10 wegen der "100 - Sdummy" weiter oben
 
  Lcd_box X2 , 85 , 123 , 94 , White      'Hintergrund löschen
 
  Lcd_box 9 , 85 , X2 , 94 , Farbe      'Balken zeichnen
 
  'Text mittig platzieren
 
  L1 = Len(text)
 
  L1 = L1 * 5
 
  L1 = L1 / 2
 
  X1 = 66 - L1
 
  Lcd_print Text , X1 , 98 , 1 , 1 , 1 , Black , White      'unterm Balken
 
 
  'km/h
 
  Singdummy = Kmh / 10
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = Text + "km/h "
 
  Text = " " + Text
 
  L1 = Len(text)
 
  Text = Text + " "
 
  L1 = L1 * 4
 
  X1 = 66 - L1
 
  Lcd_print Text , X1 , 12 , 2 , 1 , 2 , Black , White
 
 
  'km
 
  Singdummy = Meter / 1000
 
  Singdummy = Singdummy + Kilometer
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = Text + "km  "
 
  Text = " " + Text
 
  L1 = Len(text)
 
  L1 = L1 * 5
 
  L1 = L1 / 2
 
  X1 = 66 - L1
 
  Lcd_print Text , X1 , 46 , 1 , 1 , 1 , Black , White
 
 
  'Tageskilometerzähler
 
  Singdummy = Singdummy - Startkilometer
 
  Text = Fusing(Singdummy , "#.###")
 
  Text = Text + "km  "
 
  Text = " " + Text
 
  L1 = Len(text)
 
  L1 = L1 * 5
 
  L1 = L1 / 2
 
  X1 = 66 - L1
 
  Lcd_print Text , X1 , 60 , 1 , 1 , 1 , Black , White
 
 
  If Antriebaus = 1 Then
 
  Text = "AUS"
 
  Else
 
  Text = "RUN"
 
  End If
 
  'Text mittig platzieren
 
  L1 = Len(text)
 
  L1 = L1 * 5      'Schriftlänge in Pixel, jedes Zeichen = 5 Pixel
 
  L1 = L1 / 2      'Halbe schriftlänge
 
  X1 = 74 - L1      'Text mittig
 
  Lcd_print Text , X1 , 148 , 1 , 1 , 1 , Black , White
 
 
  '>>>>>>>>>>>> Fusszeile im Display >>>>>>>>>>>>
 
  '  01234567891111111111222
 
  '            0123456789012
 
  '  xxx      xxx      xxx
 
  'PmotLinks  Ta      PmotRechts
 
  '  L1        L2      L3
 
 
  Text = String(22 , 32)      'Fill with spaces
 
 
  Utext = Str(ml)      'Pmot_links (Integer)
 
  L1 = Len(utext)
 
  Mid(text , 0 , L1) = Utext      'insert Ml
 
 
  Utext = Str(ta)      'Ticks (Byte)
 
  L2 = Len(utext)
 
  Mid(text , 10 , L2) = Utext      'insert Ta
 
 
  Utext = Str(mr)      'Pmot_rechts (Integer)
 
  L3 = Len(utext)
 
  X1 = 23 - L3      'Starting position of Mr
 
  Mid(text , X1 , L3) = Utext      'insert Mr
 
 
  'L2 = X1 + L3
 
  'L1 = 22 - L2
 
  'Utext = String(l1 , 32)
 
  'Mid(text , L2 , L1) = Utext      'insert final spaces
 
 
  Lcd_print Text , 0 , 168 , 1 , 1 , 1 , White , Black
 
  '>>>>>>>>>>>> Fusszeile im Display >>>>>>>>>>>>
 
 
  If Antriebaus = 1 Then
 
  Singdummy = Null_x
 
  Singdummy = Singdummy - Xoffset
 
  Singdummy = Singdummy / 50
 
  If Singdummy > 49 Then Singdummy = 49
 
  If Singdummy < -49 Then Singdummy = -49
 
  Singdummy = Singdummy + 74
 
  X1 = Int(Singdummy)
 
  Lcd_draw Xa , 126 , Xa , 134 , 0 , White
 
  Lcd_draw X1 , 126 , X1 , 134 , 0 , Black
 
  Xa = X1
 
  Singdummy = Null_y
 
  Singdummy = Singdummy - Yoffset
 
  Singdummy = Singdummy / 50
 
  If Singdummy > 29 Then Singdummy = 29
 
  If Singdummy < -29 Then Singdummy = -29
 
  Singdummy = Singdummy + 130
 
  Y1 = Int(Singdummy)
 
  Lcd_draw 9 , Ya , 18 , Ya , 0 , White
 
  Lcd_draw 9 , Y1 , 18 , Y1 , 0 , Black
 
  Ya = Y1
 
  Else
 
  'Horizontaler Balken
 
  Singdummy = Mit_acc_x
 
  Singdummy = Singdummy / 50
 
  If Singdummy > 49 Then Singdummy = 49
 
  If Singdummy < -49 Then Singdummy = -49
 
  Singdummy = Singdummy + 74
 
  X1 = Int(Singdummy)
 
  Lcd_draw Xa , 126 , Xa , 134 , 0 , White
 
  Lcd_draw X1 , 126 , X1 , 134 , 0 , Black
 
  Xa = X1
 
 
  'Vertikaler Balken
 
  Singdummy = Mit_acc_y
 
  Singdummy = Singdummy / 50
 
  If Singdummy > 29 Then Singdummy = 29
 
  If Singdummy < -29 Then Singdummy = -29
 
  Singdummy = Singdummy + 130
 
  Y1 = Int(Singdummy)
 
  Lcd_draw 9 , Ya , 18 , Ya , 0 , White
 
  Lcd_draw 9 , Y1 , 18 , Y1 , 0 , Black
 
  Ya = Y1
 
  End If
 
Case 1      'Details
 
  'If Dateiaktuell = 1 Then
 
  ' If Porte.7 = 0 Then Activate_sd_bus
 
  ' Close #2
 
  ' Dateiaktuell = 0
 
  'End If
 
  'If Porte.7 = 1 Then call Activate_display_bus
 
  If Pind.0 = 0 Then
 
  Waitms 3
 
  If Pind.0 = 0 Then
 
    While Pind.0 = 0 : Wend
 
    If Antriebaus = 1 Then
 
    Yoffset = Null_y
 
    Xoffset = Null_x
 
    Writeeeprom Xoffset , 5
 
    Writeeeprom Yoffset , 9
 
    End If
 
  End If
 
  End If
 
  Singdummy = U / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  U= " + Text
 
  Text = Text + "V"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 9 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = I / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  I= " + Text
 
  Text = Text + "A"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = Kmh / 10
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  V= " + Text
 
  Text = Text + "km/h"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 27 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = Meter / 1000
 
  Singdummy = Singdummy + Kilometer
 
  Text = Fusing(Singdummy , "#.###")
 
  Text = "  S= " + Text
 
  Text = Text + "km  "
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = Ml
 
  Text = Str(ml )
 
  Text = "  Pl= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 45 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = Mr
 
  Text = Str(mr )
 
  Text = "  Pr= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 54 , 1 , 1 , 1 , Black , White
 
 
  Singdummy = Akkuprozente / 10
 
  Singdummy = 100 - Singdummy
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "Akku= " + Text
 
  Text = Text + "%"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 63 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(mit_acc_x)
 
  Text = "Roll= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 72 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(mit_acc_y )
 
  Text = "Nick= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 81 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(null_x )
 
  Text = "  R0= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 90 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(null_y )
 
  Text = "  N0= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 99 , 1 , 1 , 1 , Black , White
 
 
  Text = Fusing(stellwert , "#.###")
 
  Text = "  SW= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 108 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(gyro_nick )
 
  Text = "  GN= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 117 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(ta )
 
  Text = "  TA= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 126 , 1 , 1 , 1 , Black , White
 
 
  Text = Str(k_sum)
 
  Text = "Ksum= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 135 , 1 , 1 , 1 , Black , White
 
 
Case 2      'Min/Max
 
  'If Dateiaktuell = 1 Then
 
  ' If Porte.7 = 0 Then Activate_sd_bus
 
  ' Close #2
 
  ' Dateiaktuell = 0
 
  'End If
 
  'If Porte.7 = 1 Then call Activate_display_bus
 
 
  If Pind.0 = 0 Then
 
  Waitms 3
 
  If Pind.0 = 0 Then
 
    While Pind.0 = 0 : Wend
 
    Minmax      'Min-Maxwerte auf 0 setzen
 
  End If
 
  End If
 
  Singdummy = Umin / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Umin= " + Text
 
  Text = Text + "V"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 9 , 1 , 1 , 1 , Black , White
 
  Singdummy = Umax / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Umax= " + Text
 
  Text = Text + "V"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Singdummy = Imin / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Imin= " + Text
 
  Text = Text + "A"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 27 , 1 , 1 , 1 , Black , White
 
  Singdummy = Imax / 100
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Imax= " + Text
 
  Text = Text + "A"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Singdummy = Kmhmin / 10
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Vmin= " + Text
 
  Text = Text + "km/h"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 45 , 1 , 1 , 1 , Black , White
 
  Singdummy = Kmhmax / 10
 
  Text = Fusing(Singdummy , "#.#")
 
  Text = "  Vmax= " + Text
 
  Text = Text + "km/h"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 54 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(mlmin )
 
  Text = "  Plmin= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 63 , 1 , 1 , 1 , Black , White
 
  Text = Str(mlmax )
 
  Text = "  Plmax= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 72 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(mlmin )
 
  Text = "  Prmin= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 81 , 1 , 1 , 1 , Black , White
 
  Text = Str(mrmax )
 
  Text = "  Prmax= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 90 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(tamax )
 
  Text = "  TAmax= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 99 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Bin(hauptstportc)
 
  Text = "  HauptSt_C= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 108 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Bin(hauptstporta)
 
  Text = "  HauptSt_A= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 118 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(ad0)
 
  Text = "  AD(0)= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 127 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(ad1)
 
  Text = "  AD(1)= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 136 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Dummybyte = Fussschalter And &H1
 
  If Dummybyte > 0 Then
 
  Text = "1"
 
  Else
 
  Text = "0"
 
  End If
 
  Text = "  Fuss1= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 145 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Dummybyte = Fussschalter And &H2
 
  If Dummybyte > 0 Then
 
  Text = "1"
 
  Else
 
  Text = "0"
 
  End If
 
  Text = "  Fuss2= " + Text
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 153 , 1 , 1 , 1 , Black , White
 
 
Case 3      'Werte editieren
 
  'If Dateiaktuell = 1 Then
 
  ' If Porte.7 = 0 Then Activate_sd_bus
 
  ' Close #2
 
  ' Dateiaktuell = 0
 
  'End If
 
  'If Porte.7 = 1 Then call Activate_display_bus
 
 
  If Pind.7 = 0 Then      'Zeile abwärts
 
  Waitms 3
 
  If Pind.7 = 0 Then
 
    While Pind.7 = 0 : Wend
 
    If Editzeile > 1 Then Decr Editzeile : End If
 
  End If
 
 
  If Pind.4 = 0 Then      'Zeile aufwärts
 
  Waitms 3
 
  If Pind.4 = 0 Then
 
  While Pind.4 = 0 : Wend
 
  If Editzeile < 7 Then Incr Editzeile : End If
 
  End If
 
 
  If Ping.1 = 0 Then      'Zahl dekrementieren
 
  Waitms 3
 
  If Ping.1 = 0 Then
 
    While Ping.1 = 0 : Wend
 
    Select Case Editzeile
 
    Case 1
 
      Decr Pfaktor
 
    Case 2
 
      Decr Ifaktor
 
    Case 3
 
      Decr Dfaktor
 
    Case 4
 
      Decr Mpfaktor
 
    Case 5
 
      Decr Mvfaktor
 
    Case 6
 
      Decr Mplfaktor
 
    Case 7
 
      Decr Mvlfaktor
 
    End Select
 
  End If
 
  End If
 
 
  If Pind.5 = 0 Then      'Zahl inkrementieren
 
  Waitms 3
 
  If Pind.5 = 0 Then
 
    While Pind.5 = 0 : Wend
 
    Select Case Editzeile
 
    Case 1
 
      Incr Pfaktor
 
    Case 2
 
      Incr Ifaktor
 
    Case 3
 
      Incr Dfaktor
 
    Case 4
 
      Incr Mpfaktor
 
    Case 5
 
      Incr Mvfaktor
 
    Case 6
 
      Incr Mplfaktor
 
    Case 7
 
      Incr Mvlfaktor
 
    End Select
 
  End If
 
  End If
 
 
  If Ping.0 = 0 Then 'Werte aus Display übernehmen
 
  Waitms 3
 
  If Ping.0 = 0 Then
 
    While Ping.0 = 0 : Wend
 
    P_faktor = Pfaktor
 
    P_faktor = P_faktor / 10000
 
 
    I_faktor = Ifaktor
 
    I_faktor = I_faktor / 1000000
 
 
    D_faktor = Dfaktor
 
    D_faktor = D_faktor / 1000
 
 
    Mp_faktor = Mpfaktor
 
    Mp_faktor = Mp_faktor / 10000
 
 
    Mv_faktor = Mvfaktor
 
    Mv_faktor = Mv_faktor / 1000
 
 
    Mpl_faktor = Mplfaktor
 
    Mpl_faktor = Mpl_faktor / 10000
 
 
    Mvl_faktor = Mvlfaktor
 
    Mvl_faktor = Mvl_faktor / 1000
 
 
    Sichern = 1
 
    Call Lcd_cls
 
    Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue
 
    Wait 2
 
  End If
 
  End If
 
 
  Text = "  Regelparameter:"
 
  Text = Trimtext(text)
 
  Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  Text = Str(pfaktor)
 
  Text = "  P = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 1 Then
 
  Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(ifaktor)
 
  Text = "  I = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 2 Then
 
  Lcd_print Text , 0 , 46 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 46 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(dfaktor)
 
  Text = "  D = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 3 Then
 
  Lcd_print Text , 0 , 56 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 56 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(mpfaktor)
 
  Text = "  MP = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 4 Then
 
  Lcd_print Text , 0 , 66 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 66 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(mvfaktor)
 
  Text = "  MV = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 5 Then
 
  Lcd_print Text , 0 , 76 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 76 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(mplfaktor)
 
  Text = " MPL = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 6 Then
 
  Lcd_print Text , 0 , 86 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 86 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  Text = Str(mvlfaktor)
 
  Text = " MVL = " + Text
 
  Text = Trimtext(text)
 
  If Editzeile = 7 Then
 
  Lcd_print Text , 0 , 96 , 1 , 1 , 1 , Black , Green
 
  '**************************************************
 
  Else
 
  Lcd_print Text , 0 , 96 , 1 , 1 , 1 , Black , White
 
  '**************************************************
 
  End If
 
  If Transferok = 1 Then
 
  Lcd_print "  Transfer OK" , 0 , 106 , 1 , 1 , 1 , Black , White
 
  Transferok = 0
 
  End If
 
'(
 
Case 4      'Logging
 
  If Porte.7 = 0 Then Activate_sd_bus
 
  If Antriebaus = 0 Then      'Motoren laufen ->Werte Loggen
 
  If Dateiaktuell = 0 Then      'Keine Datei geöffnet
 
    Lname = 1
 
    Dateilaenge = 1      'Nächste Schleife einmal erzwingen
 
    While Dateilaenge > 0
 
    Dateiname = Str(lname)
 
    Dateiname = Dateiname + ".log"
 
    '0 voranstellen, damit sich die Dateien besser sortieren lassen.
 
    While Len(dateiname) < 12
 
      Dateiname = "0" + Dateiname
 
    Wend
 
    Dateilaenge = Filelen(dateiname)
 
    Incr Lname
 
    Wend
 
    If Porte.7 = 1 Then call Activate_display_bus
 
    Lcd_print Dateiname , 25 , 75 , 1 , 1 , 1 , Black , White
 
    If Porte.7 = 0 Then Activate_sd_bus
 
    Dateiaktuell = 1
 
    Loopcount = 0
 
    _sec = 0
 
    _min = 0
 
    _hour = 0
 
    Zeit = "00:00:00"
 
    Open Dateiname For Append As #2
 
    Logtext = "Zeit;Loopcount;U;I;Nick;GyroNick;Stellwert;Roll;Pl;Pr;Ksum;V"
 
    Print #2 , Logtext
 
  End If
 
  If Loopcount <> Aloopcount Then
 
    Ulog = U / 100
 
    Ilog = I / 100
 
    Kmhlog = Kmh / 10
 
    Logtext = Zeit
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(loopcount)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Fusing(ulog , "#.#")
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Fusing(ilog , "#.#")
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(mit_acc_y)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(gyro_nick)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Fusing(stellwert , "#.###")
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(mit_acc_x)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(ml)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Str(mr)
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Fusing(k_sum , "#.##")
 
    Logtext = Logtext + ";"
 
    Logtext = Logtext + Fusing(kmhlog , "#.#")
 
    Print #2 , Logtext
 
    Aloopcount = Loopcount
 
  End If
 
  Else
 
  Close #2
 
  Dateiaktuell = 0
 
  End If
 
')
 
End Select
 
Loop
 
 
'***************************************************************************
 
Datenempfang:
 
!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,UDR1
 
!STs {EP5},R24
 
!POP R24;
 
!Out Sreg , R24;
 
!POP R24;
 
 
'BCC prüfen
 
If Ep0 = 13 Then
 
If Ep5 = 13 Then
 
  !lds R24,{EP1}
 
  !LDs R25,{EP2}
 
  !add R24,R25
 
  !LDs R25,{EP3}
 
  !add R24,R25
 
  !STS {Bdummy},R24
 
  If Bdummy = Ep4 Then      'Die Prüfsumme stimmt
 
  '< Serielle Telegramme abarbeiten>
 
  Select Case Index      'Telegrammnummer
 
    Case 1      'Spannung
 
    U = Iwert
 
    Case 2      'Strom
 
    I = Iwert
 
    Case 3      'km/h
 
    Kmh = Iwert
 
    Case 4      'Ta und Antriebaus
 
    Antriebaus = Ep2
 
    Ta = Ep3
 
    Case 5      'Akkuprozente
 
    Akkuprozente = Iwert
 
    Case 6      'Kilometer
 
    Kilometer = Wwert
 
    Case 7      'Meter
 
    Meter = Iwert
 
    Case 8      'Roll_l
 
    Maccx1 = Ep2
 
    Maccx2 = Ep3
 
    Case 9      'Roll_h
 
    Maccx3 = Ep2
 
    Maccx4 = Ep3
 
    Mit_acc_x = Maccx
 
    Case 10      'Nick_l
 
    Maccy1 = Ep2
 
    Maccy2 = Ep3
 
    Case 11      'Nick_h
 
    Maccy3 = Ep2
 
    Maccy4 = Ep3
 
    Mit_acc_y = Maccy
 
    Case 12      'Null_Roll_l
 
    Nullx1 = Ep2
 
    Nullx2 = Ep3
 
    Case 13      'Null_Roll_h
 
    Nullx3 = Ep2
 
    Nullx4 = Ep3
 
    Null_x = Nullx
 
    Case 14      'Null_Nick_l
 
    Nully1 = Ep2
 
    Nully2 = Ep3
 
    Case 15      'Null_Nick_h
 
    Nully3 = Ep2
 
    Nully4 = Ep3
 
    Null_y = Nully
 
    Case 16
 
    Sw1 = Ep2
 
    Sw2 = Ep3
 
    Case 17
 
    Sw3 = Ep2
 
    Sw4 = Ep3
 
    Stellwert = Sw
 
    Case 18
 
    Gyronick1 = Ep2
 
    Gyronick2 = Ep3
 
    Case 19
 
    Gyronick3 = Ep2
 
    Gyronick4 = Ep3
 
    Gyro_nick = Gyronick
 
    Case 20
 
    Kksum1 = Ep2
 
    Kksum2 = Ep3
 
    Case 21
 
    Kksum3 = Ep2
 
    Kksum4 = Ep3
 
    K_sum = Kksum
 
    Case 255
 
    '(
 
    If Sichern = 1 Then
 
      'BCC berechnen
 
      !lds R24,{P_f1}
 
      !LDs R25,{P_f2}
 
      !add R24,R25
 
      !LDs R25,{P_f3}
 
      !add R24,R25
 
      !LDs R25,{P_f4}
 
      !add R24,R25
 
      !LDs R25,{I_f1}
 
      !add R24,R25
 
      !LDs R25,{I_f2}
 
      !add R24,R25
 
      !LDs R25,{I_f3}
 
      !add R24,R25
 
      !LDs R25,{I_f4}
 
      !add R24,R25
 
      !LDs R25,{D_f1}
 
      !add R24,R25
 
      !LDs R25,{D_f2}
 
      !add R24,R25
 
      !LDs R25,{D_f3}
 
      !add R24,R25
 
      !LDs R25,{D_f4}
 
      !add R24,R25
 
      !LDs R25,{Mp_f1}
 
      !add R24,R25
 
      !LDs R25,{Mp_f2}
 
      !add R24,R25
 
      !LDs R25,{Mp_f3}
 
      !add R24,R25
 
      !LDs R25,{Mp_f4}
 
      !add R24,R25
 
      !LDs R25,{Mv_f1}
 
      !add R24,R25
 
      !LDs R25,{Mv_f2}
 
      !add R24,R25
 
      !LDs R25,{Mv_f3}
 
      !add R24,R25
 
      !LDs R25,{Mv_f4}
 
      !add R24,R25
 
      !LDs R25,{Mpl_f1}
 
      !add R24,R25
 
      !LDs R25,{Mpl_f2}
 
      !add R24,R25
 
      !LDs R25,{Mpl_f3}
 
      !add R24,R25
 
      !LDs R25,{Mpl_f4}
 
      !add R24,R25
 
      !LDs R25,{Mvl_f1}
 
      !add R24,R25
 
      !LDs R25,{Mvl_f2}
 
      !add R24,R25
 
      !LDs R25,{Mvl_f3}
 
      !add R24,R25
 
      !LDs R25,{Mvl_f4}
 
      !add R24,R25
 
      !STS {Bdummy},R24
 
 
      Open "COM2:" For Binary As #1  'auf SD-Karte speichern
 
      Print #1 , Chr(p_f1) ; Chr(p_f2) ; Chr(p_f3) ; Chr(p_f4);
 
      Print #1 , Chr(i_f1) ; Chr(i_f2) ; Chr(i_f3) ; Chr(i_f4);
 
      Print #1 , Chr(d_f1) ; Chr(d_f2) ; Chr(d_f3) ; Chr(d_f4);
 
      Print #1 , Chr(mp_f1) ; Chr(mp_f2) ; Chr(mp_f3) ; Chr(mp_f4);
 
      Print #1 , Chr(mv_f1) ; Chr(mv_f2) ; Chr(mv_f3) ; Chr(mv_f4);
 
      Print #1 , Chr(mpl_f1) ; Chr(mpl_f2) ; Chr(mpl_f3) ; Chr(mpl_f4);
 
      Print #1 , Chr(mvl_f1) ; Chr(mvl_f2) ; Chr(mvl_f3) ; Chr(mvl_f4);
 
      Print #1 , Chr(bdummy) ; Chr(13);
 
      Close #1
 
      Transferok = 1
 
      Sichern = 0
 
    End If
 
')
 
    Case 76      'Linker Motor
 
    Ml = Ep3
 
    If Ep2 = 0 Then Ml = Ml * -1
 
    Incr Loopcount
 
    Case 82      'Rechter Motor
 
    Mr = Ep3
 
    If Ep2 = 0 Then Mr = Mr * -1
 
  End Select
 
 
  If Modus = 2 Then
 
    Select Case Index
 
    Case 36 'Port a und C Status
 
      Hauptstportc = Ep2
 
      Hauptstporta = Ep3
 
    Case 37  'Fussschalter 1
 
      Ad0 = Wwert
 
    Case 38  'Fussschalter 2
 
      Ad1 = Wwert
 
    Case 39 'Fussschalter gesamt
 
      Fussschalter = Ep2
 
    End Select
 
  End If
 
 
  If Modus < 3 Then
 
    Select Case Index
 
    Case 22
 
      P_f1 = Ep2
 
      P_f2 = Ep3
 
    Case 23
 
      P_f3 = Ep2
 
      P_f4 = Ep3
 
    Case 24
 
      I_f1 = Ep2
 
      I_f2 = Ep3
 
    Case 25
 
      I_f3 = Ep2
 
      I_f4 = Ep3
 
    Case 26
 
      D_f1 = Ep2
 
      D_f2 = Ep3
 
    Case 27
 
      D_f3 = Ep2
 
      D_f4 = Ep3
 
    Case 28
 
      Mp_f1 = Ep2
 
      Mp_f2 = Ep3
 
    Case 29
 
      Mp_f3 = Ep2
 
      Mp_f4 = Ep3
 
    Case 30
 
      Mv_f1 = Ep2
 
      Mv_f2 = Ep3
 
    Case 31
 
      Mv_f3 = Ep2
 
      Mv_f4 = Ep3
 
    Case 32
 
      Mpl_f1 = Ep2
 
      Mpl_f2 = Ep3
 
    Case 33
 
      Mpl_f3 = Ep2
 
      Mpl_f4 = Ep3
 
    Case 34
 
      Mvl_f1 = Ep2
 
      Mvl_f2 = Ep3
 
    Case 35
 
      Mvl_f3 = Ep2
 
      Mvl_f4 = Ep3
 
    End Select
 
  End If
 
  End If
 
End If
 
End If
 
'</Serielle Telegramme abarbeiten>
 
Return
 
'******************************************************************************
 
 
Sub Activate_display_bus:
 
'remove SD Card from bus, must be "Reset PortF.7" for board D071x
 
'Reset Porte.7
 
'different to what the SD card needs
 
'Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1
 
'Set Spsr.spi2x      'hidden parameter: doubles the speed of the SPI output
 
'Spiinit
 
End Sub
 
 
Sub Activate_sd_bus
 
'Deactivate Display
 
'Set Lcd_port.lcd_cs
 
'different to what the display needs
 
'Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , _
 
'            Polarity = High , Phase = 1 , Clockrate = 4 , Noss = 1
 
'no double speed. You may remove this line to try out with your card.
 
'It may work.
 
'Reset Spsr.spi2x
 
'Spiinit
 
  'connects SD Card to bus, must to be "Set PortF.7" for board D071x
 
'Set Porte.7
 
End Sub
 
 
Function Trimtext(t As String) As String
 
If Len(t) > 22 Then T = Left(t , 22)
 
While Len(t) < 22 : T = T + " " : Wend
 
End Function
 
 
Sub Minmax
 
Umin = 10000
 
Umax = -10000
 
Imin = 0
 
Imax = 0
 
Kmhmin = 0
 
Kmhmax = 0
 
Mlmax = 0
 
Mlmin = 0
 
Mrmax = 0
 
Mrmin = 0
 
Tamax = 0
 
End Sub
 
 
Tick:
 
Incr _sec
 
If _sec > 59 Then
 
  _sec = 0
 
  Incr _min
 
End If
 
 
If _min > 59 Then
 
  _min = 0
 
  Incr _hour
 
End If
 
 
Zeit = Time$
 
Return
 
 
Getdatetime:
 
Return
 
 
Sub Drawpagestatics
 
Call Lcd_print(titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue)
 
Select Case Modus
 
  Case 0
 
  Lcd_rect 8 , 84 , 124 , 95 , 0 , Black      'Rahmen für Akku Balken
 
  Lcd_rect 24 , 125 , 124 , 135 , 0 , Black      'Rahmen für Horizontal Lenker
 
  Lcd_rect 8 , 100 , 19 , 160 , 0 , Black      'Rahmen für Vertikal Lenker
 
  Lcd_draw 20 , 130 , 22 , 130 , 0 , Black      'Vertikaler Balken, Mitteltick
 
  Lcd_draw 74 , 136 , 74 , 138 , 0 , Black      'Horizontaler Balken, Mitteltick
 
  Lcd_draw 0 , 167 , 132 , 167 , 0 , Black      'Hintergrund der Fußzeile
 
  Case 4
 
  Call Lcd_print( "LOGGING" , 30 , 40 , 2 , 1 , 2 , Black , White)
 
  Dateiaktuell = 0
 
End Select
 
End Sub
 
 
End
 
 
$include "Y:\Programme\Tools\BASCOM-AVR\Display 3000\Displaymodul\Bascom Programme\für Include\GLCD21_display3000.bas"
 
$include "Y:\Programme\Tools\BASCOM-AVR\Display 3000\Displaymodul\Bascom Programme\für Include\GLCD21_fonts.bas"
 
 
Colortable:
 
Data 0
 
</pre>
 
  
 
[[Kategorie:Microcontroller]]
 
[[Kategorie:Microcontroller]]
Zeile 5.062: Zeile 68:
 
==Hauptcontroller==
 
==Hauptcontroller==
  
Die Hauptcontroller erledigt die Lageregelung. Sie steuert die Motoren und gibt die entsprechenden Meldungen an den Anzeigecontroller aus. Sie stellt auch die 12V für den Tacho bereit. Bei beiden Controllern wird ein Chopperspannungsregler eingesetzt der bis zu 63V verträgt. Deshalb ist eine Versorgung aus dem 24..48V Netz möglich. Die Lageregelung speichert auch die gefahrenen Km, einigen Min-Max Werte und diverse Werte bei einem Notaus. Diese Werte werden im EEprom als Text abgelegt. Beachten Sie, daß Sie das Gerät dann nur noch auf Privatgelände mit Zustimmung des Eigentümers benutzen dürfen. Eine Bertriebserlaubnis für das Gerät existiert nicht. Eine Einzelabnahme kann beim TÜV beantragt werden.
+
Die Hauptcontroller erledigt die Lageregelung. Sie steuert die Motoren und gibt die entsprechenden Meldungen an den Anzeigecontroller aus. Sie stellt auch die 12V für den Tacho bereit. Bei beiden Controllern wird ein Chopperspannungsregler eingesetzt der bis zu 63V verträgt. Deshalb ist eine Versorgung aus dem 24..48V Netz möglich. Die Lageregelung speichert auch die gefahrenen Km, einigen Min-Max Werte und diverse Werte bei einem Notaus. Diese Werte werden im EEprom als Text abgelegt.
  
 
=Schaltbild=
 
=Schaltbild=
<gallery>
+
[http://www.listrik.de/html/freeware.html Dateien liegen hier:]
Image: HauptSteuerung I2C Prototyp Rev0.png|Hauptsteuerung
+
Image: MotorSteuerung Prototyp Rev0_Blatt1.png|Motorsteuerung Blatt 1
+
Image: MotorSteuerung Prototyp Rev0_Blatt2.png|Motorsteuerung Blatt 2
+
Image: Hallgeber_D_Prototyp.png|Hall D Signal
+
Image: Listrik01-Verdrahtung_Prototyp.png|Aussenverdrahtung
+
Image: Listrik01_Prototyp_Parts_Rev0.png|Stückliste
+
</gallery>
+
  
 
=Neigungssensoradapter=
 
=Neigungssensoradapter=
  
 
Im Unterschied zu ähnlichen Projekten besitzt dieses Fahrzeug einen über den I2C Bus gesteuerten Gyro und Accelerometer. Zum Beschleunigen und Bremsen werden die Sensoren gekippt.
 
Im Unterschied zu ähnlichen Projekten besitzt dieses Fahrzeug einen über den I2C Bus gesteuerten Gyro und Accelerometer. Zum Beschleunigen und Bremsen werden die Sensoren gekippt.
 +
 +
=Rechtliches=
 +
 +
Beachten Sie, daß Sie das Gerät dann nur noch auf Privatgelände mit Zustimmung des Eigentümers benutzen dürfen. Eine allgemeine Betriebserlaubnis für das Gerät existiert nicht. Eine Einzelabnahme kann beim TÜV beantragt werden.
 +
Siehe auch [http://www.gesetze-im-internet.de/mobhv/index.html Mobilitätshilfenverordnung]
  
 
=Wie geht es weiter=
 
=Wie geht es weiter=
  
 
Ich werde diese Seite updaten, je nach Fortschritt. Habe die nächsten paar Monate wenig Zeit....
 
Ich werde diese Seite updaten, je nach Fortschritt. Habe die nächsten paar Monate wenig Zeit....

Aktuelle Version vom 7. Mai 2013, 14:17 Uhr

Listrik01

Dieser Artikel ist noch in Bearbeitung.Unter Diskussion könnt ihr dem Autor eine ToDo-Liste vorgeben.

Listrik01 - Ein selbstbalancierendes Elektroeinrad

Beim Listrik01 handelt es sich um einen selbstbalancierenden Elektroroller. Die Elektronik basiert auf den Veröffentlichungen des Rutscherle 2. Die Schaltung wurde verändert um I2C Gyro und Accelerometer anschließen zu können. Die Listing wurden außerdem umfangreicher kommentiert.

Antrieb

Der Prototyp fährt mit einem 24V / 500W Gleichstrommotor. Das Gefährt ist allerdings extrem koflastig, deshalb baue ich es um auf einen 48V/1000W BLDC Motor. Vom Hersteller in China direkt importiert. Das Bild oben zeigt den GS-Prototyp. Bei der BLDC Variante werden Batterie, Steuerung und Motor in die Felge integriert. Dies sorgt für einen niedrigen Schwerkunkt. Habe mir ein 18" Motorrad Hinterrad besorgt in das alles integriert wird.

Die Sensorik wurde um 3 weitere Hallsensoren erweitert um einen Trigger je 60 Grad elektrisch zu bekommen. Die Geschwindigkeit ist auf 20km/h begrenzt.

Akkus

Der Gleichstrom Prototyp fährt mit 2 Bleiakkus mit 12V/7AH in Reihe geschaltet. Sie sind für Motoren und Elektronik. Die Entscheidung für Bleiakkus wurde bewusst getroffen. Bei einem Prototyp sind Ergebnisse wichtiger als Eleganz.

Der BLDC Prototyp fährt mit 4 Bleiakkus mit 12V/7AH in Reihe geschaltet. Sie sind für Motoren und Elektronik.

Elektronik

Motorregler mit Atmega 168A sowie eine Hauptsteuerung mit einem Atmega 644PA. Ein Display von Display3000 als Tacho (und Datenlogger). Siehe Stückliste.

Software

Die Software ist in Basic mit BASCOM geschrieben. Zeitkritische Teile in Assembler. Siehe Link oben zum Rutscherle 2.

Sicherheitshinweis

Achtung! Gehen Sie so ein Projekt nur an, wenn Sie sehr gute Kenntisse in Mechanik und Elektronik haben.

Programme

Motorcontroller.bas (BASCOM)

Hauptsteuerung.bas (BASCOM)

Display3000.bas (BASCOM)

Funktion

Kippt das Fahrzeug nach vorn, wird nach vorn beschleunigt und umgekehrt. Die Regelung 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 aufwändig wird es bei den Motorreglern. Eine reine Blockkommutierung, wie bei solchen Motoren üblich, ist auf unebenen Untergründen suboptimal. Hier wurde zusätzliche Hallsensoren installiert.

Die seitliche Stabilität garantiert der Kreiseleffekt den jeder vom Fahrrad kennt. Das endgültige Fahrzeug wird eine Lenkung bekommen, die auf dem Beharrungsmoment basiert. Eine konventionelle Lenkung ist nicht möglich weil es nur ein Rad gibt.

Elektronik

Motorcontroller

Der Motorcontroller regelt den Motor, 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 Einheit wird vom PC aus über eine ISP Schnittstelle programmiert.

Der Motorregler ist auf einer doppelseitigen Platine aufgebaut. Die Verbindung zwischen den beiden Platinen bildet ein 10-adriges Flachkabel. 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.

Hauptcontroller

Die Hauptcontroller erledigt die Lageregelung. Sie steuert die Motoren und gibt die entsprechenden Meldungen an den Anzeigecontroller aus. Sie stellt auch die 12V für den Tacho bereit. Bei beiden Controllern wird ein Chopperspannungsregler eingesetzt der bis zu 63V verträgt. Deshalb ist eine Versorgung aus dem 24..48V Netz möglich. Die Lageregelung speichert auch die gefahrenen Km, einigen Min-Max Werte und diverse Werte bei einem Notaus. Diese Werte werden im EEprom als Text abgelegt.

Schaltbild

Dateien liegen hier:

Neigungssensoradapter

Im Unterschied zu ähnlichen Projekten besitzt dieses Fahrzeug einen über den I2C Bus gesteuerten Gyro und Accelerometer. Zum Beschleunigen und Bremsen werden die Sensoren gekippt.

Rechtliches

Beachten Sie, daß Sie das Gerät dann nur noch auf Privatgelände mit Zustimmung des Eigentümers benutzen dürfen. Eine allgemeine Betriebserlaubnis für das Gerät existiert nicht. Eine Einzelabnahme kann beim TÜV beantragt werden. Siehe auch Mobilitätshilfenverordnung

Wie geht es weiter

Ich werde diese Seite updaten, je nach Fortschritt. Habe die nächsten paar Monate wenig Zeit....


LiFePO4 Speicher Test