https://rn-wissen.de/wiki/api.php?action=feedcontributions&user=Colindrovin&feedformat=atomRN-Wissen.de - Benutzerbeiträge [de]2024-03-29T10:56:10ZBenutzerbeiträgeMediaWiki 1.25.1https://rn-wissen.de/wiki/index.php?title=Rutscherle_-_selbstbalancierender_Elektroroller&diff=19581Rutscherle - selbstbalancierender Elektroroller2012-05-12T21:39:17Z<p>Colindrovin: /* Schaltbilder */</p>
<hr />
<div>[[Bild:kltrutscherle2.jpg|right|thumb|Rutscherle 2]]<br />
<br />
Dieser Artikel ist noch in Bearbeitung. Unter [http://www.rn-wissen.de/index.php/Diskussion:Rutscherle Diskussion] könnt ihr dem Autor eine ToDo-Liste vorgeben.<br />
= Rutscherle 2 - Ein selbstbalancierender Elektroroller =<br />
<br />
<br />
Beim Rutscherle 2 handelt es sich um einen selbstbalancierenden Elektroroller mit großer Ähnlichkeit zum bekannten [http://de.wikipedia.org/wiki/Segway_Personal_Transporter Segway]. Es war und ist beabsichtigt, besser zu sein als das Original. Auch wenn das bisher noch nicht ganz gelungen ist. Dies ist kein kommerzielles Projekt und soll es auch nicht werden.<br />
<br />
<br />
Und so fährts:<br><br />
[http://www.youtube.com/watch?v=YAuZ9zhxNV8 Video]<br />
== Technische Daten ==<br />
<br />
===Antrieb===<br />
<br />
2 BLDC Felgenmotoren mit je 1000W/36V. Vom Hersteller in China direkt importiert. Mittlerweile gibt es auch in Europa vergleichbare Motoren zu kaufen. Die stammen zwar auch aus China, müssen jedoch nicht selbst importiert werden. Die Motoren sind im Lieferzustand nicht direkt verwendbar. Die Sensorik muss um 3 weitere Hallsensoren erweitert werden. Die bisherige Höchstgeschwindigkeit beträgt 27km/h.<br />
<br />
===Akkus===<br />
<br />
4 Bleiakkus mit 12V/18AH von denen 3 in Reihe geschaltet sind für die Motoren, einer allein für die Steuerung und eine zukünftige Beleuchtung. Geladen werden die Akkus an einem handelsüblichen Kfz-Ladegerät. Die Reichweite beträgt auf jeden Fall mehr als 20km. Die Entscheidung für Bleiakkus wurde bewusst getroffen. Eine kWh verteuert sich um ca. 50 cent wenn sie durch den Bleiakku geht bei Litium-Polymer-Akkus sind das ca. 5 Euro. Auch sind Bleiakkus beim Laden wesentlich unempfindlicher.<br />
<br />
===Elektronik===<br />
<br />
2 Motorregler mit Atmega 168/10Mhz sowie eine Hauptsteuerung mit einem Atmega 644/20Mhz. Zusätzlich noch ein Display von Display3000 als Tacho und Datenlogger. Beschleunigungssensor: ADXL335, Gyros: LISY300AL <br />
(ArduIMU Sensor Board - Six Degrees of Freedom)<br />
Die ganze Elektronik wurde sehr einfach gehalten. (Zu mehr hats nicht gereicht) Das hat aber den Vorteil, daß keine besonderen Spezialkentnisse erforderlich sind. Wer schonmal eine Platine mit dem Bügeleisen hergestellt hat bekommt auch das hin.<br />
<br />
===Software===<br />
<br />
Die Software ist in Bascom geschrieben. Zeitkritische Teile in Assembler.<br />
<br />
===Mechanik===<br />
<br />
Der Mechanische Aufbau besteht nahezu komplett aus Aluminium. Dabei wurde darauf geachtet, dass alles mit einfachen Werkzeugen herstellbar ist. (Eine Ständerbohrmaschine sollte man schon haben.) Die Konstruktion ist so ausgelegt, dass so wenige Teile wie möglich hinter den Rädern hervorstehen. Dies verhindert Kratzer bei den ersten Fahrversuchen.<br />
<br />
===Entwicklungskosten===<br />
<br />
Im Vergleich zu den Entwicklungskosten des Originals, laut Wikipedia 100 Mio US$, liegt dieses Projekt mit unter 2000€ zuzüglich Zeit noch im erträglichen Bereich.<br />
<br />
==Sicherheitshinweis==<br />
<br />
<div style="margin:1em; padding:1em; border:solid 2px #FF0040; background-color:#FFFFFF"><br />
''Achtung! Gehen Sie so ein Projekt nur an, wenn Sie genau wissen, auf was Sie sich da einlassen. Man braucht schon ein paar Elektronik-Kenntnisse. Es können an der Elektonik sehr hohe Ströme auftreten und so entstehen schnell Rauchwölkchen. An den Motoren können - vor allem im Fehlerfall - sehr hohe Drehmomente entstehen, die für Mobiliar und Knochen sehr beeindruckend sein können. Zwei linke Hände wären also fehl am Platz. Beschweren Sie sich also bei sich selbst, wenn Sie im Krankenhaus aufwachen sollten. Sie haben es so gewollt.''<br />
</div><br />
<br />
=Funktion=<br />
<br />
Die Funktion ist im groben recht banal. Im Prinzip macht das Teil das gleiche wie jeder Mensch beim gehen. Kommt ein Mensch nach vorn aus dem Gleichgewicht macht er einen Schritt nach vorn. Entsprechend nach hinten. Hier wird dieses Vorgehen elektronisch nachbildet. Kippt die Platform nach vorn, dann wird nach vorn beschleunigt und umgekehrt. Die genaue technische Umsetzung ist dann doch etwas aufwändiger. Die Regelung selbst erledigt ein PID-Regler. Danach kommen jedoch noch einige zusätzliche Faktoren die z.B. die Motorkennlinie ausgleichen sowie ungewollte Richtungsänderungen bei unebenen Oberflächen reduzieren. Ähnlich aufwändig wird es bei den Motorreglern. Eine reine Blockkommutierung, wie bei solchen Motoren üblich, ist auf nicht ebenen Untergründen suboptimal. Ich habe die Motoren um zusätzliche Hallsensoren erweitert und diese außerdem mit Drehstrom oder genauer: Drehspannung angesteuert.<br />
<br />
=Elektronik=<br />
<br />
==Motorregler==<br />
<br />
Der Motorregler regelt natürlich den Motor. Zusätzlich misst und übermittelt der Motorregler auch Spannung, Strom und Fahrstrecke. Die Temperatur des Kühlkörpers wird ebenfalls gemessen und wenn nötig ein Lüfter zugeschaltet. Die Ansteuerung des Motors ist keine Blockkomutierung. Diese hatte sich bei Experimenten als verbesserungswürdig gezeigt. Tatsächlich wird auf den 3 Leitungen eine angenäherte Sinusspannung ausgegeben. Das reduziert die Drehmomentwelligkeit deutlich.<br />
Ob und wieweit sich dadurch der Motorwirkungsgrad ändert wurde bisher nicht gemessen.<br />
Die ganze Einheit wird vom PC aus über die Serielle Schnittstelle (5V) parametriert und kalibriert.<br />
<br />
Der Motorregler ist auf zwei Platinen aufgebaut. Der Grund dafür ist die einfachere Herstellung der Platinen mit der Bügeleisenmethode sowie die räumliche Trennung der hohen Ströme vom Kontroller. Ob dies wegen der Störsicherheit wirklich notwendig ist wurde aus Kostengründen nie getestet. An der Stelle ist aber eine unnötige Sicherheit besser als eine vergessene. Die Verbindung zwischen den beiden Platinen bildet ein 16-adriges Flachkabel. Programmierstecker und der serielle Bus werden seitlich am Controllerboard gesteckt. Die Verbindung zu den Hallsensoren wird über ein 6-adriges Flachkabel hergestellt. Zusätzlich zu den beiden Platinen gehört zum Motorregler auch die im Motor verbaute Sensorplatine. Auf dieser werden die Signale der drei zusätzlichen Hallsensoren zu einem Signal zusammengefasst. Nach einem Ausfall wurde auch noch eine Zusatzplatine mit den Snubbern und den Supressordioden nachgerüstet. Zuvor war nämlich eine Halbbrücke nach ca. 125 km Fahrt ausgefallen.<br />
===Schaltbilder===<br />
<gallery><br />
Image:Rutscherle2_4.JPG|Motorregler (ohne Snubber)<br />
Image:Rutscherle2_1.gif|Controllerboard<br />
Image:Rutscherle2_2.GIF|Hochstromteil<br />
Image:Rutscherle2_3.gif|Snubber<br />
</gallery><br />
<br />
===Software Version 19===<br />
<br />
<pre><br />
'Version 19<br />
<br />
<br />
$prog &HFF , &HFF , &HD4 , &HF9 'Fusebits<br />
$regfile = "m168def.dat"<br />
$crystal = 10000000<br />
$baud = 57600 <br />
$hwstack = 32<br />
$swstack = 10<br />
$framesize = 40<br />
<br />
Declare Sub Setspeed<br />
Declare Sub Pwm_start<br />
Declare Sub Pwm_stop<br />
<br />
Config Portc.0 = Input 'UBAT<br />
Config Portc.1 = Input 'USHUNT<br />
Config Portc.2 = Input 'TEMP<br />
Config Portc.3 = Output 'LED1<br />
Config Portc.4 = Output 'Lüfter<br />
Config Portc.5 = Input 'Jumper1<br />
<br />
Config Portd.2 = Input 'Hall_C<br />
Config Portd.3 = Output 'A+<br />
Config Portd.4 = Input 'Hall_B<br />
Config Portd.5 = Output 'C+<br />
Config Portd.6 = Output 'C-<br />
Config Portd.7 = Input 'Hall_A<br />
Config Portb.0 = Input 'Hall_D<br />
Config Portb.1 = Output 'B-<br />
Config Portb.2 = Output 'B+<br />
Config Portb.3 = Output 'A-<br />
Config Portb.4 = Output 'LED2<br />
Config Portb.5 = Input 'Unbelegt (SCK)<br />
<br />
Hall_a Alias Pind.7 'gelb<br />
Hall_b Alias Pind.4 'blau<br />
Hall_c Alias Pind.2 'Grün<br />
Hall_d Alias Pinb.0<br />
Led1 Alias Portc.3<br />
Led2 Alias Portb.4<br />
Fan Alias Portc.4<br />
Jumper1 Alias Pinc.5<br />
<br />
Dim Uzu As Integer At $100<br />
Dim Izu As Integer At $102<br />
Dim Ausgabeticks As Integer At $104 'Anzahl Kommutieren zwischen Seriellen Telegrammen<br />
Dim Temperatur As Integer At $106 '<br />
Dim Drehzahl As Integer At $108 'Drehzahl<br />
Dim M1 As Byte At $100 Overlay<br />
Dim M2 As Byte At $101 Overlay<br />
Dim M3 As Byte At $102 Overlay<br />
Dim M4 As Byte At $103 Overlay<br />
Dim M5 As Byte At $104 Overlay<br />
Dim M6 As Byte At $105 Overlay<br />
Dim M7 As Byte At $106 Overlay<br />
Dim M8 As Byte At $107 Overlay<br />
Dim M9 As Byte At $108 Overlay<br />
Dim M10 As Byte At $109 Overlay<br />
Dim Kalibrierwert As Integer At $10a<br />
Dim Kal(2) As Byte At $10a Overlay<br />
Dim A(15) As Byte At $10c<br />
Dim S(12) As Byte At $11b<br />
Dim Sinus(12) As Byte At $127<br />
Dim Richtung(255) As Byte At $133<br />
Dim Motorposition As Byte At $232<br />
Dim Istrichtung As Integer At $233<br />
Dim Altrichtung As Integer At $235<br />
Dim Aposition As Byte At $237<br />
Dim Zposition As Byte At $238<br />
Dim Zwangskommutieren As Byte At $239<br />
Dim Temp As Word At $23a<br />
Dim Fancount As Word At $23c<br />
Dim Motoradresse As Byte At $23e<br />
Dim Vwinkel As Byte At $23f<br />
Dim Rwinkel As Byte At $240<br />
Dim Ticks As Integer At $241<br />
Dim N As Byte At $243<br />
Dim Notaus As Byte At $244<br />
Dim Loopcount As Word At $245<br />
Dim Sollrichtung As Byte At $247<br />
Dim Altsollrichtung As Byte At $248<br />
Dim Sollspeed As Byte At $249<br />
Dim Altsollspeed As Byte At $24a<br />
Dim Bdummy As Byte At $24b<br />
Dim Intbdummy As Byte At $24c<br />
Dim Intidummy As Integer At $24d<br />
Dim Sdummy As Single At $24f<br />
Dim Idummy1 As Integer At $253<br />
Dim Idummy2 As Integer At $255<br />
Dim Uw As Word At $257<br />
Dim Iw As Word At $259<br />
Dim Uwsum As Long At $25b<br />
Dim Iwsum As Long At $25f<br />
Dim Wcount As Long At $263<br />
Dim Uoffset As Single At $267<br />
Dim Ufaktor As Single At $26b<br />
Dim Ioffset As Single At $26f<br />
Dim Ifaktor As Single At $273<br />
Dim Ep0 As Byte At $277<br />
Dim Ep1 As Byte At $278<br />
Dim Ep2 As Byte At $279<br />
Dim Ep3 As Byte At $27a<br />
Dim Ep4 As Byte At $27b<br />
Dim Ep5 As Byte At $27c<br />
Dim Ta As Byte At $27d<br />
Dim Tb As Byte At $27e<br />
Dim Tc As Byte At $27f<br />
Dim Fehler As Byte At $280<br />
Sollspeed = 0<br />
Pwm_stop 'Erstmal alles auschalten<br />
'Variablen für die Richtungserkennung vorbelegen<br />
'Diese Variante frisst zwar viel Arbeitsspeicher, ist aber sehr schnell<br />
For N = 1 To 15<br />
A(n) = 0<br />
Next<br />
<br />
For N = 1 To 255<br />
Richtung(n) = 2<br />
Next<br />
<br />
If Jumper1 = 0 Then 'R<br />
Motoradresse = 82<br />
A(12) = 12<br />
A(4) = 11<br />
A(6) = 10<br />
A(14) = 9<br />
A(10) = 8<br />
A(2) = 7<br />
A(3) = 6<br />
A(11) = 5<br />
A(9) = 4<br />
A(1) = 3<br />
A(5) = 2<br />
A(13) = 1<br />
Richtung(21) = 3<br />
Richtung(93) = 3<br />
Richtung(220) = 3<br />
Richtung(196) = 3<br />
Richtung(70) = 3<br />
Richtung(110) = 3<br />
Richtung(234) = 3<br />
Richtung(162) = 3<br />
Richtung(35) = 3<br />
Richtung(59) = 3<br />
Richtung(185) = 3<br />
Richtung(145) = 3<br />
Richtung(81) = 1<br />
Richtung(25) = 1<br />
Richtung(155) = 1<br />
Richtung(179) = 1<br />
Richtung(50) = 1<br />
Richtung(42) = 1<br />
Richtung(174) = 1<br />
Richtung(230) = 1<br />
Richtung(100) = 1<br />
Richtung(76) = 1<br />
Richtung(205) = 1<br />
Richtung(213) = 1<br />
Else<br />
Motoradresse = 76 'L<br />
A(11) = 1<br />
A(3) = 2<br />
A(1) = 3<br />
A(9) = 4<br />
A(13) = 5<br />
A(5) = 6<br />
A(4) = 7<br />
A(12) = 8<br />
A(14) = 9<br />
A(6) = 10<br />
A(2) = 11<br />
A(10) = 12<br />
Richtung(236) = 3<br />
Richtung(196) = 3<br />
Richtung(69) = 3<br />
Richtung(93) = 3<br />
Richtung(217) = 3<br />
Richtung(145) = 3<br />
Richtung(19) = 3<br />
Richtung(59) = 3<br />
Richtung(186) = 3<br />
Richtung(162) = 3<br />
Richtung(38) = 3<br />
Richtung(110) = 3<br />
Richtung(42) = 1<br />
Richtung(171) = 1<br />
Richtung(179) = 1<br />
Richtung(49) = 1<br />
Richtung(25) = 1<br />
Richtung(157) = 1<br />
Richtung(213) = 1<br />
Richtung(84) = 1<br />
Richtung(76) = 1<br />
Richtung(206) = 1<br />
Richtung(230) = 1<br />
Richtung(98) = 1<br />
End If<br />
<br />
<br />
<br />
<br />
'AD-Wandler einstellen<br />
Config Adc = Single , Prescaler = Auto , Reference = Off<br />
Start Adc<br />
<br />
'<Test Hallsensoren><br />
Fehler = 1<br />
Fan = 1<br />
While Fehler = 1<br />
Fehler = 0<br />
Motorposition = 0<br />
Motorposition.0 = Hall_a<br />
Motorposition.1 = Hall_b<br />
Motorposition.2 = Hall_c<br />
Motorposition.3 = Hall_d<br />
If Motorposition = 0 Then Fehler = 1 'Stecker nicht gesteckt<br />
If Motorposition > 0 Then<br />
If A(motorposition) = 0 Then Fehler = 1 'Das währe eine Motorposition die es nicht gibt!<br />
End If<br />
If Fehler = 1 Then<br />
Toggle Led1<br />
Toggle Led2<br />
Waitms 500<br />
End If<br />
Wend<br />
'</Test Hallsensoren><br />
<br />
On Timer2 Update_pwm Nosave<br />
<br />
'Pin-Change Interrupt einstellen:<br />
Pcmsk2 = &B10010100<br />
Pcmsk1 = &B00000000<br />
Pcmsk0 = &B00000001<br />
Pcicr = &B00000101<br />
<br />
On Pcint2 Kommutieren Nosave<br />
On Pcint0 Kommutieren Nosave<br />
<br />
Readeeprom Uoffset , 1<br />
Readeeprom Ufaktor , 5<br />
Readeeprom Ioffset , 9<br />
Readeeprom Ifaktor , 13<br />
'Angepasste Sinuskurve aus dem EEprom laden<br />
For N = 1 To 12<br />
Bdummy = N + 16<br />
Readeeprom Sinus(n) , Bdummy<br />
Next<br />
'Voreilwinkel:<br />
Readeeprom Vwinkel , 29<br />
Readeeprom Rwinkel , 30<br />
<br />
If Ufaktor = 0 Then Ufaktor = 1<br />
If Ifaktor = 0 Then Ifaktor = 1<br />
<br />
<br />
On Urxc Datenempfang Nosave<br />
Enable Urxc<br />
Enable Interrupts<br />
<br />
<br />
<br />
Fancount = 15000 'Lüfter erstmal einschalten<br />
<br />
Do<br />
Led1 = 0<br />
<br />
'<Messen><br />
Uw = Getadc(0)<br />
Uwsum = Uwsum + Uw<br />
Iw = Getadc(1)<br />
Iwsum = Iwsum + Iw<br />
Incr Wcount<br />
Temp = Getadc(2)<br />
'</Messen><br />
<br />
<br />
'<Serielle Telegramme abarbeiten><br />
If Ep0 = 13 Then<br />
If Ep5 = 13 Then<br />
If Ep1 = Motoradresse Then '"R", "L"<br />
Disable Urxc<br />
$asm<br />
lds R24,{EP1}<br />
LDs R25,{EP2}<br />
add R24,R25<br />
LDs R25,{EP3}<br />
add R24,R25<br />
STS {Bdummy},R24<br />
$end Asm<br />
If Bdummy = Ep4 Then 'Die Prüfsumme stimmt<br />
Led1 = 1<br />
Pcicr = &B00000000 'Kommutieren kurz deaktivieren, weil sonst die Ticks während dem Zugriff geändert werden könnten<br />
Ausgabeticks = Ticks<br />
Ticks = 0<br />
Pcicr = &B00000101<br />
<br />
$asm<br />
lds R24,{M1}<br />
LDs R25,{M2}<br />
add R24,R25<br />
LDs R25,{M3}<br />
add R24,R25<br />
LDs R25,{M4}<br />
add R24,R25<br />
LDs R25,{M5}<br />
add R24,R25<br />
LDs R25,{M6}<br />
add R24,R25<br />
STS {Bdummy},R24<br />
'Antwort ausgeben<br />
'Print Chr(m1) ; Chr(m2) ; Chr(m3) ; Chr(m4) ; Chr(m5) ; Chr(m6) ; Chr(bdummy) ; Chr(13) ;<br />
LdS R24,{M1}<br />
STS udr,R24<br />
Warten1:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten1<br />
LDS R24,{M2}<br />
STS udr,R24<br />
Warten2:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten2<br />
lds R24,{M3}<br />
STS udr,R24<br />
Warten3:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten3<br />
LDS R24,{M4}<br />
STS udr,R24<br />
Warten4:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten4<br />
LDS R24,{M5}<br />
STS udr,R24<br />
Warten5:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten5<br />
LDS R24,{M6}<br />
STS udr,R24<br />
Warten6:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten6<br />
LDS R24,{bdummy}<br />
STS udr,R24<br />
Warten7:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten7<br />
LDi R24,13<br />
STS udr,R24<br />
Warten8:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten8<br />
$end Asm<br />
If Ep2 < 3 Then<br />
Notaus = 0<br />
Loopcount = 0<br />
Sollrichtung = Ep2<br />
Sollspeed = Ep3<br />
If Sollrichtung = 2 Then<br />
Sollrichtung = 1<br />
Notaus = 1<br />
Loopcount = 250<br />
Sollspeed = 0<br />
End If<br />
Setspeed<br />
'<Messwerte berechnen><br />
'Messwerte werden hier berechnet, weil genau jetzt 1/100s Zeit ist.<br />
'Spannung berechnen<br />
Sdummy = Uwsum / Wcount<br />
Sdummy = Sdummy - Uoffset<br />
Sdummy = Sdummy * Ufaktor<br />
Uzu = Int(sdummy)<br />
Uwsum = 0<br />
'Strom berechnen<br />
Sdummy = Iwsum / Wcount<br />
Sdummy = Sdummy - Ioffset<br />
Sdummy = Sdummy * Ifaktor<br />
Izu = Int(sdummy)<br />
Iwsum = 0<br />
Wcount = 0<br />
'</Messwerte berechnen><br />
Else<br />
Select Case Ep2<br />
Case 3 'Sinus(1) empfangen<br />
Sinus(1) = Ep3<br />
Writeeeprom Sinus(1) , 17<br />
Case 4 'Sinus(2) empfangen<br />
Sinus(2) = Ep3<br />
Writeeeprom Sinus(2) , 18<br />
Case 5 'Sinus(3) empfangen<br />
Sinus(3) = Ep3<br />
Writeeeprom Sinus(3) , 19<br />
Case 6 'Sinus(4) empfangen<br />
Sinus(4) = Ep3<br />
Writeeeprom Sinus(4) , 20<br />
Case 7 'Sinus(5) empfangen<br />
Sinus(5) = Ep3<br />
Writeeeprom Sinus(5) , 21<br />
Case 8 'Sinus(6) empfangen<br />
Sinus(6) = Ep3<br />
Writeeeprom Sinus(6) , 22<br />
Case 9 'Sinus(7) empfangen<br />
Sinus(7) = Ep3<br />
Writeeeprom Sinus(7) , 23<br />
Case 10 'Sinus(8) empfangen<br />
Sinus(8) = Ep3<br />
Writeeeprom Sinus(8) , 24<br />
Case 11 'Sinus(9) empfangen<br />
Sinus(9) = Ep3<br />
Writeeeprom Sinus(9) , 25<br />
Case 12 'Sinus(10) empfangen<br />
Sinus(10) = Ep3<br />
Writeeeprom Sinus(10) , 26<br />
Case 13 'Sinus(11) empfangen<br />
Sinus(11) = Ep3<br />
Writeeeprom Sinus(11) , 27<br />
Case 14 'Sinus(12) empfangen<br />
Sinus(12) = Ep3<br />
Writeeeprom Sinus(12) , 28<br />
Case 15 'Spannung Kalibrieren (Byte 1)<br />
Kal(1) = Ep3<br />
Case 16 'Spannung Kalibrieren (Byte 2)<br />
Kal(2) = Ep3<br />
Sdummy = Uwsum / Wcount<br />
Ufaktor = Kalibrierwert / Sdummy<br />
Writeeeprom Ufaktor , 5<br />
Uoffset = 0 'Schaltungsbedingt<br />
Writeeeprom Uoffset , 1<br />
Case 17 'Strom Kalibrieren (Byte 1)<br />
Kal(1) = Ep3<br />
Case 18 'Strom Kalibrieren Byte (2)<br />
Kal(2) = Ep3<br />
Sdummy = Iwsum / Wcount<br />
If Kalibrierwert = 0 Then 'Das ist der Offset<br />
Ioffset = Sdummy + 1<br />
Writeeeprom Ioffset , 9<br />
Else 'Jetzt den Faktor berechnen<br />
Sdummy = Sdummy - Ioffset<br />
Ifaktor = Kalibrierwert / Sdummy<br />
Writeeeprom Ifaktor , 13<br />
End If<br />
Case 19<br />
Vwinkel = Ep3<br />
Writeeeprom Vwinkel , 29<br />
Case 20<br />
Rwinkel = Ep3<br />
Writeeeprom Rwinkel , 30<br />
<br />
End Select<br />
End If<br />
<br />
$asm 'Empfangspuffer löschen<br />
LDI R24,0<br />
sTS {EP1},R24<br />
sTS {EP2},R24<br />
sTS {EP3},R24<br />
sTS {EP4},R24<br />
$end Asm<br />
<br />
End If<br />
Enable Urxc<br />
<br />
End If<br />
End If<br />
End If<br />
'</Serielle Telegramme abarbeiten><br />
<br />
<br />
<br />
'<Lüfter schalten><br />
If Temp > 740 Then Fancount = 15000 'Schaltet den Lüfter ein<br />
If Fancount > 0 Then<br />
Fan = 1<br />
Else<br />
Fan = 0<br />
End If<br />
If Fancount > 0 Then Decr Fancount<br />
'</Lüfter schalten><br />
<br />
<br />
'Notaus mit Freilauf wenn keine Nachricht von Seriell<br />
If Loopcount < 50 Then 'Das sind schätzungsweise 0.1s<br />
Led2 = 1<br />
Notaus = 0<br />
Incr Loopcount<br />
Else<br />
Led2 = 0<br />
Notaus = 1<br />
Sollspeed = 0<br />
Setspeed<br />
End If<br />
Loop<br />
<br />
<br />
'********************************************************************************************<br />
Kommutieren:<br />
$asm<br />
PUSH R10<br />
PUSH R11<br />
PUSH R16<br />
PUSH R17<br />
PUSH R20<br />
PUSH R21<br />
PUSH R24<br />
PUSH R26<br />
PUSH R27<br />
IN R24,sreg<br />
PUSH R24<br />
clr R16<br />
lds R17, $0023<br />
BST R17,0<br />
BLD R16,3<br />
LDS R17, $0029<br />
BST R17,2<br />
bld R16,2<br />
BST R17,4<br />
bld R16,1<br />
BST R17,7<br />
bld R16,0<br />
lds R17,{aposition}<br />
!swap R17<br />
andi R17,&B11110000<br />
add R17,R16<br />
STS {Aposition},R17<br />
CLR R17<br />
LDI R26,$0B<br />
LDI R27,$01<br />
ADD R26,R16<br />
ADC R27,R17<br />
LD R24,X<br />
LDS R16,{Sollrichtung}<br />
CPI R16,0<br />
BREQ Sollrichtungnull<br />
Jmp Sollrichtungnichtnull<br />
Sollrichtungnull:<br />
LDS R20,{Vwinkel}<br />
Add R24,R20<br />
JMP Richtunggesetzt<br />
Sollrichtungnichtnull:<br />
LDS R20,{Rwinkel}<br />
Add R24,R20<br />
Richtunggesetzt:<br />
CPI R24,$0D<br />
BRCC Istgroesser13_1<br />
JMP Istkleiner13_1<br />
Istgroesser13_1:<br />
SUBI R24,$0C<br />
Istkleiner13_1:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Ta},R16<br />
subi R24,$fc<br />
CPI R24,$0D<br />
BRCC Istgroesser13_2<br />
JMP Istkleiner13_2<br />
Istgroesser13_2:<br />
SUBI R24,$0C<br />
Istkleiner13_2:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Tc},R16<br />
subi R24,$fc<br />
CPI R24,$0D<br />
BRCC Istgroesser13_3<br />
JMP Istkleiner13_3<br />
Istgroesser13_3:<br />
SUBI R24,$0C<br />
Istkleiner13_3:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Tb},R16<br />
lds R10,{Aposition}<br />
CLR R11<br />
LDI R26,$32<br />
LDI R27,$01<br />
ADD R26,R10<br />
ADC R27,R11<br />
LD R16,X+<br />
CLR R17<br />
LDI R20,$02<br />
LDI R21,$00<br />
!Sub R16 , R20<br />
SBC R17,R21<br />
LDI R26,$33<br />
LDI R27,$02<br />
ST X+,R16<br />
ST X,R17<br />
LDI R26,$41<br />
LDI R27,$02<br />
LD R16,X+<br />
LD R17,X<br />
LDI R26,$33<br />
LDI R27,$02<br />
LD R20,X+<br />
LD R21,X<br />
ADD R16,R20<br />
ADC R17,R21<br />
LDI R26,$41<br />
LDI R27,$02<br />
ST X+,R16<br />
ST X,R17<br />
LDS R24,timsk2<br />
ORI R24,$01<br />
STS timsk2,R24<br />
POP R24<br />
!Out sreg , R24<br />
POP R27<br />
POP R26<br />
POP R24<br />
POP R21<br />
POP R20<br />
POP R17<br />
POP R16<br />
POP R11<br />
POP R10<br />
$end Asm<br />
<br />
Return<br />
'********************************************************************************************<br />
<br />
<br />
<br />
<br />
<br />
'********************************************************************************************<br />
Update_pwm:<br />
$asm<br />
PUSH R24<br />
IN R24,sreg<br />
PUSH R24<br />
lds R24,{Ta}<br />
STS ocr2a,R24<br />
STS ocr2b,R24<br />
LDS R24,{Tb}<br />
STS ocr1al,R24<br />
STS ocr1bl,R24<br />
lds R24,{Tc}<br />
!OUT ocr0a,R24<br />
!OUT ocr0b,R24<br />
LDS R24,timsk2<br />
ANDI R24,$FE<br />
STS timsk2,R24<br />
POP R24<br />
!OUT sreg,R24<br />
POP R24<br />
$end Asm<br />
Return<br />
'********************************************************************************************<br />
<br />
<br />
'********************************************************************************************<br />
Datenempfang:<br />
$asm<br />
PUSH R24;<br />
IN R24, SREG;<br />
PUSH R24;<br />
LDS R24,{EP1}<br />
STS {EP0},R24<br />
LDS R24,{EP2}<br />
STS {EP1},R24<br />
LDS R24,{EP3}<br />
STS {EP2},R24<br />
LDS R24,{EP4}<br />
STS {EP3},R24<br />
LDS R24,{EP5}<br />
STS {EP4},R24<br />
IN R24,UDR<br />
STs {EP5},R24<br />
POP R24;<br />
Out Sreg , R24;<br />
POP R24;<br />
$end Asm<br />
Return<br />
'********************************************************************************************<br />
<br />
'********************************************************************************************<br />
Sub Setspeed<br />
<br />
<br />
<br />
If Notaus = 1 Then<br />
Pwm_stop<br />
Sollspeed = 0<br />
For N = 1 To 12<br />
S(n) = 0<br />
Next<br />
Else<br />
For N = 1 To 12<br />
Idummy1 = Sollspeed * Sinus(n)<br />
Idummy1 = Idummy1 / 100<br />
S(n) = Idummy1<br />
Next<br />
If Tccr0a = 0 Then 'Wenn die PWM aus ist<br />
Pwm_start<br />
End If<br />
'<Zwangskommutieren><br />
Zwangskommutieren = 0<br />
If Sollrichtung <> Altsollrichtung Then Zwangskommutieren = 1<br />
If Sollspeed <> Altsollspeed Then Zwangskommutieren = 1<br />
<br />
If Zwangskommutieren = 1 Then<br />
Pcicr = &B00000000 'Den Eigentlichen Kommutierinterrupt abschalten<br />
$asm<br />
clr R16<br />
lds R17, $0023<br />
BST R17,0<br />
BLD R16,3<br />
LDS R17, $0029<br />
BST R17,2<br />
bld R16,2<br />
BST R17,4<br />
bld R16,1<br />
BST R17,7<br />
bld R16,0<br />
lds R17,{aposition}<br />
!swap R17<br />
andi R17,&B11110000<br />
add R17,R16<br />
STS {Aposition},R17<br />
CLR R17<br />
LDI R26,$0B<br />
LDI R27,$01<br />
ADD R26,R16<br />
ADC R27,R17<br />
LD R24,X<br />
LDS R16,{Sollrichtung}<br />
CPI R16,0<br />
BREQ Sollrichtungnullz<br />
Jmp Sollrichtungnichtnullz<br />
Sollrichtungnullz:<br />
LDS R20,{Vwinkel}<br />
Add R24,R20<br />
JMP Richtunggesetztz<br />
Sollrichtungnichtnullz:<br />
LDS R20,{Rwinkel}<br />
Add R24,R20<br />
Richtunggesetztz:<br />
CPI R24,$0D<br />
BRCC Istgroesser13_1z<br />
JMP Istkleiner13_1z<br />
Istgroesser13_1z:<br />
SUBI R24,$0C<br />
Istkleiner13_1z:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Ta},R16<br />
subi R24,$fc<br />
CPI R24,$0D<br />
BRCC Istgroesser13_2z<br />
JMP Istkleiner13_2z<br />
Istgroesser13_2z:<br />
SUBI R24,$0C<br />
Istkleiner13_2z:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Tc},R16<br />
subi R24,$fc<br />
CPI R24,$0D<br />
BRCC Istgroesser13_3z<br />
JMP Istkleiner13_3z<br />
Istgroesser13_3z:<br />
SUBI R24,$0C<br />
Istkleiner13_3z:<br />
CLR R20<br />
Ldi R26,$1a<br />
LDI R27,$01<br />
ADD R26,R24<br />
ADC R27,R20<br />
LD R16,X<br />
STS {Tb},R16<br />
$end Asm<br />
Pcicr = &B00000101 'Den Eigentlichen Kommutierinterrupt einschalten<br />
'Nur Overflow Interrupt (Seite 105)<br />
Timsk2.toie2 = 1<br />
<br />
Toggle Led2<br />
<br />
End If<br />
<br />
'</Zwangskommutieren><br />
End If<br />
Altsollrichtung = Sollrichtung<br />
Altsollspeed = Sollspeed<br />
End Sub<br />
'********************************************************************************************<br />
<br />
'********************************************************************************************<br />
Sub Pwm_start<br />
Disable Interrupts 'Damit die Timer auch wirklich synchron laufen<br />
Tccr0a = 161<br />
Tccr0b = 1<br />
Ocr0a = 0<br />
Ocr0b = 0<br />
Tccr1a = 161<br />
Tccr1b = 1<br />
Ocr1ah = 0<br />
Ocr1al = 0<br />
Ocr1bh = 0<br />
Ocr1bl = 0<br />
Tccr2a = 161<br />
Tccr2b = 1<br />
Ocr2a = 0<br />
Ocr2b = 0<br />
Tcnt0 = 0 'Timer Startwert, wegen Synchron<br />
Tcnt1 = 6 'Timer Startwert, wegen Synchron<br />
Tcnt2 = 9 'Timer Startwert, wegen Synchron<br />
Enable Interrupts<br />
End Sub<br />
'********************************************************************************************<br />
<br />
<br />
'********************************************************************************************<br />
Sub Pwm_stop<br />
Tccr0a = 0<br />
Tccr0b = 0<br />
Ocr0a = 0<br />
Ocr0b = 0<br />
Tccr1a = 0<br />
Tccr1b = 0<br />
Ocr1ah = 0<br />
Ocr1al = 0<br />
Ocr1bh = 0<br />
Ocr1bl = 0<br />
Tccr2a = 0<br />
Tccr2b = 0<br />
Ocr2a = 0<br />
Ocr2b = 0<br />
'alles aus<br />
Portd.3 = 0 'A+<br />
Portb.3 = 1 'A-<br />
Portb.2 = 0 'B+<br />
Portb.1 = 1 'B-<br />
Portd.5 = 0 'C+<br />
Portd.6 = 1 'C-<br />
End Sub<br />
'********************************************************************************************<br />
</pre><br />
<br />
==Hauptsteuerung==<br />
<br />
Die Hauptsteuerung erledigt die gesamte Lageregelung. Sie steuert die Motoren und gibt die entsprechenden Meldungen an den Tacho/Datenlogger aus. Sie stellt auch die 5V für den Tacho bereit. Darum die Möglichkeit einen größeren Spannungsregler zu bestücken. 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, also direkt lesbar. Beim Einschalten ist die Gewschwindigkeit auf 6km/h begrenzt. Diese Begrenzung kann jedoch aufgehoben werden. 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.<br />
===Schaltbild===<br />
<gallery><br />
Image:Rutscherle2_5.png|Schaltbild Hauptsteuerung<br />
</gallery><br />
<br />
===Sensoradapter===<br />
<br />
Zur Hauptsteuerung gehört auch der Sensoradapter. (Schaltbild siehe Hauptsteuerung) Dieser stellt die 3,3V für die Sensoren bereit. Im Unterschied zu ähnlichen Projekten besitzt das Rutscherle2 kein Potentiometer für die Lenkung. Zum Lenken werden die gesamten Sensoren gekippt. Darum auch dieser Sensoradapter. Die Sensoren werden mit dem Adapter direkt mit der Achse der Lenkung verbunden. Die ideale Position ist dabei natürlich genau im Schnittpunkt von Lenk- und Motorachse.<br />
<br />
===Software Version 67===<br />
<br />
<pre><br />
$prog &HFF , &HFF , &HD1 , &HFF 'Fusebits für Atmega644<br />
$regfile = "m644def.dat"<br />
$framesize = 64<br />
$swstack = 64<br />
$hwstack = 64<br />
$crystal = 20000000<br />
$baud = 57600<br />
Declare Sub Onbutton1<br />
Declare Sub Logtext(byval Adresse As Word , Text As String )<br />
Declare Sub Akkugrenzen<br />
Declare Sub Unfalldatenschreiber<br />
Declare Sub Betriebsdatenschreiber<br />
Config Portb.0 = Output<br />
Config Portb.1 = Output<br />
Config Portb.2 = Output<br />
Config Portb.3 = Output<br />
Config Portb.4 = Output<br />
Config Portb.6 = Input 'Fusstaster<br />
Config Portc.0 = Input<br />
Config Portc.1 = Input<br />
Config Portc.2 = Input<br />
Config Portc.3 = Input<br />
Config Portc.4 = Input<br />
Config Portc.5 = Input<br />
Config Portc.6 = Input<br />
Config Portc.7 = Input<br />
Config Portd.7 = Output<br />
Config Portd.6 = Output<br />
Config Portd.5 = Output<br />
Config Portd.4 = Output<br />
Config Portd.3 = Output<br />
Config Portd.2 = Input<br />
Led1 Alias Portb.4<br />
Led2 Alias Portb.3<br />
Sensor_aus Alias Portb.2<br />
Sensor_test Alias Portb.1 'Self-Test. 0=Normalbetrieb<br />
Led3 Alias Portd.4<br />
Led4 Alias Portd.5<br />
Led5 Alias Portd.6<br />
Led6 Alias Portd.3<br />
Led7 Alias Portd.7<br />
Button1 Alias Pind.2<br />
Fusstaster Alias Pinb.6<br />
'******************************************************************************************************************************<br />
'******************************************************************************************************************************<br />
'Konstanten für die Geschwindigkeits und Streckenmessung<br />
Const Kom_pro_u = 276 '276*Kommutieren für eine Umdrehung.<br />
Const Radumpfang = 139 'RaduMPFang in Zentimeter<br />
'Maximalwert bis zu dem die Abweichung in y aufaddiert wird<br />
Const Max_mit_acc_nick_s = 1024<br />
Const Min_mit_acc_nick_s = -1024<br />
Const Max_lenk = 128<br />
Const Min_lenk = -128<br />
'Konstanten für die Leistungsbegrenzung, Geschwindigkeitsbegrenzung<br />
'Maximalleistung<br />
Const Maxpwm = 255<br />
Const Minpwm = -255<br />
'PWM ab der automatisch gebremst wird um blos nie an die Grenze zu kommen<br />
Const Spwm = 128<br />
Const Spwmr = -128<br />
'Offsetwerte für die Mittellage<br />
Const Offset_roll = 67700<br />
Const Offset_nick = 65400<br />
Const O_roll_u = 66200<br />
Const O_roll_o = 69200<br />
Const O_nick_u = 63900<br />
Const O_nick_o = 66900<br />
Const O_nick_oo = 67700<br />
Const Vmax = 60 'Vmax Vorwärts in km/h*10<br />
Const Vmaxr = -60 'Vmax Rückwärts in km/h*10<br />
'Konstanten für die Akkus<br />
Const Akkuleer = 3600 '36V, 12V pro Akku -> Akkus leer<br />
Const Akkufastleer = 3750<br />
'Konstanten für die Signalaufbereitoung<br />
Const Gyro_anz = 10000<br />
Const Acc_anz = 50<br />
Const Gyro_faktor = 91<br />
'******************************************************************************************************************************<br />
'******************************************************************************************************************************<br />
'Variablen für die Rückmeldungen von den Motorreglern<br />
Dim U As Integer At $100<br />
Dim I As Integer At $102<br />
Dim K As Integer At $104<br />
Dim Checksumme As Byte At $106<br />
Dim Ende As Byte At $107<br />
Dim Motormeldung(8) As Byte At $100 Overlay<br />
Dim M1 As Byte At $100 Overlay<br />
Dim M2 As Byte At $101 Overlay<br />
Dim M3 As Byte At $102 Overlay<br />
Dim M4 As Byte At $103 Overlay<br />
Dim M5 As Byte At $104 Overlay<br />
Dim M6 As Byte At $105 Overlay<br />
Dim M7 As Byte At $106 Overlay<br />
Dim M8 As Byte At $107 Overlay<br />
'Variablen für die Telegramme an die Motorregler<br />
Dim Checksum_rechts As Byte At $108<br />
Dim Checksum_links As Byte At $109<br />
Dim Richtung_rechts As Byte At $10a<br />
Dim Richtung_links As Byte At $10b<br />
Dim Pwm_rechts As Byte At $10c<br />
Dim Pwm_links As Byte At $10d<br />
Dim Zeiger_meldung As Byte At $10e<br />
Dim Ta As Byte At $10f<br />
Dim U_links As Integer At $111<br />
Dim U_rechts As Integer At $113<br />
Dim I_links As Integer At $115<br />
Dim I_rechts As Integer At $117<br />
Dim K_links As Integer At $119<br />
Dim K_rechts As Integer At $11b<br />
Dim B(5) As Byte At $11d<br />
Dim Kilometer As Word At $122<br />
Dim Kilometermeldung(2) As Byte At $122 Overlay<br />
Dim Akkustand As Integer At $124<br />
Dim Akkumeldung(2) As Byte At $124 Overlay<br />
Dim Kmh As Integer At $126<br />
Dim Kmhmeldung(2) As Byte At $126 Overlay<br />
Dim Meter As Integer At $128<br />
Dim Metermeldung(2) As Byte At $128 Overlay<br />
Dim Di As Single At $12a 'Distanz pro Kommutieren<br />
Dim Kmhfaktor As Single At $12e<br />
Dim Zentimeter As Single At $132<br />
Dim Strecke As Single At $136 'Gefahrene Strecke während 1/100s<br />
Dim Kx As Single At $13a 'Anzahl Kommutierungen für die Streckenberechnung<br />
Dim Kv As Single At $13e 'Anzahl Kommutierungen für die Geschwindigkeitosberechnung<br />
Dim Vbrems As Long At $142 'Bremse bei Überlast oder zu hoher Geschwindigkeit<br />
Dim Lbrems As Long At $146<br />
Dim Brems As Long At $14a<br />
Dim P_faktor As Single At $14e<br />
Dim Pf1 As Byte At $14e Overlay<br />
Dim Pf2 As Byte At $14f Overlay<br />
Dim Pf3 As Byte At $150 Overlay<br />
Dim Pf4 As Byte At $151 Overlay<br />
Dim I_faktor As Single At $152<br />
Dim If1 As Byte At $152 Overlay<br />
Dim If2 As Byte At $153 Overlay<br />
Dim If3 As Byte At $154 Overlay<br />
Dim If4 As Byte At $155 Overlay<br />
Dim D_faktor As Single At $156<br />
Dim Df1 As Byte At $156 Overlay<br />
Dim Df2 As Byte At $157 Overlay<br />
Dim Df3 As Byte At $158 Overlay<br />
Dim Df4 As Byte At $159 Overlay<br />
Dim Gyro_nick As Word At $015a<br />
Dim Gyro_roll As Word At $015c<br />
Dim Gyro_roll_alt As Word At $015e<br />
Dim Gyro_nick_alt As Word At $0160<br />
Dim Acc_nick As Long At $0162<br />
Dim Acc_roll As Long At $0166<br />
Dim Sum_acc_roll As Long At $016a<br />
Dim Sum_acc_nick As Long At $016e<br />
Dim Sum_gyro_roll As Long At $0172<br />
Dim Sum_gyro_nick As Long At $0176<br />
Dim Korr_acc_roll As Long At $017a<br />
Dim Korr_acc_nick As Long At $017e<br />
Dim Maccroll As Long At $0182<br />
Dim Maccroll1 As Byte At $0182 Overlay<br />
Dim Maccroll2 As Byte At $0183 Overlay<br />
Dim Maccroll3 As Byte At $0184 Overlay<br />
Dim Maccroll4 As Byte At $0185 Overlay<br />
Dim Maccnick As Long At $0186<br />
Dim Maccnick1 As Byte At $0186 Overlay<br />
Dim Maccnick2 As Byte At $0187 Overlay<br />
Dim Maccnick3 As Byte At $0188 Overlay<br />
Dim Maccnick4 As Byte At $0189 Overlay<br />
Dim Mit_acc_nick_s As Long At $018a<br />
Dim Mit_gyro_roll As Long At $018e<br />
Dim Mit_gyro_nick As Long At $0192<br />
Dim Sig_gyro_roll As Long At $0196<br />
Dim Sig_gyro_nick As Long At $019a<br />
<br />
Dim Nullroll As Long At $019e<br />
Dim Nullroll1 As Byte At $019e Overlay<br />
Dim Nullroll2 As Byte At $019f Overlay<br />
Dim Nullroll3 As Byte At $01a0 Overlay<br />
Dim Nullroll4 As Byte At $01a1 Overlay<br />
Dim Nullnick As Long At $01a2<br />
Dim Nullnick1 As Byte At $01a2 Overlay<br />
Dim Nullnick2 As Byte At $01a3 Overlay<br />
Dim Nullnick3 As Byte At $01a4 Overlay<br />
Dim Nullnick4 As Byte At $01a5 Overlay<br />
Dim Stellwert As Single At $01a6<br />
<br />
Dim Mrg As Single At $01aa<br />
Dim Mrg1 As Byte At $01aa Overlay<br />
Dim Mrg2 As Byte At $01ab Overlay<br />
Dim Mrg3 As Byte At $01ac Overlay<br />
Dim Mrg4 As Byte At $01ad Overlay<br />
Dim Mra As Single At $01ae<br />
Dim Mra1 As Byte At $01ae Overlay<br />
Dim Mra2 As Byte At $01af Overlay<br />
Dim Mra3 As Byte At $01b0 Overlay<br />
Dim Mra4 As Byte At $01b1 Overlay<br />
<br />
Dim Kksum As Single At $01b2<br />
Dim Kksum1 As Byte At $01b2 Overlay<br />
Dim Kksum2 As Byte At $01b3 Overlay<br />
Dim Kksum3 As Byte At $01b4 Overlay<br />
Dim Kksum4 As Byte At $01b5 Overlay<br />
Dim Sw As Single At $01b6<br />
Dim Sw1 As Byte At $01b6 Overlay<br />
Dim Sw2 As Byte At $01b7 Overlay<br />
Dim Sw3 As Byte At $01b8 Overlay<br />
Dim Sw4 As Byte At $01b9 Overlay<br />
Dim Gyronick As Long At $01ba<br />
Dim Gyronick1 As Byte At $01ba Overlay<br />
Dim Gyronick2 As Byte At $01bb Overlay<br />
Dim Gyronick3 As Byte At $01bc Overlay<br />
Dim Gyronick4 As Byte At $01bd Overlay<br />
<br />
Dim Mp_faktor As Single At $01be<br />
Dim Mpf1 As Byte At $01be Overlay<br />
Dim Mpf2 As Byte At $01bf Overlay<br />
Dim Mpf3 As Byte At $01c0 Overlay<br />
Dim Mpf4 As Byte At $01c1 Overlay<br />
Dim Mv_faktor As Single At $01c2<br />
Dim Mvf1 As Byte At $01c2 Overlay<br />
Dim Mvf2 As Byte At $01c3 Overlay<br />
Dim Mvf3 As Byte At $01c4 Overlay<br />
Dim Mvf4 As Byte At $01c5 Overlay<br />
Dim Mpl_faktor As Single At $01c6<br />
Dim Mplf1 As Byte At $01c6 Overlay<br />
Dim Mplf2 As Byte At $01c7 Overlay<br />
Dim Mplf3 As Byte At $01c8 Overlay<br />
Dim Mplf4 As Byte At $01c9 Overlay<br />
Dim Mvl_faktor As Single At $01ca<br />
Dim Mvlf1 As Byte At $01ca Overlay<br />
Dim Mvlf2 As Byte At $01cb Overlay<br />
Dim Mvlf3 As Byte At $01cc Overlay<br />
Dim Mvlf4 As Byte At $01cd Overlay<br />
<br />
Dim P_tacho As Single At $01ce<br />
Dim I_tacho As Single At $01d2<br />
Dim D_tacho As Single At $01d6<br />
Dim Mp_tacho As Single At $01da<br />
Dim Mv_tacho As Single At $01de<br />
Dim Mpl_tacho As Single At $01e2<br />
Dim Mvl_tacho As Single At $01e6<br />
<br />
Dim Tdummy As Integer At $01ea<br />
Dim Tachomeldung(30) As Byte At $01ce Overlay<br />
Dim T1 As Byte At $01ce Overlay<br />
Dim T2 As Byte At $01cf Overlay<br />
Dim T3 As Byte At $01d0 Overlay<br />
Dim T4 As Byte At $01d1 Overlay<br />
<br />
Dim T5 As Byte At $01d2 Overlay<br />
Dim T6 As Byte At $01d3 Overlay<br />
Dim T7 As Byte At $01d4 Overlay<br />
Dim T8 As Byte At $01d5 Overlay<br />
<br />
Dim T9 As Byte At $01d6 Overlay<br />
Dim T10 As Byte At $01d7 Overlay<br />
Dim T11 As Byte At $01d8 Overlay<br />
Dim T12 As Byte At $01d9 Overlay<br />
<br />
Dim T13 As Byte At $01da Overlay<br />
Dim T14 As Byte At $01db Overlay<br />
Dim T15 As Byte At $01dc Overlay<br />
Dim T16 As Byte At $01dd Overlay<br />
<br />
Dim T17 As Byte At $01de Overlay<br />
Dim T18 As Byte At $01df Overlay<br />
Dim T19 As Byte At $01e0 Overlay<br />
Dim T20 As Byte At $01e1 Overlay<br />
<br />
Dim T21 As Byte At $01e2 Overlay<br />
Dim T22 As Byte At $01e3 Overlay<br />
Dim T23 As Byte At $01e4 Overlay<br />
Dim T24 As Byte At $01e5 Overlay<br />
<br />
Dim T25 As Byte At $01e6 Overlay<br />
Dim T26 As Byte At $01e7 Overlay<br />
Dim T27 As Byte At $01e8 Overlay<br />
Dim T28 As Byte At $01e9 Overlay<br />
<br />
Dim T29 As Byte At $01ea Overlay<br />
Dim T30 As Byte At $01eb Overlay<br />
<br />
<br />
Dim Gyro_gier As Word<br />
Dim Gyro_gier_alt As Word<br />
Dim Sum_gyro_gier As Long<br />
Dim Mit_gyro_gier As Long<br />
Dim Sig_gyro_gier As Long<br />
<br />
Dim Werteneu As Byte<br />
Dim Mit_acc_roll As Long<br />
Dim Mit_acc_nick As Long<br />
Dim Null_roll As Long<br />
Dim Null_nick As Long<br />
Dim Mit_regelzeit_ges As Single<br />
<br />
Dim Lagefehler As Long<br />
Dim Regelzeit As Word 'Die Zeit in 1/100s die gebraucht wird bis die Nullage erreicht ist<br />
Dim Regelzeitmax As Word<br />
Dim Mit_acc_roll_max As Long<br />
Dim Mit_acc_nick_max As Long<br />
Dim Mit_acc_roll_min As Long<br />
Dim Mit_acc_nick_min As Long<br />
<br />
<br />
Dim Pwm_gesamt As Single<br />
Dim Pwm_rechts_max As Byte<br />
Dim Pwm_links_max As Byte<br />
Dim Intcount As Byte<br />
Dim K_diff As Single<br />
Dim K_sum As Single<br />
Dim K_diff_min As Single<br />
Dim K_diff_max As Single<br />
Dim Pwm_lenk_rechts As Integer<br />
Dim Pwm_lenk_links As Integer<br />
<br />
Dim Lenkvorgabe As Single<br />
Dim Mp_anpassung As Single<br />
Dim Mv_anpassung As Single<br />
Dim Mpl_anpassung As Single<br />
Dim Mvl_anpassung As Single<br />
Dim K_sum_anpassung As Single<br />
<br />
<br />
Dim Wdummy1 As Word<br />
Dim Ldummyi As Long<br />
Dim Ldummy1 As Long<br />
Dim Ldummy2 As Long<br />
Dim Bdummy1 As Byte<br />
Dim Idummy1 As Integer<br />
Dim Sdummy1 As Single<br />
<br />
<br />
Dim Antriebaus As Byte<br />
Dim Notaus As Byte<br />
Dim Sensor_ok As Byte 'Zeigt an ob die Mittelwerte der Gyros stabil stehen.<br />
Dim Sensor_ok_count As Byte<br />
Dim Ltest As Byte<br />
Dim Ugemessen As Long 'Batteriespannung in V*100<br />
Dim Igemessen As Long 'Gesamter Motorstrom in mA<br />
<br />
Dim Imin As Long 'Kleinster gemessener Motorstrom (größte Rückspeisung)<br />
Dim Imax As Long 'größter gemessener Motorstrom<br />
Dim Summe_as_entladen As Long<br />
Dim Summe_mah_entladen As Long<br />
Dim Summe_as_laden As Long<br />
Dim Summe_mah_laden As Long<br />
Dim Akkukap As Long<br />
Dim Akku1 As Long<br />
Dim Akku2 As Long<br />
Dim Akku3 As Long<br />
Dim Akku4 As Long<br />
Dim Akku5 As Long<br />
Dim Erzeugt As Long<br />
Dim Verbraucht As Long<br />
'Single Variablen um die Prozente rechnen zu können<br />
Dim Akkuinhalt As Single<br />
Dim Akkuverbrauch As Single<br />
Dim Akkuprozent As Single<br />
<br />
Dim Adresse As Word<br />
Dim Bzeit As Long<br />
Dim Bstate As Byte<br />
Dim Frei As Byte<br />
Dim Timeout As Byte<br />
Dim S_err As Byte<br />
Dim Seriell_err_l As Word<br />
Dim Seriell_err_r As Word<br />
Dim Tamax As Byte<br />
Dim Fusscount As Word<br />
Dim Blinkcount As Byte<br />
Dim Lenkerstellung As Single<br />
Dim Lenkstellwert As Single<br />
Dim Lenkfehler As Single<br />
Dim N As Integer<br />
Dim Utext As String * 32 'Texte für den Unfalldatenschreiber (als Text im eeprom)<br />
Dim Ugrund As String * 32<br />
Dim Text As String * 16<br />
Dim Min_v As Integer<br />
Dim Max_v As Integer<br />
<br />
<br />
Dim Tachocount As Byte<br />
Led3 = 1<br />
Led4 = 1<br />
Led5 = 1<br />
Led6 = 1<br />
Led7 = 1<br />
Wait 5 '5 Sekunden Warten<br />
Antriebaus = 1<br />
'Ein paar feste Werte vorab berechnen:<br />
Di = Radumpfang / Kom_pro_u<br />
Kmhfaktor = Di * 9 'Eigentlich 3.6 aber bei der Mittelwertbildung entsteht der 4-Fache Wert. Darum 9, und es ergibt sich automateisch V in 0.1km/h<br />
'Unbenutzte Pins auf Masse legen<br />
Portb.7 = 0<br />
Portb.5 = 0<br />
'Input-Pins hochziehen<br />
Portc.0 = 1<br />
Portc.1 = 1<br />
Portc.2 = 1<br />
Portc.3 = 1<br />
Portc.4 = 1<br />
Portc.5 = 1<br />
Portc.6 = 1<br />
<br />
'Sensorboard schalten:<br />
Sensor_aus = 0<br />
Sensor_test = 0<br />
'Hochziehwiderstände der Knöpfe einschalten<br />
Button1 = 1<br />
Fusstaster = 1<br />
<br />
Config Adc = Single , Prescaler = Auto , Reference = Internal_2.56<br />
Start Adc<br />
'Wartezeit bis die Motorregler soweit sind<br />
Readeeprom Max_v , $2f0<br />
Readeeprom Min_v , $2f2<br />
Readeeprom Summe_as_entladen , $300 'Entnommene Wh und Ws aus EEPROM lesen<br />
Led3 = 0<br />
Waitms 150<br />
Readeeprom Summe_mah_entladen , $310<br />
Led4 = 0<br />
Waitms 150<br />
Readeeprom Summe_as_laden , $320<br />
Led5 = 0<br />
Waitms 150<br />
Readeeprom Summe_mah_laden , $330<br />
Led6 = 0<br />
Waitms 150<br />
Readeeprom Akkukap , $340<br />
Led7 = 0<br />
Waitms 150<br />
Readeeprom Kilometer , $350<br />
Readeeprom Meter , $360<br />
Readeeprom Zentimeter , $370<br />
<br />
'<Faktoren für den PID-Regler einlesen><br />
Readeeprom P_faktor , $380<br />
Readeeprom I_faktor , $384<br />
Readeeprom D_faktor , $388<br />
Readeeprom Mp_faktor , $38c<br />
Readeeprom Mv_faktor , $390<br />
Readeeprom Mpl_faktor , $394<br />
Readeeprom Mvl_faktor , $398<br />
<br />
If P_faktor < 0 Or P_faktor > 1 Then P_faktor = 0.0033 'Halbwegs sinnvolle Werte vorbelegen<br />
If I_faktor < 0 Or I_faktor > 1 Then I_faktor = 0.00006<br />
If D_faktor < 0 Or D_faktor > 1 Then D_faktor = 0.08<br />
If Mp_faktor < 0 Or Mp_faktor > 1 Then Mp_faktor = 0.006<br />
<br />
If Mv_faktor < 0 Or Mv_faktor > 1 Then Mv_faktor = 0<br />
If Mpl_faktor < 0 Or Mpl_faktor > 1 Then Mpl_faktor = 0<br />
If Mvl_faktor < 0 Or Mvl_faktor > 1 Then Mvl_faktor = 0<br />
<br />
'</Faktoren für den PID-Regler einlesen><br />
If Kilometer = $ffff Then 'Kommt bei frischem EEPROM vor<br />
Zentimeter = 0<br />
Meter = 0<br />
Kilometer = 0<br />
Min_v = 0<br />
Max_v = 0<br />
End If<br />
'Bei Fehlerhaften Werten aus dem EEPROM einfach 100mAh als Vorgabe<br />
If Akkukap <= 0 Then Akkukap = 100<br />
If Akkukap > 32000 Then Akkukap = 100<br />
Akkugrenzen<br />
Antriebaus = 1 'Beim Start ist immer alles aus<br />
Notaus = 0<br />
Readeeprom Max_v , $2f0<br />
Readeeprom Min_v , $2f4<br />
Config Watchdog = 128<br />
'<Sicherheitstest 1><br />
Start Watchdog<br />
If Button1 = 0 Then Wait 10<br />
If Antriebaus = 0 Then Wait 10<br />
If P_faktor > 1 Then Wait 10<br />
If I_faktor > 1 Then Wait 10<br />
If D_faktor > 1 Then Wait 10<br />
If P_faktor < 0 Then Wait 10<br />
If I_faktor < 0 Then Wait 10<br />
If D_faktor < 0 Then Wait 10<br />
If Fusstaster = 0 Then Wait 10<br />
Stop Watchdog<br />
'</Sicherheitstest 1><br />
'Maximalwerte für Datenschreiber/Notauserkennung auf 0 setzen<br />
Regelzeit = 0<br />
Regelzeitmax = 0<br />
Mit_acc_nick_max = 0<br />
Mit_acc_roll_max = 0<br />
Pwm_rechts_max = 0<br />
Pwm_links_max = 0<br />
K_diff_min = 0<br />
K_diff_max = 0<br />
Richtung_links = 2 'Leerlauf<br />
Richtung_rechts = 2 'Leerlauf<br />
Pwm_links = 0<br />
Pwm_rechts = 0<br />
Pwm_gesamt = 0<br />
Mit_acc_nick_s = 0<br />
Lenkerstellung = 0<br />
<br />
K_rechts = 0<br />
K_links = 0<br />
Seriell_err_l = 0<br />
Seriell_err_r = 0<br />
Ugrund = "----------------" 'Einfach mal vorbelegen um zu sehen obs auch einen Notaus ohne Grund gibt.<br />
On Timer0 Regel_interrupt<br />
Config Timer0 = Timer , Prescale = 1024<br />
Enable Timer0<br />
Enable Interrupts<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
<br />
'<Sicherheitstest 2><br />
Start Watchdog<br />
If Button1 = 0 Then Wait 10<br />
If Antriebaus = 0 Then Wait 10<br />
If P_faktor > 1 Then Wait 10<br />
If I_faktor > 1 Then Wait 10<br />
If D_faktor > 1 Then Wait 10<br />
If P_faktor < 0 Then Wait 10<br />
If I_faktor < 0 Then Wait 10<br />
If D_faktor < 0 Then Wait 10<br />
If Ugemessen < 1000 Then Wait 10<br />
If Ugemessen > 4700 Then Wait 10<br />
If Fusstaster = 0 Then Wait 10<br />
Stop Watchdog<br />
'</Sicherheitstest 2><br />
If Ugemessen < 2400 Then 'Sensoren ausschalten wenn am Ladegerät oder zu Testzwecken<br />
Sensor_aus = 1<br />
Else<br />
Sensor_aus = 0<br />
End If<br />
<br />
<br />
While Ugemessen < 2400 'Unterspannung oder am Ladegerät!<br />
Led3 = 1<br />
Led4 = 1<br />
Led5 = 1<br />
Led6 = 0<br />
Led7 = 1<br />
Wend<br />
<br />
'Prüfung ob Akku gerade geladen:<br />
If Ugemessen > 3950 Then 'Der Akku wurde gerade geladen<br />
Disable Interrupts 'Interruts abschalten damit die folgenden Zeilen nicht gerade jetzt vom Interrupt unterbrochen werden.<br />
Waitms 50<br />
Summe_as_entladen = 0<br />
Summe_mah_entladen = 0<br />
Summe_as_laden = 0<br />
Summe_mah_laden = 0<br />
Enable Interrupts<br />
End If<br />
Summen_vorbelegen:<br />
Acc_roll = Getadc(5) 'Roll<br />
Acc_nick = Getadc(7) 'Nick<br />
Gyro_roll = Getadc(2) 'Roll<br />
Gyro_nick = Getadc(4) 'Nick<br />
Gyro_gier = Getadc(3)<br />
<br />
Acc_roll = Acc_roll * 100<br />
Acc_nick = Acc_nick * 100<br />
<br />
Sum_gyro_roll = Gyro_roll * Gyro_anz<br />
Sum_gyro_nick = Gyro_nick * Gyro_anz<br />
Sum_gyro_gier = Gyro_gier * Gyro_anz<br />
<br />
Gyro_roll_alt = Gyro_roll<br />
Gyro_nick_alt = Gyro_nick<br />
Gyro_gier_alt = Gyro_gier<br />
<br />
Mit_gyro_roll = Gyro_roll<br />
Mit_gyro_nick = Gyro_nick<br />
Mit_gyro_gier = Gyro_gier<br />
<br />
Sum_acc_roll = Acc_roll * Acc_anz<br />
Sum_acc_nick = Acc_nick * Acc_anz<br />
<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
Waitms 100<br />
Toggle Led3<br />
Toggle Led4<br />
Toggle Led5<br />
Toggle Led6<br />
Toggle Led7<br />
<br />
If Sig_gyro_nick < -3 Then Goto Summen_vorbelegen<br />
If Sig_gyro_nick > 3 Then Goto Summen_vorbelegen<br />
If Sig_gyro_roll < -3 Then Goto Summen_vorbelegen<br />
If Sig_gyro_roll > 3 Then Goto Summen_vorbelegen<br />
If Sig_gyro_gier < -3 Then Goto Summen_vorbelegen<br />
If Sig_gyro_gier > 3 Then Goto Summen_vorbelegen<br />
<br />
'<Sicherheitstest 3><br />
Start Watchdog<br />
If Button1 = 0 Then Wait 10<br />
If Antriebaus = 0 Then Wait 10<br />
If P_faktor > 1 Then Wait 10<br />
If I_faktor > 1 Then Wait 10<br />
If D_faktor > 1 Then Wait 10<br />
If P_faktor < 0 Then Wait 10<br />
If I_faktor < 0 Then Wait 10<br />
If D_faktor < 0 Then Wait 10<br />
If Ugemessen < 1000 Then Wait 10<br />
If Ugemessen > 4700 Then Wait 10<br />
If Fusstaster = 0 Then Wait 10<br />
Stop Watchdog<br />
'</Sicherheitstest 3><br />
'********************************************************************************************************************************************************<br />
Do<br />
'<Fusstaster abfragen><br />
If Fusscount = 0 Then<br />
If Antriebaus = 0 Then<br />
Antriebaus = 1<br />
Waitms 100 'Damit der Regelinterrupt auch was davon mitbekommt<br />
Disable Interrupts<br />
Betriebsdatenschreiber<br />
Enable Interrupts<br />
End If<br />
End If<br />
'</Fusstaster abfragen><br />
<br />
'<Sicherheitstest Sensoren><br />
If Antriebaus = 1 Then<br />
<br />
If Intcount <> Ltest Then<br />
Ltest = Intcount<br />
Sensor_ok = 0<br />
If Sensor_ok_count > 0 Then Decr Sensor_ok_count<br />
'1. Es darf keine nennenswerte Drehbewegung erkannt werden!<br />
<br />
If Sig_gyro_nick < -3 Then Sensor_ok_count = 50<br />
If Sig_gyro_nick > 3 Then Sensor_ok_count = 50<br />
If Sig_gyro_roll < -3 Then Sensor_ok_count = 50<br />
If Sig_gyro_roll > 3 Then Sensor_ok_count = 50<br />
If Sig_gyro_gier < -15 Then Sensor_ok_count = 50 'Nach mehrfachen Drehungen könnte der Mittelwert etwas verschoben sein. Darum hier 12<br />
If Sig_gyro_gier > 15 Then Sensor_ok_count = 50<br />
<br />
'2. Die Werte dürfen nicht verrauscht sein<br />
Ldummy2 = Mit_acc_nick + 500<br />
If Acc_nick > Ldummy2 Then Sensor_ok_count = 50<br />
Ldummy2 = Mit_acc_nick - 500<br />
If Acc_nick < Ldummy2 Then Sensor_ok_count = 50<br />
Ldummy2 = Mit_acc_roll + 500<br />
If Acc_roll > Ldummy2 Then Sensor_ok_count = 50<br />
Ldummy2 = Mit_acc_roll - 500<br />
If Acc_roll < Ldummy2 Then Sensor_ok_count = 50<br />
<br />
'3. Die Werte müssen ungefähr in einer legalen Nullage sein.<br />
If Null_roll < O_roll_u Then Sensor_ok_count = 50<br />
If Null_roll > O_roll_o Then Sensor_ok_count = 50<br />
If Null_nick < O_nick_u Then Sensor_ok_count = 50<br />
If Null_nick > O_nick_o Then Sensor_ok_count = 50<br />
<br />
If Sensor_ok_count = 0 Then Sensor_ok = 1 'Bedingungen während 50 Messungen (0.5s) eingehalten<br />
<br />
End If<br />
Else<br />
Sensor_ok = 0<br />
End If<br />
<br />
'</Sicherheitstest Sensoren><br />
<br />
'<Batterieanzeige><br />
If Ugemessen > Akkufastleer Then 'alles unter 36V Leerlaufspannung ist LEER<br />
If Verbraucht > Akkukap Then<br />
Akkukap = Verbraucht + 1 'Einfach mal annehmen daß noch mehr als angezeigt im Akku ist<br />
Akkugrenzen<br />
End If<br />
End If<br />
'Mit Blinken wenn Gyros nicht bereit<br />
If Antriebaus = 1 Then<br />
If Ugemessen > Akkuleer Then 'alles unter 36V Leerlaufspannung ist LEER<br />
If Verbraucht > Akkukap Then<br />
Akkukap = Verbraucht + 20 'Einfach mal annehmen daß noch mehr als angezeigt im Akku ist<br />
Akkugrenzen<br />
End If<br />
End If<br />
If Sensor_ok = 1 Then<br />
If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1<br />
If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1<br />
If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1<br />
If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1<br />
If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1<br />
Else<br />
If Frei = 1 Then 'Schneller Blinken wenn Frei<br />
Blinkcount = Intcount<br />
If Blinkcount > 50 Then Blinkcount = Blinkcount - 50<br />
Else<br />
Blinkcount = Intcount / 2<br />
End If<br />
<br />
If Blinkcount > 40 Then<br />
If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1<br />
If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1<br />
If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1<br />
If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1<br />
If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1<br />
Else<br />
Led7 = 1<br />
Led6 = 1<br />
Led5 = 1<br />
Led4 = 1<br />
Led3 = 1<br />
End If<br />
<br />
End If<br />
Else<br />
If Verbraucht < Akku1 Then Led7 = 0 Else Led7 = 1<br />
If Verbraucht < Akku2 Then Led6 = 0 Else Led6 = 1<br />
If Verbraucht < Akku3 Then Led5 = 0 Else Led5 = 1<br />
If Verbraucht < Akku4 Then Led4 = 0 Else Led4 = 1<br />
If Verbraucht < Akku5 Then Led3 = 0 Else Led3 = 1<br />
<br />
End If<br />
'</Batterieanzeige><br />
'<Maximalwerte für Betriebsdatenschreiber><br />
If Igemessen < Imin Then Imin = Igemessen 'Nur zur Information<br />
If Igemessen > Imax Then Imax = Igemessen 'Nur zur Information<br />
If Regelzeit > Regelzeitmax Then Regelzeitmax = Regelzeit<br />
If Mit_acc_nick > Mit_acc_nick_max Then Mit_acc_nick_max = Mit_acc_nick<br />
If Mit_acc_roll > Mit_acc_roll_max Then Mit_acc_roll_max = Mit_acc_roll<br />
If Mit_acc_nick < Mit_acc_nick_min Then Mit_acc_nick_min = Mit_acc_nick<br />
If Mit_acc_roll < Mit_acc_roll_min Then Mit_acc_roll_min = Mit_acc_roll<br />
If Pwm_links > Pwm_links_max Then Pwm_links_max = Pwm_links<br />
If Pwm_rechts > Pwm_rechts_max Then Pwm_rechts_max = Pwm_rechts<br />
If K_diff > K_diff_max Then K_diff_max = K_diff<br />
If K_diff < K_diff_min Then K_diff_min = K_diff<br />
If Ta > Tamax Then Tamax = Ta<br />
'</Maximalwerte für Betriebsdatenschreiber><br />
<br />
If Intcount > 80 Then Led1 = 1 Else Led1 = 0 'Sekundenblinken<br />
'Daran lässt sich leicht erkennen ob<br />
'noch alles normal läuft.<br />
Debounce Button1 , 0 , Onbutton1 , Sub<br />
<br />
<br />
Loop<br />
End<br />
'**************************************************************************************************<br />
'Ab hier kommen die Subroutinen und die Interrupts<br />
'**************************************************************************************************<br />
Sub Akkugrenzen<br />
'Grenzwerte für die Akku-LEDs berechnen<br />
Ldummy1 = Akkukap / 5<br />
Akku1 = Ldummy1<br />
Akku2 = 2 * Ldummy1<br />
Akku3 = 3 * Ldummy1<br />
Akku4 = 4 * Ldummy1<br />
Akku5 = 5 * Ldummy1<br />
End Sub<br />
'**************************************************************************************************<br />
Sub Unfalldatenschreiber<br />
Waitms 10<br />
Utext = Str(regelzeit)<br />
Utext = "Rz=" + Utext<br />
Logtext 0 , Utext<br />
Utext = Str(mit_acc_nick_max)<br />
Utext = "N max=" + Utext<br />
Logtext $10 , Utext<br />
Utext = Str(mit_acc_nick)<br />
Utext = "N=" + Utext<br />
Logtext $20 , Utext<br />
Utext = Str(mit_acc_nick_min)<br />
Utext = "N min=" + Utext<br />
Logtext $30 , Utext<br />
Utext = Str(mit_acc_roll_max)<br />
Utext = "R max=" + Utext<br />
Logtext $40 , Utext<br />
Utext = Str(mit_acc_roll)<br />
Utext = "R=" + Utext<br />
Logtext $50 , Utext<br />
Utext = Str(mit_acc_roll_min)<br />
Utext = "R min=" + Utext<br />
Logtext $60 , Utext<br />
Utext = Str(pwm_rechts)<br />
Utext = "PWM r=" + Utext<br />
Logtext $70 , Utext<br />
Utext = Str(pwm_links)<br />
Utext = "PWM l=" + Utext<br />
Logtext $80 , Utext<br />
Utext = Str(u_rechts)<br />
Utext = "U r=" + Utext<br />
Logtext $90 , Utext<br />
Utext = Str(u_links)<br />
Utext = "U l=" + Utext<br />
Logtext $a0 , Utext<br />
Utext = Str(ta)<br />
Utext = "Ta=" + Utext<br />
Logtext $b0 , Utext<br />
Utext = Str(seriell_err_l)<br />
Utext = Utext + "|"<br />
Utext = Utext + Str(seriell_err_r)<br />
Utext = "S =" + Utext<br />
Logtext $c0 , Utext<br />
Utext = Ugrund<br />
Logtext $d0 , Utext<br />
End Sub<br />
<br />
'**************************************************************************************************<br />
Sub Betriebsdatenschreiber<br />
'Ob die Wartezeiten beim EEprom schreiben nötig sind ist nicht sicher.<br />
'Mit den Wartezeiten treten aber keine Fehler bei den Werten mehr auf.<br />
'Möglich, daß dies auch durch eine andere Änderung bewirkt wurde.<br />
Writeeeprom Max_v , $2f0<br />
Writeeeprom Min_v , $2f2<br />
Zentimeter = Int(zentimeter) 'Die Millimeter sollen nicht geschrieben werden<br />
Writeeeprom Summe_as_entladen , $300<br />
Writeeeprom Summe_mah_entladen , $310<br />
Writeeeprom Summe_as_laden , $320<br />
Writeeeprom Summe_mah_laden , $330<br />
Writeeeprom Akkukap , $340<br />
Writeeeprom Kilometer , $350<br />
Writeeeprom Meter , $360<br />
Writeeeprom Zentimeter , $370<br />
If Werteneu = 1 Then 'Nur wenn das Einstellklavier gesteckt ist.<br />
Writeeeprom P_faktor , $380<br />
Writeeeprom I_faktor , $384<br />
Writeeeprom D_faktor , $388<br />
Writeeeprom Mp_faktor , $38c<br />
Writeeeprom Mv_faktor , $390<br />
Writeeeprom Mpl_faktor , $394<br />
Writeeeprom Mvl_faktor , $398<br />
Werteneu = 0<br />
End If<br />
Utext = Str(pwm_rechts_max)<br />
Utext = "PWM r max=" + Utext<br />
Logtext $e0 , Utext<br />
Utext = Str(pwm_links_max)<br />
Utext = "PWM l max=" + Utext<br />
Logtext $f0 , Utext<br />
Utext = Str(ugemessen)<br />
Utext = "U=" + Utext<br />
Logtext $100 , Utext<br />
Utext = Str(imin)<br />
Utext = "Imin=" + Utext<br />
Logtext $110 , Utext<br />
Utext = Str(imax)<br />
Utext = "Imax=" + Utext<br />
Logtext $120 , Utext<br />
Utext = Str(summe_mah_entladen)<br />
Utext = "-mAh" + Utext<br />
Logtext $130 , Utext<br />
Utext = Str(summe_mah_laden)<br />
Utext = "+mAh=" + Utext<br />
Logtext $140 , Utext<br />
Utext = Str(verbraucht)<br />
Utext = " =" + Utext<br />
Logtext $150 , Utext<br />
Utext = Str(akkukap)<br />
Utext = "Kap=" + Utext<br />
Logtext $160 , Utext<br />
Utext = Str(kilometer)<br />
Utext = "Km=" + Utext<br />
Logtext $170 , Utext<br />
Utext = Str(meter)<br />
Utext = "M=" + Utext<br />
Logtext $180 , Utext<br />
Utext = Str(zentimeter)<br />
Utext = "cm=" + Utext<br />
Logtext $190 , Utext<br />
Utext = Str(regelzeitmax)<br />
Utext = "Rz Max=" + Utext<br />
Logtext $1a0 , Utext<br />
Utext = Str(null_roll)<br />
Utext = "Null_R=" + Utext<br />
Logtext $1b0 , Utext<br />
Utext = Str(null_nick)<br />
Utext = "null_N=" + Utext<br />
Logtext $1c0 , Utext<br />
Utext = Str(p_faktor)<br />
Utext = "P=" + Utext<br />
Logtext $1d0 , Utext<br />
Utext = Str(i_faktor)<br />
Utext = "I=" + Utext<br />
Logtext $1e0 , Utext<br />
Utext = Str(d_faktor)<br />
Utext = "D=" + Utext<br />
Logtext $1f0 , Utext<br />
Utext = Str(mp_faktor)<br />
Utext = "M=" + Utext<br />
Logtext $200 , Utext<br />
Utext = Str(k_diff_min)<br />
Utext = "K min=" + Utext<br />
Logtext $210 , Utext<br />
Utext = Str(k_diff_max)<br />
Utext = "K max=" + Utext<br />
Logtext $220 , Utext<br />
Utext = Str(seriell_err_l)<br />
Utext = "S l=" + Utext<br />
Logtext $230 , Utext<br />
Utext = Str(seriell_err_r)<br />
Utext = "S r=" + Utext<br />
Logtext $240 , Utext<br />
Utext = Str(tamax)<br />
Utext = "Ta_Max=" + Utext<br />
Logtext $250 , Utext<br />
Utext = Str(max_v)<br />
Utext = "V_Max=" + Utext<br />
Logtext $260 , Utext<br />
Utext = Str(min_v)<br />
Utext = "V_Min=" + Utext<br />
Logtext $270 , Utext<br />
<br />
End Sub<br />
'**************************************************************************************************<br />
Sub Onbutton1<br />
If Antriebaus = 1 Then<br />
If Ugemessen > Akkuleer Then 'alles unter 36V Leerlaufspannung ist LEER<br />
If Sensor_ok = 1 Then 'Prüfen ob Gyros noch driften<br />
Disable Interrupts 'Interupts abschalten damit Fusscount nicht gerade jetzt decrementiert wird<br />
Regelzeit = 0<br />
Regelzeitmax = 0<br />
Mit_acc_nick_max = 0<br />
Mit_acc_roll_max = 0<br />
Mit_acc_nick_min = 0<br />
Mit_acc_roll_min = 0<br />
Pwm_rechts_max = 0<br />
Pwm_links_max = 0<br />
Seriell_err_r = 0<br />
Seriell_err_l = 0<br />
K_diff_min = 0<br />
K_diff_max = 0<br />
Antriebaus = 0<br />
Fusscount = 50 '0.5 Sekunden zeit zum Aufsteigen<br />
Enable Interrupts<br />
Else<br />
If Null_nick > O_nick_o And Null_nick < O_nick_oo Then<br />
If Bzeit = 500 Then<br />
Bstate = 1<br />
Bzeit = 0<br />
Else<br />
If Bstate = 1 Then<br />
If Bzeit < 50 Then<br />
Disable Interrupts<br />
Utext = " "<br />
Logtext $00 , Utext<br />
Logtext $10 , Utext<br />
Logtext $20 , Utext<br />
Logtext $30 , Utext<br />
Logtext $40 , Utext<br />
Logtext $50 , Utext<br />
Logtext $60 , Utext<br />
Logtext $70 , Utext<br />
Logtext $80 , Utext<br />
Logtext $90 , Utext<br />
Logtext $a0 , Utext<br />
Logtext $b0 , Utext<br />
Logtext $c0 , Utext<br />
Logtext $d0 , Utext<br />
Logtext $e0 , Utext<br />
Logtext $f0 , Utext<br />
Logtext $100 , Utext<br />
Logtext $110 , Utext<br />
Logtext $120 , Utext<br />
Logtext $130 , Utext<br />
Logtext $140 , Utext<br />
Logtext $150 , Utext<br />
Logtext $160 , Utext<br />
Logtext $170 , Utext<br />
Logtext $180 , Utext<br />
Logtext $190 , Utext<br />
Logtext $1a0 , Utext<br />
Logtext $1b0 , Utext<br />
Logtext $1c0 , Utext<br />
Logtext $1d0 , Utext<br />
Logtext $1e0 , Utext<br />
Logtext $1f0 , Utext<br />
Logtext $200 , Utext<br />
Logtext $210 , Utext<br />
Logtext $220 , Utext<br />
Logtext $230 , Utext<br />
Logtext $240 , Utext<br />
Logtext $250 , Utext<br />
Logtext $260 , Utext<br />
Summe_as_entladen = 0<br />
Summe_mah_entladen = 0<br />
Summe_as_laden = 0<br />
Summe_mah_laden = 0<br />
Writeeeprom Summe_as_entladen , $300<br />
Writeeeprom Summe_mah_entladen , $310<br />
Writeeeprom Summe_as_laden , $320<br />
Writeeeprom Summe_mah_laden , $330<br />
Frei = 0<br />
For Bzeit = 1 To 10<br />
Led3 = 1<br />
Led4 = 1<br />
Led5 = 1<br />
Led6 = 1<br />
Led7 = 1<br />
Waitms 100<br />
Led3 = 0<br />
Led4 = 0<br />
Led5 = 0<br />
Led6 = 0<br />
Led7 = 0<br />
Waitms 100<br />
Next<br />
Bzeit = 500<br />
Enable Interrupts<br />
Waitms 100<br />
<br />
End If<br />
If Bzeit > 250 And Bzeit < 350 Then<br />
Frei = 1<br />
Bzeit = 500<br />
Else<br />
Frei = 0<br />
Bzeit = 500<br />
<br />
End If<br />
End If<br />
End If<br />
Else<br />
Frei = 0<br />
Bzeit = 500<br />
End If<br />
End If<br />
Else<br />
If Verbraucht < Akkukap Then 'Akku ist laut Spannung leer!<br />
Akkukap = Verbraucht * 0.95 'Einfach mal annehmen daß zuviel entnommen wurde<br />
Akkugrenzen<br />
End If<br />
Disable Interrupts<br />
Betriebsdatenschreiber<br />
Enable Interrupts<br />
End If<br />
Else<br />
Antriebaus = 1<br />
Waitms 100<br />
Frei = 0<br />
Disable Interrupts<br />
Betriebsdatenschreiber<br />
Enable Interrupts<br />
End If<br />
End Sub<br />
'**************************************************************************************************<br />
Sub Logtext(adresse , Text)<br />
If Len(text) > 16 Then Text = Mid(text , 1 , 16)<br />
While Len(text) < 16<br />
Text = Text + " "<br />
Wend<br />
Writeeeprom Text , Adresse<br />
<br />
End Sub<br />
'**************************************************************************************************<br />
<br />
Regel_interrupt:<br />
'**************************************************************************************************<br />
'Eigentlich ist das kein Typischer Interrupt. Der Interrupt wird hier nur verwendet um der<br />
'Regelung einen 100Hz Takt zu geben. Normalerweise sollte kein Interrupt so lange sein.<br />
'Dadurch werden andere Interrupts für diese Dauer blockiert.<br />
'**************************************************************************************************<br />
Timer0 = 61 'Sollte ca. 100Hz ergeben<br />
Led2 = 1<br />
If Fusscount > 0 Then Decr Fusscount<br />
If Fusstaster = 0 Then Fusscount = 25 '0.25 Sekunden ohne Fusstaster<br />
Bdummy1 = Udr<br />
Gyro_gier = Getadc(3) 'Gier<br />
Acc_roll = Getadc(5) 'Roll<br />
Acc_nick = Getadc(7) 'Nick<br />
Gyro_roll = Getadc(2) 'Roll<br />
Gyro_nick = Getadc(4) 'Nick<br />
<br />
Acc_roll = Acc_roll * 100<br />
Acc_nick = Acc_nick * 100<br />
<br />
<br />
'<Mittellage ausgleichen><br />
'Die Offsetwerte werden langsam an eine früher ermittelte Waagerechte Positoion angeglichen.<br />
Null_roll = Null_roll * 99<br />
Null_nick = Null_nick * 99<br />
Null_roll = Null_roll + Offset_roll 'Mittellage<br />
Null_nick = Null_nick + Offset_nick 'Mittellage<br />
Null_roll = Null_roll / 100<br />
Null_nick = Null_nick / 100<br />
'</Mittellage ausgleichen><br />
<br />
'Offsetwerte der Beschleunigungssensoren sofort abziehen<br />
'Diese werden nicht laufend ermittelt<br />
Acc_roll = Acc_roll - Null_roll<br />
Acc_nick = Acc_nick - Null_nick<br />
'<Geschwindikgeitsbegrenzung><br />
'Bei der Geschwindigkeitsbegrenzung wird einfach die Nullage der Plattform verändert.<br />
'Beim Vorwärtsbremsen wird nach hinten geneigt.<br />
'Beim Rückwärtsbremsen nach vorne.<br />
'Höchstgeschwindigkeit im Gesetzlichen Rahmen unter 6Km/h (Ausserhalb der KFZ Zulassungsordnung)<br />
Vbrems = 0<br />
Lbrems = 0<br />
If Frei = 0 Then<br />
If Kmh > Vmax Then Vbrems = Vmax - Kmh<br />
If Kmh < Vmaxr Then Vbrems = Vmaxr - Kmh<br />
End If<br />
<br />
'Lastabhängige Bremse<br />
'Es muss immer genug Reserve sein um noch zu Bremsen oder zu Balancieren<br />
Ldummyi = Int(pwm_gesamt)<br />
If Ldummyi > Spwm Then Lbrems = Spwm - Ldummyi<br />
If Ldummyi < Spwmr Then Lbrems = Spwmr - Ldummyi<br />
Brems = Lbrems + Vbrems<br />
Brems = Brems * 50<br />
'Nicht zu heftig Bremsen<br />
If Brems < -2000 Then Brems = -2000<br />
If Brems > 2000 Then Brems = 2000<br />
Acc_nick = Acc_nick + Brems<br />
'</Geschwindikgeitsbegrenzung><br />
<br />
'<Signalaufbereitung der Sensorsignale><br />
K_diff = K_rechts - K_links<br />
K_sum = K_sum * 0.84<br />
K_sum = K_sum + K_diff<br />
'Gleitender Mittelwert der Gyros berechnen um damit den Offset bei Stillstand<br />
'zu haben. Dieser ist leider Temperaturabhängig.<br />
Sum_gyro_gier = Sum_gyro_gier - Mit_gyro_gier<br />
Sum_gyro_gier = Sum_gyro_gier + Gyro_gier<br />
Mit_gyro_gier = Sum_gyro_gier / Gyro_anz<br />
Sig_gyro_gier = Gyro_gier - Mit_gyro_gier<br />
<br />
Sum_gyro_roll = Sum_gyro_roll - Mit_gyro_roll<br />
Sum_gyro_roll = Sum_gyro_roll + Gyro_roll<br />
Mit_gyro_roll = Sum_gyro_roll / Gyro_anz<br />
Sig_gyro_roll = Gyro_roll - Mit_gyro_roll<br />
Korr_acc_roll = Sig_gyro_roll * Gyro_faktor<br />
Sum_acc_roll = Sum_acc_roll - Mit_acc_roll<br />
Sum_acc_roll = Sum_acc_roll + Acc_roll<br />
Sum_acc_roll = Sum_acc_roll + Korr_acc_roll 'Gyrowert hinzu<br />
Mit_acc_roll = Sum_acc_roll / Acc_anz<br />
'************************************************************************************************************************************************************************************<br />
Sdummy1 = Mit_acc_roll * Sig_gyro_gier 'Das soll ausgleichen, daß die Gyros bei gekippten Sensoren eine Drehung um die falsche Achse registrieren.<br />
Sdummy1 = Sdummy1 / 20000 'Die Sensorplatine muss dazu absolut Waagerecht montiert sein.<br />
Lagefehler = Int(sdummy1)<br />
Gyro_nick = Gyro_nick + Lagefehler 'Das soll den Fehler ausgleichen, der durch die geänderte Lage des Gyros auftritt.<br />
'************************************************************************************************************************************************************************************<br />
Sum_gyro_nick = Sum_gyro_nick - Mit_gyro_nick<br />
Sum_gyro_nick = Sum_gyro_nick + Gyro_nick<br />
Mit_gyro_nick = Sum_gyro_nick / Gyro_anz<br />
Sig_gyro_nick = Gyro_nick - Mit_gyro_nick<br />
Korr_acc_nick = Sig_gyro_nick * Gyro_faktor<br />
Sum_acc_nick = Sum_acc_nick - Mit_acc_nick<br />
Sum_acc_nick = Sum_acc_nick + Acc_nick<br />
Sum_acc_nick = Sum_acc_nick - Korr_acc_nick 'Gyrowert hinzu<br />
Mit_acc_nick = Sum_acc_nick / Acc_anz<br />
'</Signalaufbereitung der Sensorsignale><br />
<br />
'<PID-Regler><br />
Stellwert = 0<br />
'<P-Regler><br />
Sdummy1 = Mit_acc_nick<br />
Sdummy1 = Sdummy1 * P_faktor<br />
Stellwert = Stellwert - Sdummy1<br />
'</P-Regler><br />
'<I-Regler><br />
Mit_acc_nick_s = Mit_acc_nick_s + Mit_acc_nick<br />
'Überlauf/unsinnige Werte verhindern<br />
If Mit_acc_nick_s > Max_mit_acc_nick_s Then Mit_acc_nick_s = Max_mit_acc_nick_s<br />
If Mit_acc_nick_s < Min_mit_acc_nick_s Then Mit_acc_nick_s = Min_mit_acc_nick_s<br />
Sdummy1 = Mit_acc_nick_s<br />
Sdummy1 = Sdummy1 * I_faktor<br />
Stellwert = Stellwert - Sdummy1<br />
'</I-Regler><br />
'<D-Regeler><br />
Sdummy1 = Sig_gyro_nick<br />
Sdummy1 = Sdummy1 * D_faktor<br />
Stellwert = Stellwert + Sdummy1<br />
'</D-Regler><br />
<br />
'<Anpassungsfaktoren berechnen><br />
K_sum_anpassung = K_rechts + K_links<br />
K_sum_anpassung = Abs(k_sum_anpassung)<br />
<br />
Mp_anpassung = Pwm_gesamt * Mp_faktor<br />
Mp_anpassung = Abs(mp_anpassung)<br />
Mp_anpassung = Mp_anpassung + 0.95<br />
<br />
Mv_anpassung = K_sum_anpassung * Mv_faktor<br />
Mv_anpassung = Abs(mv_anpassung)<br />
Mv_anpassung = Mv_anpassung + 1<br />
<br />
Mpl_anpassung = Pwm_gesamt * Mpl_faktor<br />
Mpl_anpassung = Abs(mpl_anpassung)<br />
Mpl_anpassung = Mpl_anpassung + 1<br />
<br />
Mvl_anpassung = K_sum_anpassung * Mvl_faktor<br />
Mvl_anpassung = Abs(mvl_anpassung)<br />
Mvl_anpassung = Mvl_anpassung + 1<br />
'</Anpassungsfaktoren berechnen><br />
<br />
<br />
'<Verstärkte Regelung bei hoher Leistung><br />
Stellwert = Stellwert * Mp_anpassung<br />
Stellwert = Stellwert * Mv_anpassung<br />
'<Verstärkte Regelung bei hoher Leistung><br />
<br />
<br />
'<Abgeschwächte Regelung in Stand><br />
<br />
If K_sum_anpassung < 8 Then Stellwert = Stellwert * 0.8<br />
If K_sum_anpassung < 6 Then Stellwert = Stellwert * 0.8<br />
If K_sum_anpassung < 4 Then Stellwert = Stellwert * 0.8<br />
<br />
'</Abgeschwächte Regelung in Stand><br />
Pwm_gesamt = Pwm_gesamt + Stellwert<br />
<br />
'</PID-Regler><br />
<br />
'<Bremsvibrator einmischen><br />
'Der Bremsvibrator signalisiert dem Fahrer, daß wegen irgend einem Grenzwert gebremst wird.<br />
'Das kann V-Max oder P-Max sein.<br />
If Brems <> 0 Then<br />
Bdummy1 = Intcount / 2<br />
Bdummy1 = Bdummy1 Mod 2<br />
If Bdummy1 = 0 Then<br />
Pwm_gesamt = Pwm_gesamt + 5<br />
Else<br />
Pwm_gesamt = Pwm_gesamt - 5<br />
End If<br />
End If<br />
'<Bremsvibrator einmischen><br />
'<Lenkung><br />
Lenkvorgabe = Mit_acc_roll / 80<br />
<br />
Sdummy1 = Abs(lenkvorgabe)<br />
If Sdummy1 <= 6 Then<br />
Sdummy1 = Sdummy1 / 12<br />
Lenkerstellung = Lenkvorgabe * Sdummy1<br />
Else<br />
If Lenkvorgabe < 0 Then<br />
Lenkerstellung = Lenkvorgabe + 3<br />
Else<br />
Lenkerstellung = Lenkvorgabe - 3<br />
End If<br />
End If<br />
<br />
'Lenkfehler berechnen und zum Stellwert hinzu.<br />
Sdummy1 = Sig_gyro_gier<br />
Sdummy1 = Sdummy1 / 5<br />
Lenkfehler = Lenkerstellung - Sdummy1<br />
Lenkfehler = Lenkfehler * Mpl_anpassung<br />
Lenkfehler = Lenkfehler * Mvl_anpassung<br />
<br />
Lenkstellwert = Lenkerstellung + Lenkfehler<br />
<br />
If Lenkstellwert > Max_lenk Then Lenkstellwert = Max_lenk<br />
If Lenkstellwert < Min_lenk Then Lenkstellwert = Min_lenk<br />
<br />
Pwm_lenk_links = Pwm_gesamt + Lenkstellwert<br />
Pwm_lenk_rechts = Pwm_gesamt - Lenkstellwert<br />
<br />
If Pwm_lenk_links > 0 Then Richtung_links = 1 Else Richtung_links = 0<br />
If Pwm_lenk_rechts > 0 Then Richtung_rechts = 1 Else Richtung_rechts = 0<br />
<br />
Pwm_lenk_links = Abs(pwm_lenk_links)<br />
Pwm_lenk_rechts = Abs(pwm_lenk_rechts)<br />
<br />
If Pwm_lenk_links > Maxpwm Then Pwm_lenk_links = Maxpwm<br />
If Pwm_lenk_rechts > Maxpwm Then Pwm_lenk_rechts = Maxpwm<br />
<br />
If Pwm_lenk_links < Minpwm Then Pwm_lenk_links = Minpwm<br />
If Pwm_lenk_rechts < Minpwm Then Pwm_lenk_rechts = Minpwm<br />
<br />
Pwm_links = Pwm_lenk_links<br />
Pwm_rechts = Pwm_lenk_rechts<br />
'</Lenkung><br />
If Antriebaus = 1 Then<br />
If Notaus = 1 Then<br />
'Unfalldatenschreiber: *********************************************************<br />
'Dauert zwar Lange, macht aber nix. Bei Notaus muss nix geregelt werden.<br />
Unfalldatenschreiber<br />
Betriebsdatenschreiber<br />
Notaus = 0<br />
'*******************************************************************************<br />
End If<br />
'Auf 0 setzen was sonst geregelt wird<br />
Richtung_links = 2 'Leerlauf<br />
Richtung_rechts = 2 'Leerlauf<br />
Pwm_links = 0<br />
Pwm_rechts = 0<br />
Pwm_gesamt = 0<br />
Mit_acc_nick_s = 0<br />
Lenkerstellung = 0<br />
K_rechts = 0<br />
K_links = 0<br />
'Waagerechte Positoion setzen wenn Zustand Antriebaus:<br />
Wdummy1 = Getadc(5)<br />
Null_roll = Wdummy1 * 100<br />
Wdummy1 = Getadc(7)<br />
Null_nick = Wdummy1 * 100<br />
'Mittelwert der Beschleunigungssensoren auf aktuellen Wert stellen<br />
'Der Mittelwert braucht sonst zu lange bis<br />
'er sich eingeregelt hat<br />
'Sum_acc_roll = Acc_roll * Acc_anz<br />
'Sum_acc_nick = Acc_nick * Acc_anz<br />
If Intcount = 0 Then T30 = 1 'Regelparameter vom Tacho anfordern<br />
If Intcount = 50 Then T30 = 1 'Regelparameter vom Tacho anfordern<br />
End If<br />
'*******************************************************************************<br />
If T30 = 1 Then 'Regelparameter vom Tacho anfordern<br />
K_links = 0<br />
K_rechts = 0<br />
Zeiger_meldung = 1<br />
Bdummy1 = Udr<br />
T30 = 0 'Damit keine alte Rückmeldung ausgewertet wird<br />
Timeout = Timer0<br />
Timeout = Timeout + 100<br />
Print Chr(255) ; Chr(0) ; Chr(0) ; Chr(255) ; Chr(13)<br />
<br />
While Zeiger_meldung < 31<br />
If Ucsr0a.rxc0 = 1 Then 'Warten bis ein Byte eingetroffen ist<br />
Tachomeldung(zeiger_meldung) = Udr<br />
Incr Zeiger_meldung<br />
Timeout = Timer0<br />
Timeout = Timeout + 20<br />
End If<br />
If Timer0 > Timeout Then<br />
T30 = 0<br />
Exit While 'Timeout<br />
End If<br />
Wend<br />
If T30 = 13 Then<br />
$asm<br />
lds R24,{t1}<br />
LDs R25,{t2}<br />
add R24,R25<br />
LDs R25,{t3}<br />
add R24,R25<br />
LDs R25,{t4}<br />
add R24,R25<br />
LDs R25,{t5}<br />
add R24,R25<br />
LDs R25,{t6}<br />
add R24,R25<br />
LDs R25,{t7}<br />
add R24,R25<br />
LDs R25,{t8}<br />
add R24,R25<br />
LDs R25,{t9}<br />
add R24,R25<br />
LDs R25,{t10}<br />
add R24,R25<br />
LDs R25,{t11}<br />
add R24,R25<br />
LDs R25,{t12}<br />
add R24,R25<br />
LDs R25,{t13}<br />
add R24,R25<br />
LDs R25,{t14}<br />
add R24,R25<br />
LDs R25,{t15}<br />
add R24,R25<br />
LDs R25,{t16}<br />
add R24,R25<br />
LDs R25,{t17}<br />
add R24,R25<br />
LDs R25,{t18}<br />
add R24,R25<br />
LDs R25,{t19}<br />
add R24,R25<br />
LDs R25,{t20}<br />
add R24,R25<br />
LDs R25,{t21}<br />
add R24,R25<br />
LDs R25,{t22}<br />
add R24,R25<br />
LDs R25,{t23}<br />
add R24,R25<br />
LDs R25,{t24}<br />
add R24,R25<br />
LDs R25,{t25}<br />
add R24,R25<br />
LDs R25,{t26}<br />
add R24,R25<br />
LDs R25,{t27}<br />
add R24,R25<br />
LDs R25,{t28}<br />
add R24,R25<br />
STS {Bdummy1},R24<br />
$end Asm<br />
<br />
If Bdummy1 = T29 Then<br />
P_faktor = P_tacho<br />
I_faktor = I_tacho<br />
D_faktor = D_tacho<br />
Mp_faktor = Mp_tacho<br />
Mv_faktor = Mv_tacho<br />
Mpl_faktor = Mpl_tacho<br />
Mvl_faktor = Mvl_tacho<br />
Werteneu = 1<br />
End If<br />
End If<br />
<br />
Else<br />
'Errechnete Geschwindigkeiten an Motoren Senden:<br />
'Rechter Motor:<br />
Checksum_rechts = 82<br />
Checksum_rechts = Checksum_rechts + Richtung_rechts<br />
Checksum_rechts = Checksum_rechts + Pwm_rechts<br />
'Geschwindigkeit an Motorregler senden<br />
Zeiger_meldung = 1<br />
Bdummy1 = Udr 'Puffer leeren<br />
'Print Chr(82) ; Chr(richtung_rechts) ; Chr(pwm_rechts) ; Chr(checksum_rechts) ; Chr(13);<br />
'In Assembler geht das so:<br />
$asm<br />
Ldi R24 , 82<br />
STS udr,R24<br />
Warten1:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten1<br />
LDS R24,{Richtung_rechts}<br />
STS udr,R24<br />
Warten2:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten2<br />
lds R24,{Pwm_rechts}<br />
STS udr,R24<br />
Warten3:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten3<br />
LDS R24,{Checksum_rechts}<br />
STS udr,R24<br />
Warten4:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten4<br />
LDI R24,13<br />
STS udr,R24<br />
Warten5:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten5<br />
$end Asm<br />
Motormeldung(8) = 0 'Damit keine alte Rückmeldung ausgewertet wird<br />
Timeout = Timer0<br />
Timeout = Timeout + 80<br />
While Zeiger_meldung < 9<br />
If Ucsr0a.rxc0 = 1 Then 'Warten bis ein Byte eingetroffen ist<br />
Motormeldung(zeiger_meldung) = Udr<br />
Incr Zeiger_meldung<br />
End If<br />
If Timer0 > Timeout Then<br />
Ende = 0<br />
Exit While 'Timeout<br />
End If<br />
Wend<br />
$asm<br />
lds R24,{M1}<br />
LDs R25,{M2}<br />
ADD R24,R25<br />
LDs R25,{M3}<br />
ADD R24,R25<br />
LDs R25,{M4}<br />
ADD R24,R25<br />
LDs R25,{M5}<br />
ADD R24,R25<br />
LDs R25,{M6}<br />
ADD R24,R25<br />
STS {Bdummy1},R24<br />
$end Asm<br />
If Bdummy1 <> Checksumme Then Ende = 0<br />
If Ende = 13 Then<br />
U_rechts = U<br />
I_rechts = I<br />
K_rechts = K<br />
Else<br />
Incr Seriell_err_r<br />
S_err = 1<br />
End If<br />
'Linker Motor:<br />
Checksum_links = 76<br />
Checksum_links = Checksum_links + Richtung_links<br />
Checksum_links = Checksum_links + Pwm_links<br />
Zeiger_meldung = 1<br />
Bdummy1 = Udr 'Puffer leeren<br />
'Print Chr(76) ; Chr(richtung_links) ; Chr(pwm_links) ; Chr(checksum_links) ; Chr(13);<br />
'In Assembler geht das so:<br />
$asm<br />
Ldi R24 , 76<br />
STS udr,R24<br />
Warten6:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten6<br />
LDS R24,{Richtung_links}<br />
STS udr,R24<br />
Warten7:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten7<br />
lds R24,{Pwm_links}<br />
STS udr,R24<br />
Warten8:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten8<br />
LDS R24,{Checksum_links}<br />
STS udr,R24<br />
Warten9:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten9<br />
LDI R24,13<br />
STS udr,R24<br />
Warten10:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten10<br />
$end Asm<br />
Motormeldung(8) = 0 'Damit keine alte Rückmeldung ausgewertet wird<br />
Timeout = Timer0<br />
Timeout = Timeout + 80<br />
While Zeiger_meldung < 9<br />
If Ucsr0a.rxc0 = 1 Then 'Warten bis ein Byte eingetroffen ist<br />
Motormeldung(zeiger_meldung) = Udr<br />
Incr Zeiger_meldung<br />
End If<br />
If Timer0 > Timeout Then<br />
Ende = 0<br />
Exit While 'Timeout<br />
End If<br />
Wend<br />
$asm<br />
lds R24,{M1}<br />
LDs R25,{M2}<br />
ADD R24,R25<br />
LDs R25,{M3}<br />
ADD R24,R25<br />
LDs R25,{M4}<br />
ADD R24,R25<br />
LDs R25,{M5}<br />
ADD R24,R25<br />
LDs R25,{M6}<br />
ADD R24,R25<br />
STS {Bdummy1},R24<br />
$end Asm<br />
If Bdummy1 <> Checksumme Then Ende = 0<br />
If Ende = 13 Then<br />
U_links = U<br />
I_links = I<br />
K_links = K<br />
Else<br />
Incr Seriell_err_l<br />
S_err = 1<br />
End If<br />
If S_err = 1 Then 'Sicherheitshalber, damit der Lenkausgleich nicht überreagiert.<br />
K_links = 0<br />
K_rechts = 0<br />
S_err = 0<br />
End If<br />
End If<br />
If Antriebaus = 0 Then<br />
'<Notauskriterien ermitteln><br />
If Mit_acc_nick > -300 Then<br />
If Mit_acc_nick < 300 Then<br />
<br />
Regelzeit = 0<br />
End If<br />
End If<br />
Incr Regelzeit<br />
'</Notauskriterien ermitteln><br />
'<Notauskriterien abprüfen><br />
If Regelzeit > 250 Then 'Wenn nach 2,5s waagerechte Lage nicht erreicht<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(regelzeit)<br />
Ugrund = "*Rz " + Ugrund<br />
End If<br />
Ldummyi = 4000 + Brems<br />
If Mit_acc_nick > Ldummyi Then 'zu weit nach hinten gekippt<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(mit_acc_nick)<br />
Ugrund = "*Nick " + Ugrund<br />
End If<br />
Ldummyi = -4000 + Brems<br />
If Mit_acc_nick < Ldummyi Then 'zu weit nach vorn gekippt<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(mit_acc_nick)<br />
Ugrund = "*Nick " + Ugrund<br />
End If<br />
If Mit_acc_roll > 5000 Then 'Lenker zu weit<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(mit_acc_roll)<br />
Ugrund = "*Roll " + Ugrund<br />
End If<br />
If Mit_acc_roll < -5000 Then 'Lenker zu weit<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(mit_acc_roll)<br />
Ugrund = "*Roll " + Ugrund<br />
End If<br />
If K_diff > 10 Then 'Plattform rotiert zu schnell<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(k_diff)<br />
Ugrund = "*Gier " + Ugrund<br />
End If<br />
<br />
If K_diff < -10 Then 'Plattform rotiert zu schnell<br />
Notaus = 1<br />
Antriebaus = 1<br />
Ugrund = Str(k_diff)<br />
Ugrund = "*Gier " + Ugrund<br />
End If<br />
'</Notauskriterien abprüfen><br />
End If<br />
'<Akkuspannung berechnen><br />
Ugemessen = U_links + U_rechts<br />
Shift Ugemessen , Right , 1 , Signed<br />
'</Akkuspannung berechnen><br />
'<Gesamtstrom berechnen><br />
Igemessen = I_links + I_rechts<br />
'</Gesamtstrom berechnen><br />
'<verbrauchte As berechnen><br />
If Igemessen > 0 Then<br />
Summe_as_entladen = Summe_as_entladen + Igemessen 'Verbrauchte<br />
End If<br />
If Igemessen < 0 Then<br />
Summe_as_laden = Summe_as_laden - Igemessen 'Rückgespeiste<br />
End If<br />
'mAh aus den As rausholen<br />
'um überläufe zu verhindern<br />
'Die 360000 kommen weil:<br />
'Igemessen in mA -> Faktor 1<br />
'100 Messungen pro Sekunde -> mal 100<br />
'3600 mAmperesekunden=1 mAh -> also nochmal mal 3600<br />
If Summe_as_entladen > 360000 Then<br />
Summe_mah_entladen = Summe_mah_entladen + 1<br />
Summe_as_entladen = Summe_as_entladen - 360000<br />
End If<br />
If Summe_as_laden > 360000 Then 'Das kann passieren wenns den Berg runter geht<br />
Summe_mah_laden = Summe_mah_laden + 1<br />
Summe_as_laden = Summe_as_laden - 360000<br />
End If<br />
Erzeugt = Summe_mah_laden<br />
Verbraucht = Summe_mah_entladen<br />
Erzeugt = Erzeugt * 0.7 'Das ist der Akku-Wirkungsgrad 0.7 (0.85) bezogen auf den Stom<br />
Verbraucht = Verbraucht - Erzeugt<br />
Akkuinhalt = Akkukap<br />
Akkuverbrauch = Verbraucht<br />
Akkuprozent = Akkuverbrauch / Akkuinhalt<br />
Akkuprozent = Akkuprozent * 1000<br />
Akkuprozent = Int(akkuprozent)<br />
Akkustand = Akkuprozent<br />
'</verbrauchte As berechnen><br />
'<Strecke berechnen><br />
Kx = K_links + K_rechts<br />
Kx = Kx / 2<br />
Strecke = Kx * Di<br />
Zentimeter = Zentimeter + Strecke<br />
If Zentimeter >= 100 Then<br />
Meter = Meter + 1<br />
Zentimeter = Zentimeter - 100<br />
End If<br />
If Zentimeter < 0 Then<br />
Meter = Meter - 1<br />
Zentimeter = Zentimeter + 100<br />
End If<br />
If Meter >= 1000 Then<br />
Kilometer = Kilometer + 1<br />
Meter = Meter - 1000<br />
End If<br />
If Meter < 0 Then<br />
Kilometer = Kilometer - 1<br />
Meter = Meter + 1000<br />
End If<br />
'</Strecke berechnen><br />
'<Geschwindigkeit berechnen><br />
Kv = Kv + Kx<br />
Kmh = Kv * Kmhfaktor<br />
Kv = Kv * 0.75 'Bei Änderung auch den kmhfaktor neu berechnen<br />
If Kmh > Max_v Then Max_v = Kmh<br />
If Kmh < Min_v Then Min_v = Kmh<br />
'</Geschwindigkeit berechnen><br />
If Bzeit < 500 Then Incr Bzeit<br />
Incr Intcount<br />
Incr Tachocount<br />
Select Case Tachocount<br />
'*******************************************************************************<br />
'Alle möglichen Werte werden an den Tacho geschickt. Manche für die Funktion<br />
'des Tachos, andere um die Steuerung zu optimieren.<br />
'*******************************************************************************<br />
Case 0 'U ausgeben<br />
B(1) = 1<br />
U = Ugemessen<br />
'U = Sig_Gyro_Nick<br />
B(2) = Motormeldung(1)<br />
B(3) = Motormeldung(2)<br />
B(5) = 1<br />
Case 1 'I ausgeben<br />
B(1) = 2<br />
I = Igemessen / 10<br />
B(2) = Motormeldung(3)<br />
B(3) = Motormeldung(4)<br />
B(5) = 1<br />
Case 2 'Km/h<br />
B(1) = 3<br />
B(2) = Kmhmeldung(1)<br />
B(3) = Kmhmeldung(2)<br />
B(5) = 1<br />
Case 3 'Akkuprozente<br />
B(1) = 5<br />
B(2) = Akkumeldung(1)<br />
B(3) = Akkumeldung(2)<br />
B(5) = 1<br />
Case 4 'Meter<br />
B(1) = 7<br />
B(2) = Metermeldung(1)<br />
B(3) = Metermeldung(2)<br />
B(5) = 1<br />
Case 5 'Kilometer<br />
B(1) = 6<br />
B(2) = Kilometermeldung(1)<br />
B(3) = Kilometermeldung(2)<br />
B(5) = 1<br />
Case 6<br />
If Antriebaus = 0 Then<br />
Maccroll = Mit_acc_roll<br />
B(1) = 8<br />
B(2) = Maccroll1<br />
B(3) = Maccroll2<br />
B(4) = 1<br />
Else<br />
Nullroll = Null_roll<br />
B(1) = 12<br />
B(2) = Nullroll1<br />
B(3) = Nullroll2<br />
B(4) = 1<br />
End If<br />
Case 7<br />
If Antriebaus = 0 Then<br />
B(1) = 9<br />
B(2) = Maccroll3<br />
B(3) = Maccroll4<br />
B(4) = 1<br />
Else<br />
B(1) = 13<br />
B(2) = Nullroll3<br />
B(3) = Nullroll4<br />
B(4) = 1<br />
End If<br />
Case 8<br />
B(1) = 4<br />
B(2) = Antriebaus<br />
B(3) = Ta<br />
B(4) = 1<br />
Case 9<br />
If Antriebaus = 0 Then<br />
Maccnick = Mit_acc_nick<br />
B(1) = 10<br />
B(2) = Maccnick1<br />
B(3) = Maccnick2<br />
B(4) = 1<br />
Else<br />
Nullnick = Null_nick<br />
B(1) = 14<br />
B(2) = Nullnick1<br />
B(3) = Nullnick2<br />
B(4) = 1<br />
End If<br />
Case 10<br />
If Antriebaus = 0 Then<br />
B(1) = 11<br />
B(2) = Maccnick3<br />
B(3) = Maccnick4<br />
B(4) = 1<br />
Else<br />
B(1) = 15<br />
B(2) = Nullnick3<br />
B(3) = Nullnick4<br />
B(4) = 1<br />
End If<br />
Case 11<br />
Sw = Stellwert<br />
B(1) = 16<br />
B(2) = Sw1<br />
B(3) = Sw2<br />
B(4) = 1<br />
Case 12<br />
B(1) = 17<br />
B(2) = Sw3<br />
B(3) = Sw4<br />
B(4) = 1<br />
Case 13<br />
Gyronick = Sig_gyro_nick<br />
B(1) = 18<br />
B(2) = Gyronick1<br />
B(3) = Gyronick2<br />
B(4) = 1<br />
Case 14<br />
B(1) = 19<br />
B(2) = Gyronick3<br />
B(3) = Gyronick4<br />
B(4) = 1<br />
Case 15<br />
Kksum = K_sum<br />
B(1) = 20<br />
B(2) = Kksum1<br />
B(3) = Kksum2<br />
B(4) = 1<br />
Case 16<br />
B(1) = 21<br />
B(2) = Kksum3<br />
B(3) = Kksum4<br />
B(4) = 1<br />
If Antriebaus = 0 Then Tachocount = 255 'Gleich zu 0 überlaufen lassen<br />
Case 17<br />
B(1) = 22<br />
B(2) = Pf1<br />
B(3) = Pf2<br />
B(4) = 1<br />
Case 18<br />
B(1) = 23<br />
B(2) = Pf3<br />
B(3) = Pf4<br />
B(4) = 1<br />
Case 19<br />
B(1) = 24<br />
B(2) = If1<br />
B(3) = If2<br />
B(4) = 1<br />
Case 20<br />
B(1) = 25<br />
B(2) = If3<br />
B(3) = If4<br />
B(4) = 1<br />
Case 21<br />
B(1) = 26<br />
B(2) = Df1<br />
B(3) = Df2<br />
B(4) = 1<br />
Case 22<br />
B(1) = 27<br />
B(2) = Df3<br />
B(3) = Df4<br />
B(4) = 1<br />
Case 23<br />
B(1) = 28<br />
B(2) = Mpf1<br />
B(3) = Mpf2<br />
B(4) = 1<br />
Case 24<br />
B(1) = 29<br />
B(2) = Mpf3<br />
B(3) = Mpf4<br />
B(4) = 1<br />
Case 25<br />
B(1) = 30<br />
B(2) = Mvf1<br />
B(3) = Mvf2<br />
B(4) = 1<br />
Case 26<br />
B(1) = 31<br />
B(2) = Mvf3<br />
B(3) = Mvf4<br />
B(4) = 1<br />
Case 27<br />
B(1) = 32<br />
B(2) = Mplf1<br />
B(3) = Mplf2<br />
B(4) = 1<br />
Case 28<br />
B(1) = 33<br />
B(2) = Mplf3<br />
B(3) = Mplf4<br />
B(4) = 1<br />
Case 29<br />
B(1) = 34<br />
B(2) = Mvlf1<br />
B(3) = Mvlf2<br />
B(4) = 1<br />
Case 30<br />
B(1) = 35<br />
B(2) = Mvlf3<br />
B(3) = Mvlf4<br />
B(4) = 1<br />
<br />
Tachocount = 255<br />
Case Else<br />
B(5) = 0 'Nix ausgeben<br />
End Select<br />
If Intcount = 99 Then Intcount = 255<br />
If B(5) = 1 Then<br />
'Checksumme berechnen<br />
B(4) = B(1)<br />
B(4) = B(4) + B(2)<br />
B(4) = B(4) + B(3)<br />
<br />
'Print Chr(b(1)) ; Chr(b(2)) ; Chr(b(3)) ; Chr(b(4)) ; Chr(13);<br />
'Print in Assembler:<br />
$asm<br />
LDS R24,285 'b(1)<br />
STS udr,R24<br />
Warten11:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten11<br />
LDS R24,286 'b(2)<br />
STS udr,R24<br />
Warten12:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten12<br />
lds R24,287 'B(3)<br />
STS udr,R24<br />
Warten13:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten13<br />
LDS R24,288 'B(4)<br />
STS udr,R24<br />
Warten14:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten14<br />
LDI R24,13<br />
STS udr,R24<br />
Warten15:<br />
LDS R24,UCSR0A<br />
BST R24,5<br />
Brtc warten15<br />
$end Asm<br />
Ta = Timer0 'Um festzustellen ob der Interrupt zu lange dauert<br />
End If<br />
Led2 = 0<br />
Return<br />
</pre><br />
<br />
==Tacho==<br />
<br />
Als Tacho wird ein fertiges Display von [http://www.shop.display3000.com/mikrocontrollerloesungen/uc-mit-21-tft/d072-mikrocontroller-atmega-tft-farbdisplay-21.html Display3000.de] mit dem optionalen SD-Katen Modul verwendet. Das Display ist für diese Zwecke gerade brauchbar. Die mitgelieferten Bibliotheken könnten etwas besser, und vor allem schneller sein. Neben der normalen Geschwindigkeitsanzeige können über den Tacho auch die PID-Parameter sowie die diversen Parameter zur Anpassung der Motorkennlinie eingestellt werden. Wenn diese Parameter einmal eingestellt sind ist zum Betrieb der Tacho nicht zwingend erforderlich. Das ganze läuft auch ohne. Wenn eine SD-Karte gesteckt ist können mit dem Tacho auch alle Telegramme, die über die Serielle Schnittstelle gehen, mitgeloggt werden. In diesem Modus muss wegen der langsamen Bibliotheken auf die Aktualisierung des Display verzichtet werden. Bei früheren Versuchen wurde auch versucht einen PDA als Tacho zu verwenden. Dies funktioierte sogar, ein mitloggen war jedoch nicht möglich. Windows-Mobile ist bei 600Mhz langsamer als ein Atmel mit 16Mhz.<br />
<br />
===Software===<br />
Die Software des Tachos wurde nicht ganz so sorgfältig erstellt wie die des Motorreglers oder der Lageregelung. Hier war der Leitgedanke "Haupsache es tut".<br />
<pre><br />
$hwstack = 256<br />
$swstack = 256<br />
$framesize = 64<br />
$regfile = "m2561def.dat"<br />
$crystal = 16000000 'enter the used clock of your actual microcontroller<br />
$baud1 = 57600<br />
<br />
<br />
<br />
<br />
'############################################################################################<br />
'4 - Definition of used ports and pull up resistors<br />
'At our boards we are using Port B for the SPI-communication to the LCD.<br />
'Now we need to select Port B as to an output port (data output to the display)<br />
Ddrb = &B01110110 'DDR = Data direction register; Port B1, B2, B4, B5, B6 switched to output (1) as needed by the display ....<br />
Portb = &B10001001 '... the other ports of Port B are inputs with switched on pull up resistors<br />
<br />
Ddra = &B00000000 'switch all 8 Ports of Port A to input (0), Pin (PA.0 - PA.7)<br />
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<br />
'You need to pull these Pins against ground (GND)<br />
Ddrc = &B00000000 'switch all Ports of Port C to input<br />
Portc = &B11111111 'all pull-up-Resistors turned on<br />
<br />
Ddrd = &B00000000 'switch all Ports of Port D to input<br />
Portd = &B11110011 'all pull-up-Resistors turned on<br />
<br />
Ddre = &B10000000 'E7=Output (SD card activate), all other Input<br />
Porte = &B11111111 'all pull-up-Resistors turned on<br />
<br />
Ddrf = &B00000000 'switch all Ports of Port F to input<br />
Portf = &B11111111 'all pull-up-Resistors turned on<br />
<br />
Ddrg = &B00000000 'switch all Ports of Port G to input<br />
Portg = &B11111111 'all pull-up-Resistors turned on<br />
<br />
<br />
<br />
<br />
Declare Sub Activate_display()<br />
Declare Sub Activate_sd()<br />
Declare Sub Minmax()<br />
Declare Function Trimtext(t As String) As String * 22<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
Const Titel = "Tacho 0.1 "<br />
<br />
Dim Ep0 As Byte At $0201<br />
Dim Ep1 As Byte At $0202<br />
Dim Ep2 As Byte At $0203<br />
Dim Ep3 As Byte At $0204<br />
Dim Ep4 As Byte At $0205<br />
Dim Ep5 As Byte At $0206<br />
Dim Iwert As Integer At $0203 Overlay<br />
Dim Wwert As Integer At $0203 Overlay<br />
Dim Index As Byte At $202 Overlay<br />
<br />
<br />
Dim Maccx As Long At $0207<br />
Dim Maccx1 As Byte At $0207 Overlay<br />
Dim Maccx2 As Byte At $0208 Overlay<br />
Dim Maccx3 As Byte At $0209 Overlay<br />
Dim Maccx4 As Byte At $020a Overlay<br />
Dim Maccy As Long At $020b<br />
Dim Maccy1 As Byte At $020b Overlay<br />
Dim Maccy2 As Byte At $020c Overlay<br />
Dim Maccy3 As Byte At $020d Overlay<br />
Dim Maccy4 As Byte At $020e Overlay<br />
<br />
Dim Nullx As Long At $020f<br />
Dim Nullx1 As Byte At $020f Overlay<br />
Dim Nullx2 As Byte At $0210 Overlay<br />
Dim Nullx3 As Byte At $0211 Overlay<br />
Dim Nullx4 As Byte At $0212 Overlay<br />
Dim Nully As Long At $0213<br />
Dim Nully1 As Byte At $0213 Overlay<br />
Dim Nully2 As Byte At $0214 Overlay<br />
Dim Nully3 As Byte At $0215 Overlay<br />
Dim Nully4 As Byte At $0216 Overlay<br />
Dim Sw As Single At $00217<br />
<br />
Dim Sw1 As Byte At $0217 Overlay<br />
Dim Sw2 As Byte At $0218 Overlay<br />
Dim Sw3 As Byte At $0219 Overlay<br />
Dim Sw4 As Byte At $021a Overlay<br />
<br />
Dim Gyronick As Long At $0021b<br />
Dim Gyronick1 As Byte At $021b Overlay<br />
Dim Gyronick2 As Byte At $021c Overlay<br />
Dim Gyronick3 As Byte At $021d Overlay<br />
Dim Gyronick4 As Byte At $021e Overlay<br />
<br />
Dim Kksum As Single At $0021f<br />
Dim Kksum1 As Byte At $021f Overlay<br />
Dim Kksum2 As Byte At $0220 Overlay<br />
Dim Kksum3 As Byte At $0221 Overlay<br />
Dim Kksum4 As Byte At $0222 Overlay<br />
<br />
Dim P_faktor As Single At $0223<br />
Dim P_f1 As Byte At $0223 Overlay<br />
Dim P_f2 As Byte At $0224 Overlay<br />
Dim P_f3 As Byte At $0225 Overlay<br />
Dim P_f4 As Byte At $0226 Overlay<br />
Dim I_faktor As Single At $0227<br />
Dim I_f1 As Byte At $0227 Overlay<br />
Dim I_f2 As Byte At $0228 Overlay<br />
Dim I_f3 As Byte At $0229 Overlay<br />
Dim I_f4 As Byte At $022a Overlay<br />
Dim D_faktor As Single At $022b<br />
Dim D_f1 As Byte At $022b Overlay<br />
Dim D_f2 As Byte At $022c Overlay<br />
Dim D_f3 As Byte At $022d Overlay<br />
Dim D_f4 As Byte At $022e Overlay<br />
Dim Mp_faktor As Single At $022f<br />
Dim Mp_f1 As Byte At $022f Overlay<br />
Dim Mp_f2 As Byte At $0230 Overlay<br />
Dim Mp_f3 As Byte At $0231 Overlay<br />
Dim Mp_f4 As Byte At $0232 Overlay<br />
<br />
Dim Mv_faktor As Single At $0233<br />
Dim Mv_f1 As Byte At $0233 Overlay<br />
Dim Mv_f2 As Byte At $0234 Overlay<br />
Dim Mv_f3 As Byte At $0235 Overlay<br />
Dim Mv_f4 As Byte At $0236 Overlay<br />
<br />
Dim Mpl_faktor As Single At $0237<br />
Dim Mpl_f1 As Byte At $0237 Overlay<br />
Dim Mpl_f2 As Byte At $0238 Overlay<br />
Dim Mpl_f3 As Byte At $0239 Overlay<br />
Dim Mpl_f4 As Byte At $023a Overlay<br />
<br />
Dim Mvl_faktor As Single At $023b<br />
Dim Mvl_f1 As Byte At $023b Overlay<br />
Dim Mvl_f2 As Byte At $023c Overlay<br />
Dim Mvl_f3 As Byte At $023d Overlay<br />
Dim Mvl_f4 As Byte At $023e Overlay<br />
<br />
Dim Pfaktor As Long<br />
Dim Ifaktor As Long<br />
Dim Dfaktor As Long<br />
Dim Mpfaktor As Long<br />
Dim Mvfaktor As Long<br />
Dim Mplfaktor As Long<br />
Dim Mvlfaktor As Long<br />
<br />
<br />
Dim Stellwert As Single<br />
Dim Gyro_nick As Long<br />
Dim Null_y As Long<br />
Dim Null_x As Long<br />
Dim Mit_acc_y As Long<br />
Dim Mit_acc_x As Long<br />
Dim K_sum As Single<br />
Dim K_summax As Single<br />
Dim K_summin As Single<br />
<br />
Dim Bdummy As Byte<br />
Dim Sdummy As Single<br />
Dim Wdummy As Word<br />
Dim Ldummy As Long<br />
Dim Idummy As Integer<br />
Dim Kilometer As Word<br />
Dim Meter As Integer<br />
Dim Akkuprozente As Integer<br />
Dim Kmh As Integer<br />
Dim Kmhmax As Integer<br />
Dim Kmhmin As Integer<br />
<br />
Dim I As Integer<br />
Dim Imax As Integer<br />
Dim Imin As Integer<br />
<br />
Dim U As Integer<br />
Dim Umax As Integer<br />
Dim Umin As Integer<br />
Dim Ml As Integer<br />
Dim Mlmax As Integer<br />
Dim Mrmax As Integer<br />
Dim Mr As Integer<br />
Dim Mlmin As Integer<br />
Dim Mrmin As Integer<br />
Dim Modus As Byte<br />
Dim Editzeile As Byte<br />
Dim Utext As String * 22<br />
Dim Itext As String * 22<br />
Dim Ltext As String * 22<br />
Dim L1 As Byte<br />
Dim L2 As Byte<br />
Dim Text As String * 22<br />
Dim Farbe As Word<br />
Dim X1 As Byte<br />
Dim Y1 As Byte<br />
Dim X2 As Byte<br />
Dim Y2 As Byte<br />
Dim Startkilometer As Single<br />
Dim Ta As Byte<br />
Dim Tamax As Byte<br />
<br />
Dim Antriebaus As Byte<br />
<br />
Dim Xoffset As Long<br />
Dim Yoffset As Long<br />
Dim Ya As Byte<br />
Dim Xa As Byte<br />
<br />
Dim Lname As Long<br />
Dim Dateiname As String * 12<br />
Dim Dateilaenge As Long<br />
Dim Dateiaktuell As Byte<br />
Dim Ulog As Single<br />
Dim Ilog As Single<br />
Dim Kmhlog As Single<br />
Dim Kmlog As Single<br />
Dim Akkuprozentelog As Single<br />
Dim Loopcount As Word<br />
Dim Aloopcount As Word<br />
Dim Logtext As String * 255<br />
Dim Zeit As String * 8<br />
Dim Sichern As Byte<br />
Dim Transferok As Byte<br />
<br />
Config Clock = User<br />
Config Date = Dmy , Separator = .<br />
<br />
<br />
$include "Init21_display3000.bas"<br />
$include "Config_mmc.bas"<br />
<br />
If Porte.7 = 1 Then Activate_display<br />
Gosub Lcd_init<br />
Wait 1<br />
<br />
<br />
Orientation = Portrait180<br />
<br />
If Porte.7 = 0 Then Activate_sd<br />
Gbdriveerror = Driveinit() ' Init MMC/SD Card<br />
If Gbdriveerror = 0 Then<br />
$include "Config_AVR-DOS.BAS" ' Include AVR-DOS Configuration and library<br />
Bdummy = Initfilesystem(1) ' Partition 1<br />
Ldummy = Disksize()<br />
Ldummy = Ldummy / 1024<br />
Utext = Str(ldummy)<br />
Utext = "Size: " + Utext<br />
Utext = Utext + " mb"<br />
Ldummy = Diskfree()<br />
Ldummy = Ldummy / 1024<br />
Itext = Str(ldummy)<br />
Itext = "Free: " + Itext<br />
Itext = Itext + " mb"<br />
If Porte.7 = 1 Then Activate_display<br />
Lcd_cls<br />
Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue<br />
Lcd_print "SD-Karte init" , 0 , 18 , 1 , 1 , 1 , Black , White<br />
Lcd_print Utext , 0 , 27 , 1 , 1 , 1 , Black , White<br />
Lcd_print Itext , 0 , 36 , 1 , 1 , 1 , Black , White<br />
Wait 7<br />
Else<br />
If Porte.7 = 1 Then Activate_display<br />
Ltext = Str(gbdriveerror)<br />
Ltext = "Fehler: " + Ltext<br />
Lcd_cls<br />
Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue<br />
Lcd_print "SD-Karte init" , 0 , 18 , 1 , 1 , 1 , Black , White<br />
Lcd_print Ltext , 0 , 27 , 1 , 1 , 1 , Black , White<br />
Wait 7<br />
End If<br />
<br />
Readeeprom Startkilometer , 0<br />
Readeeprom Xoffset , 4<br />
Readeeprom Yoffset , 8<br />
'Einige Werte vorbelegen um Fehlerhafte Grafik<br />
'zu vermeiden wenn keine Verbindung besteht<br />
Xa = 74<br />
Ya = 130<br />
Antriebaus = 1<br />
Null_x = Xoffset<br />
Null_y = Yoffset<br />
<br />
<br />
<br />
<br />
<br />
If Porte.7 = 1 Then Activate_display<br />
Lcd_cls<br />
Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue<br />
If Modus = 0 Then<br />
Lcd_rect 8 , 84 , 124 , 95 , 0 , Black<br />
Lcd_rect 24 , 125 , 124 , 135 , 0 , Black<br />
Lcd_rect 8 , 100 , 19 , 160 , 0 , Black<br />
Lcd_draw 20 , 130 , 22 , 130 , 0 , Black<br />
Lcd_draw 74 , 136 , 74 , 138 , 0 , Black<br />
Lcd_draw 0 , 167 , 132 , 167 , 0 , Black<br />
End If<br />
<br />
Config Timer2 = Timer , Prescale = 128<br />
Assr.exclk = 0<br />
Assr.as2 = 1<br />
<br />
On Timer2 Tick<br />
Enable Timer2<br />
Start Timer2<br />
<br />
<br />
On Urxc1 Datenempfang<br />
Enable Urxc1<br />
Enable Interrupts<br />
Minmax<br />
Do<br />
<br />
If Pind.1 = 0 Then<br />
Waitms 3<br />
If Pind.1 = 0 Then<br />
While Pind.1 = 0<br />
Wend<br />
Modus = Modus + 1<br />
If Gbdriveerror <> 0 Then 'Logging nicht zulassen wenn DriveError<br />
If Modus > 3 Then Modus = 0<br />
End If<br />
<br />
If Modus <> 3 Then 'nur berechnen wenn die Werte nicht editiert werden<br />
<br />
Sdummy = P_faktor * 10000<br />
Sdummy = Round(sdummy)<br />
Pfaktor = Sdummy<br />
<br />
Sdummy = I_faktor * 1000000<br />
Sdummy = Round(sdummy)<br />
Ifaktor = Sdummy<br />
<br />
Sdummy = D_faktor * 1000<br />
Sdummy = Round(sdummy)<br />
Dfaktor = Sdummy<br />
<br />
Sdummy = Mp_faktor * 10000<br />
Sdummy = Round(sdummy)<br />
Mpfaktor = Sdummy<br />
<br />
Sdummy = Mv_faktor * 1000<br />
Sdummy = Round(sdummy)<br />
Mvfaktor = Sdummy<br />
<br />
Sdummy = Mpl_faktor * 10000<br />
Sdummy = Round(sdummy)<br />
Mplfaktor = Sdummy<br />
<br />
Sdummy = Mvl_faktor * 1000<br />
Sdummy = Round(sdummy)<br />
Mvlfaktor = Sdummy<br />
<br />
End If<br />
<br />
<br />
<br />
If Modus > 4 Then Modus = 0<br />
If Porte.7 = 1 Then Activate_display<br />
Lcd_cls<br />
Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue<br />
<br />
<br />
If Modus = 4 Then<br />
Lcd_print "LOGGING" , 30 , 40 , 2 , 1 , 2 , Black , White<br />
Dateiaktuell = 0<br />
Else<br />
If Modus = 0 Then<br />
Lcd_rect 8 , 84 , 124 , 95 , 0 , Black<br />
Lcd_rect 24 , 125 , 124 , 135 , 0 , Black<br />
Lcd_rect 8 , 100 , 19 , 160 , 0 , Black<br />
Lcd_draw 20 , 130 , 22 , 130 , 0 , Black<br />
Lcd_draw 74 , 136 , 74 , 138 , 0 , Black<br />
Lcd_draw 0 , 167 , 132 , 167 , 0 , Black<br />
End If<br />
End If<br />
End If<br />
End If<br />
If Modus <> 4 Then 'Nur wenn nicht geloggt wird<br />
If U <> 0 Then 'Nur wenn auch schon eine Spannung übertragen wurde<br />
If Ta <> 0 Then<br />
Idummy = U 'Nur wenn auch schon ein Ta übertragen wurde<br />
If Idummy > Umax Then Umax = Idummy<br />
If Idummy < Umin Then Umin = Idummy<br />
Idummy = I<br />
If Idummy > Imax Then Imax = Idummy<br />
If Idummy < Imin Then Imin = Idummy<br />
Idummy = Kmh<br />
If Idummy > Kmhmax Then Kmhmax = Idummy<br />
If Idummy < Kmhmin Then Kmhmin = Idummy<br />
Bdummy = Ta<br />
If Bdummy > Tamax Then Tamax = Bdummy<br />
Idummy = Ml<br />
If Idummy > Mlmax Then Mlmax = Idummy<br />
If Idummy < Mlmin Then Mlmin = Idummy<br />
Idummy = Mr<br />
If Idummy > Mrmax Then Mrmax = Idummy<br />
If Idummy < Mrmin Then Mrmin = Idummy<br />
End If<br />
End If<br />
End If<br />
<br />
<br />
Select Case Modus<br />
Case 0<br />
If Dateiaktuell = 1 Then<br />
If Porte.7 = 0 Then Activate_sd<br />
Close #2<br />
Dateiaktuell = 0<br />
End If<br />
If Porte.7 = 1 Then Activate_display 'Standart-Anzeige<br />
If Pind.0 = 0 Then<br />
Waitms 3<br />
If Pind.0 = 0 Then<br />
While Pind.0 = 0<br />
Wend<br />
Sdummy = Meter / 1000<br />
Sdummy = Sdummy + Kilometer<br />
Startkilometer = Sdummy<br />
Writeeeprom Startkilometer , 0<br />
End If<br />
End If<br />
'Spannung und Strom<br />
Sdummy = U / 100<br />
Utext = Fusing(sdummy , "#.#")<br />
Utext = Utext + "V"<br />
Utext = " " + Utext<br />
Sdummy = I / 100<br />
Itext = Fusing(sdummy , "#.#")<br />
Itext = Itext + "A "<br />
L1 = Len(utext)<br />
L2 = Len(itext)<br />
L1 = L1 + L2<br />
L2 = 22 - L1<br />
Ltext = String(l2 , 32)<br />
Text = Utext + Ltext<br />
Text = Text + Itext<br />
Lcd_print Text , 0 , 75 , 1 , 1 , 1 , Black , White<br />
'Akkuprozente<br />
Sdummy = Akkuprozente / 10<br />
Sdummy = 100 - Sdummy<br />
Text = Fusing(sdummy , "#.#" )<br />
Text = Text + "% "<br />
Text = " " + Text<br />
Farbe = Red<br />
If Sdummy > 33 Then Farbe = Yellow<br />
If Sdummy > 66 Then Farbe = Green<br />
Sdummy = Sdummy * 1.14<br />
X2 = Sdummy<br />
X2 = X2 + 10<br />
X1 = X2 + 1<br />
Lcd_box X1 , 85 , 123 , 94 , White<br />
Lcd_box 9 , 85 , X2 , 94 , Farbe<br />
L1 = Len(text)<br />
L1 = L1 * 5<br />
L1 = L1 / 2<br />
X1 = 66 - L1<br />
Lcd_print Text , X1 , 98 , 1 , 1 , 1 , Black , White<br />
'km/h<br />
Sdummy = Kmh / 10<br />
Text = Fusing(sdummy , "#.#")<br />
Text = Text + "km/h "<br />
Text = " " + Text<br />
L1 = Len(text)<br />
Text = Text + " "<br />
L1 = L1 * 4<br />
X1 = 66 - L1<br />
Lcd_print Text , X1 , 12 , 2 , 1 , 2 , Black , White<br />
'km<br />
Sdummy = Meter / 1000<br />
Sdummy = Sdummy + Kilometer<br />
Text = Fusing(sdummy , "#.#")<br />
Text = Text + "km "<br />
Text = " " + Text<br />
L1 = Len(text)<br />
L1 = L1 * 5<br />
L1 = L1 / 2<br />
X1 = 66 - L1<br />
Lcd_print Text , X1 , 46 , 1 , 1 , 1 , Black , White<br />
'Tageskilometerzähler<br />
Sdummy = Sdummy - Startkilometer<br />
Text = Fusing(sdummy , "#.###")<br />
Text = Text + "km "<br />
Text = " " + Text<br />
L1 = Len(text)<br />
L1 = L1 * 5<br />
L1 = L1 / 2<br />
X1 = 66 - L1<br />
Lcd_print Text , X1 , 60 , 1 , 1 , 1 , Black , White<br />
'Ta<br />
Text = Str(ta)<br />
Lcd_print Text , 0 , 168 , 1 , 1 , 1 , White , Black<br />
'Motorleistung<br />
Utext = Str(ml)<br />
Utext = Utext + " "<br />
Utext = " " + Utext<br />
Itext = Str(mr)<br />
Itext = Itext + " "<br />
L1 = Len(utext)<br />
L2 = Len(itext)<br />
L1 = L1 + L2<br />
L2 = 19 - L1<br />
Ltext = String(l2 , 32)<br />
Text = Utext + Ltext<br />
Text = Text + Itext<br />
Lcd_print Text , 18 , 168 , 1 , 1 , 1 , White , Black<br />
If Antriebaus = 1 Then<br />
Sdummy = Null_x<br />
Sdummy = Sdummy - Xoffset<br />
Sdummy = Sdummy / 50<br />
If Sdummy > 49 Then Sdummy = 49<br />
If Sdummy < -49 Then Sdummy = -49<br />
Sdummy = Sdummy + 74<br />
X1 = Int(sdummy)<br />
Lcd_draw Xa , 126 , Xa , 134 , 0 , White<br />
Lcd_draw X1 , 126 , X1 , 134 , 0 , Black<br />
Xa = X1<br />
Sdummy = Null_y<br />
Sdummy = Sdummy - Yoffset<br />
Sdummy = Sdummy / 50<br />
If Sdummy > 29 Then Sdummy = 29<br />
If Sdummy < -29 Then Sdummy = -29<br />
Sdummy = Sdummy + 130<br />
Y1 = Int(sdummy)<br />
Lcd_draw 9 , Ya , 18 , Ya , 0 , White<br />
Lcd_draw 9 , Y1 , 18 , Y1 , 0 , Black<br />
Ya = Y1<br />
Else<br />
Sdummy = Mit_acc_x<br />
Sdummy = Sdummy / 50<br />
If Sdummy > 49 Then Sdummy = 49<br />
If Sdummy < -49 Then Sdummy = -49<br />
Sdummy = Sdummy + 74<br />
X1 = Int(sdummy)<br />
Lcd_draw Xa , 126 , Xa , 134 , 0 , White<br />
Lcd_draw X1 , 126 , X1 , 134 , 0 , Black<br />
Xa = X1<br />
Sdummy = Mit_acc_y<br />
Sdummy = Sdummy / 50<br />
If Sdummy > 29 Then Sdummy = 29<br />
If Sdummy < -29 Then Sdummy = -29<br />
Sdummy = Sdummy + 130<br />
Y1 = Int(sdummy)<br />
Lcd_draw 9 , Ya , 18 , Ya , 0 , White<br />
Lcd_draw 9 , Y1 , 18 , Y1 , 0 , Black<br />
Ya = Y1<br />
End If<br />
Case 1 'Details<br />
If Dateiaktuell = 1 Then<br />
If Porte.7 = 0 Then Activate_sd<br />
Close #2<br />
Dateiaktuell = 0<br />
End If<br />
If Porte.7 = 1 Then Activate_display<br />
If Pind.0 = 0 Then<br />
Waitms 3<br />
If Pind.0 = 0 Then<br />
While Pind.0 = 0<br />
Wend<br />
If Antriebaus = 1 Then<br />
Yoffset = Null_y<br />
Xoffset = Null_x<br />
<br />
Writeeeprom Xoffset , 4<br />
Writeeeprom Yoffset , 8<br />
End If<br />
End If<br />
End If<br />
Sdummy = U / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " U= " + Text<br />
Text = Text + "V"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 9 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = I / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " I= " + Text<br />
Text = Text + "A"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = Kmh / 10<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " V= " + Text<br />
Text = Text + "km/h"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 27 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = Meter / 1000<br />
Sdummy = Sdummy + Kilometer<br />
Text = Fusing(sdummy , "#.###")<br />
Text = " S= " + Text<br />
Text = Text + "km "<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = Ml<br />
Text = Str(ml )<br />
Text = " Pl= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 45 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = Mr<br />
Text = Str(mr )<br />
Text = " Pr= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 54 , 1 , 1 , 1 , Black , White<br />
<br />
Sdummy = Akkuprozente / 10<br />
Sdummy = 100 - Sdummy<br />
Text = Fusing(sdummy , "#.#")<br />
Text = "Akku= " + Text<br />
Text = Text + "%"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 63 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(mit_acc_x)<br />
Text = "Roll= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 72 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(mit_acc_y )<br />
Text = "Nick= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 81 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(null_x )<br />
Text = " R0= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 90 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(null_y )<br />
Text = " N0= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 99 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Fusing(stellwert , "#.###")<br />
Text = " SW= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 108 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(gyro_nick )<br />
Text = " GN= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 117 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(ta )<br />
Text = " TA= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 126 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(k_sum)<br />
Text = "Ksum= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 135 , 1 , 1 , 1 , Black , White<br />
<br />
<br />
<br />
Case 2 'minmax<br />
<br />
If Dateiaktuell = 1 Then<br />
If Porte.7 = 0 Then Activate_sd<br />
Close #2<br />
Dateiaktuell = 0<br />
End If<br />
If Porte.7 = 1 Then Activate_display<br />
If Pind.0 = 0 Then<br />
Waitms 3<br />
If Pind.0 = 0 Then<br />
While Pind.0 = 0<br />
Wend<br />
Minmax 'Min-Maxwerte auf 0 setzen<br />
End If<br />
End If<br />
Sdummy = Umin / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Umin= " + Text<br />
Text = Text + "V"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 9 , 1 , 1 , 1 , Black , White<br />
Sdummy = Umax / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Umax= " + Text<br />
Text = Text + "V"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
Sdummy = Imin / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Imin= " + Text<br />
Text = Text + "A"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 27 , 1 , 1 , 1 , Black , White<br />
Sdummy = Imax / 100<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Imax= " + Text<br />
Text = Text + "A"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
Sdummy = Kmhmin / 10<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Vmin= " + Text<br />
Text = Text + "km/h"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 45 , 1 , 1 , 1 , Black , White<br />
Sdummy = Kmhmax / 10<br />
Text = Fusing(sdummy , "#.#")<br />
Text = " Vmax= " + Text<br />
Text = Text + "km/h"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 54 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
<br />
<br />
Text = Str(mlmin )<br />
Text = " Plmin= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 63 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(mlmax )<br />
Text = " Plmax= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 72 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
<br />
Text = Str(mlmin )<br />
Text = " Prmin= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 81 , 1 , 1 , 1 , Black , White<br />
<br />
Text = Str(mrmax )<br />
Text = " Prmax= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 90 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
<br />
<br />
Text = Str(tamax )<br />
Text = " TAmax= " + Text<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 99 , 1 , 1 , 1 , Black , White<br />
<br />
Case 3<br />
If Dateiaktuell = 1 Then<br />
If Porte.7 = 0 Then Activate_sd<br />
Close #2<br />
Dateiaktuell = 0<br />
End If<br />
If Porte.7 = 1 Then Activate_display<br />
<br />
<br />
<br />
If Pind.4 = 0 Then<br />
Waitms 3<br />
If Pind.4 = 0 Then<br />
While Pind.4 = 0<br />
Wend<br />
If Editzeile > 1 Then Decr Editzeile<br />
End If<br />
End If<br />
<br />
<br />
<br />
<br />
If Pind.7 = 0 Then<br />
Waitms 3<br />
If Pind.7 = 0 Then<br />
While Pind.7 = 0<br />
Wend<br />
If Editzeile < 7 Then Incr Editzeile<br />
End If<br />
End If<br />
<br />
<br />
If Pind.5 = 0 Then<br />
Waitms 3<br />
If Pind.5 = 0 Then<br />
While Pind.5 = 0<br />
Wend<br />
Select Case Editzeile<br />
Case 1<br />
Decr Pfaktor<br />
Case 2<br />
Decr Ifaktor<br />
Case 3<br />
Decr Dfaktor<br />
Case 4<br />
Decr Mpfaktor<br />
Case 5<br />
Decr Mvfaktor<br />
Case 6<br />
Decr Mplfaktor<br />
Case 7<br />
Decr Mvlfaktor<br />
End Select<br />
End If<br />
End If<br />
<br />
<br />
If Pind.6 = 0 Then<br />
Waitms 3<br />
If Pind.6 = 0 Then<br />
While Pind.6 = 0<br />
Wend<br />
Select Case Editzeile<br />
Case 1<br />
Incr Pfaktor<br />
Case 2<br />
Incr Ifaktor<br />
Case 3<br />
Incr Dfaktor<br />
Case 4<br />
Incr Mpfaktor<br />
Case 5<br />
Incr Mvfaktor<br />
Case 6<br />
Incr Mplfaktor<br />
Case 7<br />
Incr Mvlfaktor<br />
End Select<br />
End If<br />
End If<br />
<br />
If Pind.0 = 0 Then<br />
Waitms 3<br />
If Pind.0 = 0 Then<br />
While Pind.0 = 0<br />
Wend<br />
P_faktor = Pfaktor<br />
P_faktor = P_faktor / 10000<br />
<br />
I_faktor = Ifaktor<br />
I_faktor = I_faktor / 1000000<br />
<br />
D_faktor = Dfaktor<br />
D_faktor = D_faktor / 1000<br />
<br />
Mp_faktor = Mpfaktor<br />
Mp_faktor = Mp_faktor / 10000<br />
<br />
Mv_faktor = Mvfaktor<br />
Mv_faktor = Mv_faktor / 1000<br />
<br />
Mpl_faktor = Mplfaktor<br />
Mpl_faktor = Mpl_faktor / 10000<br />
<br />
Mvl_faktor = Mvlfaktor<br />
Mvl_faktor = Mvl_faktor / 1000<br />
<br />
Sichern = 1<br />
Lcd_cls<br />
Lcd_print Titel , 0 , 0 , 1 , 1 , 1 , Yellow , Blue<br />
Wait 2<br />
End If<br />
End If<br />
<br />
<br />
<br />
Text = " Regelparameter:"<br />
Text = Trimtext(text)<br />
Lcd_print Text , 0 , 18 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
<br />
<br />
<br />
Text = Str(pfaktor)<br />
Text = " P = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 1 Then<br />
Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 36 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
Text = Str(ifaktor)<br />
Text = " I = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 2 Then<br />
Lcd_print Text , 0 , 46 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 46 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
Text = Str(dfaktor)<br />
Text = " D = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 3 Then<br />
Lcd_print Text , 0 , 56 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 56 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
<br />
Text = Str(mpfaktor)<br />
Text = " MP = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 4 Then<br />
Lcd_print Text , 0 , 66 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 66 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
Text = Str(mvfaktor)<br />
Text = " MV = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 5 Then<br />
Lcd_print Text , 0 , 76 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 76 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
Text = Str(mplfaktor)<br />
Text = " MPL = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 6 Then<br />
Lcd_print Text , 0 , 86 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 86 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
<br />
Text = Str(mvlfaktor)<br />
Text = " MVL = " + Text<br />
Text = Trimtext(text)<br />
If Editzeile = 7 Then<br />
Lcd_print Text , 0 , 96 , 1 , 1 , 1 , Black , Green<br />
'**************************************************<br />
Else<br />
Lcd_print Text , 0 , 96 , 1 , 1 , 1 , Black , White<br />
'**************************************************<br />
End If<br />
<br />
If Transferok = 1 Then<br />
Lcd_print " Transfer OK" , 0 , 106 , 1 , 1 , 1 , Black , White<br />
Transferok = 0<br />
End If<br />
<br />
<br />
Case 4<br />
If Porte.7 = 0 Then Activate_sd<br />
If Antriebaus = 0 Then 'Motoren laufen ->Werte Loggen<br />
If Dateiaktuell = 0 Then 'Keine Datei geöffnet<br />
<br />
Lname = 1<br />
Dateilaenge = 1 'Nächste Schleife einmal erzwingen<br />
While Dateilaenge > 0<br />
Dateiname = Str(lname)<br />
Dateiname = Dateiname + ".log"<br />
'0 voranstellen, damit sich die Dateien besser sortieren lassen.<br />
While Len(dateiname) < 12<br />
Dateiname = "0" + Dateiname<br />
Wend<br />
Dateilaenge = Filelen(dateiname)<br />
<br />
Incr Lname<br />
Wend<br />
If Porte.7 = 1 Then Activate_display<br />
Lcd_print Dateiname , 25 , 75 , 1 , 1 , 1 , Black , White<br />
If Porte.7 = 0 Then Activate_sd<br />
Dateiaktuell = 1<br />
Loopcount = 0<br />
_sec = 0<br />
_min = 0<br />
_hour = 0<br />
Zeit = "00:00:00"<br />
Open Dateiname For Append As #2<br />
Logtext = "Zeit;Loopcount;U;I;Nick;GyroNick;Stellwert;Roll;Pl;Pr;Ksum;V"<br />
Print #2 , Logtext<br />
End If<br />
<br />
If Loopcount <> Aloopcount Then<br />
Ulog = U / 100<br />
Ilog = I / 100<br />
Kmhlog = Kmh / 10<br />
Logtext = Zeit<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(loopcount)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Fusing(ulog , "#.#")<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Fusing(ilog , "#.#")<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(mit_acc_y)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(gyro_nick)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Fusing(stellwert , "#.###")<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(mit_acc_x)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(ml)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Str(mr)<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Fusing(k_sum , "#.##")<br />
Logtext = Logtext + ";"<br />
Logtext = Logtext + Fusing(kmhlog , "#.#")<br />
<br />
Print #2 , Logtext<br />
<br />
Aloopcount = Loopcount<br />
End If<br />
<br />
<br />
Else<br />
<br />
Close #2<br />
Dateiaktuell = 0<br />
<br />
<br />
End If<br />
<br />
<br />
End Select<br />
<br />
Loop<br />
<br />
<br />
<br />
'********************************************************************************************<br />
Datenempfang:<br />
$asm<br />
PUSH R24;<br />
IN R24, SREG;<br />
PUSH R24;<br />
LDS R24,{EP1}<br />
STS {EP0},R24<br />
LDS R24,{EP2}<br />
STS {EP1},R24<br />
LDS R24,{EP3}<br />
STS {EP2},R24<br />
LDS R24,{EP4}<br />
STS {EP3},R24<br />
LDS R24,{EP5}<br />
STS {EP4},R24<br />
IN R24,UDR1<br />
STs {EP5},R24<br />
POP R24;<br />
Out Sreg , R24;<br />
POP R24;<br />
$end Asm<br />
'<Serielle Telegramme abarbeiten><br />
If Ep0 = 13 Then<br />
If Ep5 = 13 Then<br />
'Disable Urxc1<br />
$asm<br />
lds R24,{EP1}<br />
LDs R25,{EP2}<br />
add R24,R25<br />
LDs R25,{EP3}<br />
add R24,R25<br />
STS {Bdummy},R24<br />
$end Asm<br />
If Bdummy = Ep4 Then 'Die Prüfsumme stimmt<br />
Select Case Index<br />
Case 1 'Spannung<br />
U = Iwert<br />
<br />
Case 2 'Strom<br />
I = Iwert<br />
Case 3 'km/h<br />
Kmh = Iwert<br />
Case 4 'Ta und Antriebaus<br />
Antriebaus = Ep2<br />
Ta = Ep3<br />
Case 5 'Akkuprozente<br />
Akkuprozente = Iwert<br />
Case 6 'Kilometer<br />
Kilometer = Wwert<br />
Case 7 'Meter<br />
Meter = Iwert<br />
Case 8<br />
Maccx1 = Ep2<br />
Maccx2 = Ep3<br />
Case 9<br />
Maccx3 = Ep2<br />
Maccx4 = Ep3<br />
Mit_acc_x = Maccx<br />
Case 10<br />
Maccy1 = Ep2<br />
Maccy2 = Ep3<br />
Case 11<br />
Maccy3 = Ep2<br />
Maccy4 = Ep3<br />
Mit_acc_y = Maccy<br />
Case 12<br />
Nullx1 = Ep2<br />
Nullx2 = Ep3<br />
Case 13<br />
Nullx3 = Ep2<br />
Nullx4 = Ep3<br />
Null_x = Nullx<br />
Case 14<br />
Nully1 = Ep2<br />
Nully2 = Ep3<br />
Case 15<br />
Nully3 = Ep2<br />
Nully4 = Ep3<br />
Null_y = Nully<br />
Case 16<br />
Sw1 = Ep2<br />
Sw2 = Ep3<br />
Case 17<br />
Sw3 = Ep2<br />
Sw4 = Ep3<br />
Stellwert = Sw<br />
Case 18<br />
Gyronick1 = Ep2<br />
Gyronick2 = Ep3<br />
Case 19<br />
Gyronick3 = Ep2<br />
Gyronick4 = Ep3<br />
Gyro_nick = Gyronick<br />
Case 20<br />
Kksum1 = Ep2<br />
Kksum2 = Ep3<br />
Case 21<br />
Kksum3 = Ep2<br />
Kksum4 = Ep3<br />
K_sum = Kksum<br />
Case 255<br />
If Sichern = 1 Then<br />
$asm<br />
lds R24,{P_f1}<br />
LDs R25,{P_f2}<br />
add R24,R25<br />
LDs R25,{P_f3}<br />
add R24,R25<br />
LDs R25,{P_f4}<br />
add R24,R25<br />
LDs R25,{I_f1}<br />
add R24,R25<br />
LDs R25,{I_f2}<br />
add R24,R25<br />
LDs R25,{I_f3}<br />
add R24,R25<br />
LDs R25,{I_f4}<br />
add R24,R25<br />
LDs R25,{D_f1}<br />
add R24,R25<br />
LDs R25,{D_f2}<br />
add R24,R25<br />
LDs R25,{D_f3}<br />
add R24,R25<br />
LDs R25,{D_f4}<br />
add R24,R25<br />
LDs R25,{Mp_f1}<br />
add R24,R25<br />
LDs R25,{Mp_f2}<br />
add R24,R25<br />
LDs R25,{Mp_f3}<br />
add R24,R25<br />
LDs R25,{Mp_f4}<br />
add R24,R25<br />
<br />
LDs R25,{Mv_f1}<br />
add R24,R25<br />
LDs R25,{Mv_f2}<br />
add R24,R25<br />
LDs R25,{Mv_f3}<br />
add R24,R25<br />
LDs R25,{Mv_f4}<br />
add R24,R25<br />
<br />
LDs R25,{Mpl_f1}<br />
add R24,R25<br />
LDs R25,{Mpl_f2}<br />
add R24,R25<br />
LDs R25,{Mpl_f3}<br />
add R24,R25<br />
LDs R25,{Mpl_f4}<br />
add R24,R25<br />
<br />
LDs R25,{Mvl_f1}<br />
add R24,R25<br />
LDs R25,{Mvl_f2}<br />
add R24,R25<br />
LDs R25,{Mvl_f3}<br />
add R24,R25<br />
LDs R25,{Mvl_f4}<br />
add R24,R25<br />
<br />
STS {Bdummy},R24<br />
$end Asm<br />
Open "COM2:" For Binary As #1<br />
Print #1 , Chr(p_f1) ; Chr(p_f2) ; Chr(p_f3) ; Chr(p_f4) ;<br />
Print #1 , Chr(i_f1) ; Chr(i_f2) ; Chr(i_f3) ; Chr(i_f4) ;<br />
Print #1 , Chr(d_f1) ; Chr(d_f2) ; Chr(d_f3) ; Chr(d_f4) ;<br />
Print #1 , Chr(mp_f1) ; Chr(mp_f2) ; Chr(mp_f3) ; Chr(mp_f4) ;<br />
Print #1 , Chr(mv_f1) ; Chr(mv_f2) ; Chr(mv_f3) ; Chr(mv_f4) ;<br />
Print #1 , Chr(mpl_f1) ; Chr(mpl_f2) ; Chr(mpl_f3) ; Chr(mpl_f4) ;<br />
Print #1 , Chr(mvl_f1) ; Chr(mvl_f2) ; Chr(mvl_f3) ; Chr(mvl_f4) ;<br />
<br />
Print #1 , Chr(bdummy) ; Chr(13) ;<br />
Close #1<br />
Transferok = 1<br />
Sichern = 0<br />
End If<br />
Case 76 'Linker Motor<br />
Ml = Ep3<br />
If Ep2 = 0 Then Ml = Ml * -1<br />
Incr Loopcount<br />
Case 82 'Rechter Motor<br />
Mr = Ep3<br />
If Ep2 = 0 Then Mr = Mr * -1<br />
<br />
End Select<br />
<br />
If Modus < 3 Then<br />
Select Case Index<br />
Case 22<br />
P_f1 = Ep2<br />
P_f2 = Ep3<br />
Case 23<br />
P_f3 = Ep2<br />
P_f4 = Ep3<br />
Case 24<br />
I_f1 = Ep2<br />
I_f2 = Ep3<br />
Case 25<br />
I_f3 = Ep2<br />
I_f4 = Ep3<br />
Case 26<br />
D_f1 = Ep2<br />
D_f2 = Ep3<br />
Case 27<br />
D_f3 = Ep2<br />
D_f4 = Ep3<br />
Case 28<br />
Mp_f1 = Ep2<br />
Mp_f2 = Ep3<br />
Case 29<br />
Mp_f3 = Ep2<br />
Mp_f4 = Ep3<br />
<br />
Case 30<br />
Mv_f1 = Ep2<br />
Mv_f2 = Ep3<br />
Case 31<br />
Mv_f3 = Ep2<br />
Mv_f4 = Ep3<br />
<br />
Case 32<br />
Mpl_f1 = Ep2<br />
Mpl_f2 = Ep3<br />
Case 33<br />
Mpl_f3 = Ep2<br />
Mpl_f4 = Ep3<br />
<br />
Case 34<br />
Mvl_f1 = Ep2<br />
Mvl_f2 = Ep3<br />
Case 35<br />
Mvl_f3 = Ep2<br />
Mvl_f4 = Ep3<br />
<br />
<br />
<br />
<br />
<br />
<br />
<br />
End Select<br />
End If<br />
End If<br />
'Enable Urxc1<br />
End If<br />
End If<br />
'</Serielle Telegramme abarbeiten><br />
Return<br />
'********************************************************************************************<br />
<br />
<br />
Sub Activate_display<br />
Reset Porte.7 'remove SD Card from bus, need to be "Reset PortF.7" at board D071x<br />
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = Low , Phase = 0 , Clockrate = 4 , Noss = 1 'different to what the SD card needs<br />
Set Spsr.spi2x 'hidden parameter: doubles the speed of the SPI output<br />
Spiinit<br />
<br />
End Sub<br />
<br />
<br />
<br />
Sub Activate_sd<br />
Set Lcd_port.lcd_cs 'Deactivate Display<br />
Config Spi = Hard , Interrupt = Off , Data Order = Msb , Master = Yes , Polarity = High , Phase = 1 , Clockrate = 4 , Noss = 1 'different to what the display needs<br />
Reset Spsr.spi2x 'no double speed. You may remove this line to try out with your card. It may work.<br />
Spiinit<br />
Set Porte.7 'connects SD Card to bus, need to be "Set PortF.7" at board D071x<br />
End Sub<br />
<br />
Function Trimtext(t As String) As String<br />
If Len(t) > 22 Then T = Left(t , 22)<br />
While Len(t) < 22<br />
T = T + " "<br />
Wend<br />
End Function<br />
<br />
Sub Minmax<br />
Umin = 10000<br />
Umax = -10000<br />
Imin = 0<br />
Imax = 0<br />
Kmhmin = 0<br />
Kmhmax = 0<br />
Mlmax = 0<br />
Mlmin = 0<br />
Mrmax = 0<br />
Mrmin = 0<br />
Tamax = 0<br />
End Sub<br />
<br />
<br />
<br />
<br />
<br />
<br />
Tick:<br />
Incr _sec<br />
If _sec > 59 Then<br />
_sec = 0<br />
Incr _min<br />
End If<br />
If _min > 59 Then<br />
_min = 0<br />
Incr _hour<br />
End If<br />
Zeit = Time$<br />
Return<br />
Getdatetime:<br />
<br />
Return<br />
<br />
<br />
<br />
$include "Glcd21_display3000.bas"<br />
$include "Glcd21_fonts.bas"<br />
'Dummy Data um Fehlermeldungen bei der Kompilierung der Standardroutinen zu vermeiden<br />
'Die Tabelle wird dann bei Nutzung eines indizierten Grafikdatei mit "echten" Daten ausgetauscht<br />
Colortable:<br />
Data 0<br />
</pre><br />
<br />
==Akkuladestecker==<br />
Um die 4 12V Akkus zu laden wird ein spezieller Stecker verwendet. Durch diesen werden die 4 Akkus paralell geschaltet und können danach mit einem normalen KFZ-Ladegerät geladen werden. Für den Fahrbetrieb wird der Ladestecker abgezogen und der Fahrstecker gesteckt. Dadurch werden 3 der Akkus in Reihe geschaltet für die Versorgung der Motoren mit 36V.<br />
Einer der Akkus bleibt alleine, nur am Minuspol mit den anderen verbunden. Aus diesem Akku werden die 5V für die Steuerung gewonnen. Ein extra Akku nur für die 5V-Seite wurde vor allem aus Angst vor EMV-Problemen gewählt. Auserdem war aus Symetriegründen sowiso noch Platz für diesen Akku.<br />
<br />
=Mechanik=<br />
Wie oben erwähnt musste die Mechanik mehrere Kriterien erfüllen. Zum einen sollte fast nichts hinter den Rädern hervorstehen, zum anderen sollte alles noch mit den vorhandenen Werkzeugen herstellbar sein. Das gerade letzteres bei jedem anders ist, wird sich jeder seinen eigenen mechanischen Aufbau konstruieren müssen. Ein Styropormodell oder ein 3D-Modell im Rechner sollte man auf jeden Fall erstellen bevor man sich Teile zusammenschweisst, die hinterher in keine Mülltonne passen. Unten gezeigte Lösung muss noch lange nicht das beste sein. Sie stellt nur den idealen Kompromiss zwischen den von mir aufgestellten Anforderungen und meinem vorhandenen Maschinenpark dar. <br />
<br />
<gallery><br />
Image:Rutscherle2_6.png|3D-Modell<br />
Image:Rutscherle2_7.JPG|Innenansicht<br />
Image:Rutscherle2_8.JPG|Innenansicht<br />
Image:Rutscherle2_9.JPG|Innenansicht<br />
Image:Rutscherle2_10.JPG|Innenansicht<br />
Image:Rutscherle2_11.JPG|von unten<br />
Image:Kotflügel.jpg|Kotflügel aus PE<br />
</gallery><br />
<br />
Weitere Bilder folgen.<br />
<br />
==Motorumbau==<br />
<br />
<div style="margin:1em; padding:1em; border:solid 2px #FF0040; background-color:#FFFFFF"><br />
''Achtung! Bauen Sie sich zum Zerlegen der Motoren unbedingt eine Hilfsvorrichtung. Vor allem beim Zusammenbauen wird das Blechpaket mit der Wicklung derart stark von den Magneten in den Läufer hineingezogen, daß es im ungünstigen Fall einen oder mehrere Finger abtrennen könnte. Auch der Motor kann beschädigt werden wenn die Teile plötzlich zusammenpatschen.''<br />
</div><br />
<br />
Die verwendeten Motoren können im Anlieferzustand nicht verwendet werden. Mit den 3 verbauten Hallsensoren ist nur eine normale Blockkommutierung möglich. Diese hat jedoch den Nachteil, daß im Moment des Kommutierens das Drehmoment stark einbricht. Beim Anfahren gegen ein kleines Hindernis hat das den Effekt, daß der Motor immer wenn er Kommutieren sollte wieder leicht zurückrollt und dadurch erneut kommutieren muss. Das Ergebnis ist ein Quitschen ohne nennenswertes Drehmoment. Als Abhilfe werden drei weitere Halsensoren verbaut, die genau die Zwischenpositionen der Bisherigen erfassen. Die drei Sensoren werden mit einer kleinen Platine im Motor zu einem Signal zusammengefasst. Es gibt jetzt nicht nur 6 Positionen pro elektrischer Umdrehung sondern 12. (30° el.) Dadurch kann der Motor mit einer Sinusspannung angesteuert werden. Der Drehmomentripple ist soweit reduziert, daß er sich nicht mehr negativ auswirkt. Als netter Nebeneffekt wird der Motor auch noch deutlich leiser. <br />
<gallery><br />
Image:Sinus_1.PNG|Theoretisch mögliche Spannungsvorgabe<br />
Image:Sinus_2.PNG|Praxistaugliche Spannungsvorgabe<br />
</gallery><br />
In den beiden Grafiken ist die Spannungsvorgabe an den Motor dargestellt. X-Achse sind die 12 Positionen pro elektrischer Umdrehung, Y-Achse die Spannung in Prozent. <br />
Wenn jetzt zum Beispiel die 4 Sensorsignale besagen, daß der Motor in Position 7 steht, dann werden die einzelnen Wicklungen wie folgt versorgt:<br />
<br />
Blau=100% von der PWM-Vorgabe<br />
<br />
Lila=37% von der PWM-Vorgabe<br />
<br />
Gelb=13% von der PWM-Vorgabe<br />
<br />
<br />
Da sich der magnetische Fluss beim kommutieren jetzt nicht mehr so extem ändern muss wie bei normaler Blockkommutierung fällt auch der Drehmomenteinbruch entsprechend geringer aus.<br />
In der Praxis hat sich gezeigt, daß das Ergebnis der obigen Rechnung bei kleiner PWM-Vorgabe oft 0 ergibt. Darum wird in der Praxis die etwas eckigere Kuve verwendet.<br />
<br />
Oft wird angemerkt, daß diese Vorgehensweise sehr ungewöhnlich und nicht "Standart" sei. Macht aber nix. Es funktioniert prächtig! Ohne diesen Trick sind solche Motoren für den Zweck unbrauchbar oder nur mit Getriebe verwendbar. Ein Getriebe benötigt jedoch Platz und macht Geräusche. Auserdem sind BLDC-Motoren mit passendem Getriebe noch schwerer zu bekommen oder für Normalverdiener unbezahlbar. Drei zusätzliche Hallsensoren und etwas Hirnschmalz sind da wesentlich billiger.<br />
<br />
=Bezugsquellen=<br />
Da die Beschaffung geeigneter Motoren für einige Leser offensichtlich ein Problem darstellt möchte ich hier meine Quelle nennen. Hier soll keine Aussage über die Qualität der angebotenen Motoren getroffen werden. Die könnte von "gut" bis "bescheiden" variieren.<br />
<br />
[http://successmotor.en.made-in-china.com/product/koKmSdnxCRVB/China-Bicycle-Motor.html Yongkang Success Permanent Magnetic Motor Manufactory]<br><br />
<br />
Weitere Quellen werden hinzugefügt wenn eine erfolgreiche Bestellung gemeldet wird.<br />
<br />
<br />
<br />
[[Kategorie:Projekte]]<br />
[[Kategorie:Praxis]] <br />
[[Kategorie:Quellcode Bascom]]</div>Colindrovinhttps://rn-wissen.de/wiki/index.php?title=Bascom_und_LCD%27s&diff=19523Bascom und LCD's2012-04-30T20:22:28Z<p>Colindrovin: /* Mit Bascom, LCD’s ansteuern */</p>
<hr />
<div>== Mit Bascom, LCDs ansteuern ==<br />
<br />
===LCD===<br />
<br />
Ein LCD kann man mit wenig Aufwand an einen AVR anschließen. Ein paar Leitungen, ein kleines Programm und schon hat man eine Anzeige für den AVR.<br />
<br />
Es gibt unter den Displays zwei große Gruppen. <br />
<br />
Die einen sind die Text-Displays (können nur Text und deren Sonderzeichen darstellen), die anderen sind die Grafik-Displays.<br />
<br />
Hier geht es um Text- Displays.<br />
<br />
====Anschlüsse:====<br />
<br />
Die meisten Text-LCDs haben einen 14 poligen bzw. einen 16 poligen Anschluss. <br />
14 polig ist meist ein LCD ohne Hintergrundbeleuchtung und beim 16 poligen ist meist der Pin 15 und 16 die Beleuchtung.<br />
<br />
Die Anschlüsse vom LCD:<br />
<br />
{|{{Blauetabelle}} <br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2<br />
|Vcc<br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Kontrastspannung (0V bis 1,5V)<br />
|-<br />
|4 <br />
|RS <br />
|Register Select (Befehle/Daten)<br />
|-<br />
|5 <br />
|RW <br />
|Read/Write<br />
|-<br />
|6 <br />
|E <br />
|Enable<br />
|-<br />
|7 <br />
|DB0 <br />
|Datenbit 0<br />
|-<br />
|8 <br />
|DB1 <br />
|Datenbit 1<br />
|-<br />
|9 <br />
|DB2 <br />
|Datenbit 2<br />
|-<br />
|10 <br />
|DB3 <br />
|Datenbit 3<br />
|-<br />
|11<br />
|DB4<br />
|Datenbit 4<br />
|-<br />
|12<br />
|DB5<br />
|Datenbit 5<br />
|-<br />
|13 <br />
|DB6 <br />
|Datenbit 6<br />
|-<br />
|14 <br />
|DB7 <br />
|Datenbit 7<br />
|-<br />
|15 <br />
|Beleuchtung <br />
|GND<br />
|-<br />
|16 <br />
|Beleuchtung <br />
|5V über mindestens einen 5 Ohm Widerstand anschließen)<br />
|}<br />
<br />
<br />
<br />
In den meisten Displays wird der Controllerchip HD44780 von Hitachi eingesetzt, oder auch der kompatible Bruder SED1278 von Epson. Auch in Verbindung mit dem Chip HD44100. (Auf der Rückseite vom Display nachschauen) Für alle diese trifft das obige Anschlussbild zu.<br />
<br />
Hier ein LCD mit 16 Zeichen mal 2 Zeilen (16*2)<br />
[[Bild:LCD 16 2 Vorderseite.jpg|center]]<br />
<br />
<br />
Und davon die Rückseite, mit Chip HD44100 und HD44780<br />
[[Bild:LCD_16_2_Rückseite_kleiner.jpg|center]]<br />
<br />
<br />
<br />
<br />
Hier ein LCD mit 24 Zeichen in je 2 Zeilen<br />
[[Bild:LCD_24_2_Vorderseite_kleiner.jpg|center]]<br />
<br />
Und die Rückseite<br />
[[Bild:LCD_24_2_Rückseite_kleiner.jpg|center]]<br />
<br />
==== Anschluss ====<br />
Die Stromversorgung eines LCD sieht so aus:<br />
[[Bild:Stromversorgung.jpg|center]]<br />
<br />
<br />
<br />
Mit dieser Beschaltung kann man schon mal probieren, ob man durch verdrehen des Kontrast-Potie, dunkle Vierecke zu sehen bekommt. Wenn ja, ist bis hier her schon mal alles ok .<br />
Den Kontrast jetzt so einstellen, dass man gerade, diese dunklen Vierecke nicht mehr sieht.<br />
<br />
==== Anschlussmöglichkeiten des Displays ====<br />
<br />
Das Display besitzt neben der Stromversorgung noch die Anschlüsse: RW, RS , E und 8 Datenleitungen.<br />
<br />
Es gibt zwei Möglichkeiten, wie man die 8 Datenleitungen des Displays an den AVR anschließen kann.<br><br />
Einmal den 8-Bit Modus und einmal den 4-Bit Modus.<br />
Beim 8 Bit Modus schließt man alle 8 Datenleitungen an den AVR und kann in einem Schritt ein Zeichen (=1 Byte )in das Display übertragen.<br />
Oder man macht es im 4 Bit Modus mit nur 4 Datenleitungen und muss dafür 2*4 Bit für ein Zeichen übertragen (4 Bit = ein Nibble)<br />
<br />
Der Vorteil: <br><br />
Ich erspare mir somit 4 Leitungen des AVR’s und kann sie anderweitig nutzen.<br />
<br />
Der Nachteil:<br><br />
Ich muss für ein Zeichen nun 2*4 Bit übertragen (= langsamer)<br />
<br />
Aber da in diesem Fall die Geschwindigkeit nicht so eine große Rolle spielt und wir lieber 4 Leitungen mehr am AVR haben möchten, schließen wird das Display im 4Bit Modus an.<br />
<br />
<br />
Anschlussbelegung für das Display im 4-Bit Modus: (Als Beispiel am Port D)<br />
<br />
{|{{Blauetabelle}}<br />
|<br />
|Display <br />
|Am AVR<br />
|-<br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2 <br />
|Vcc <br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Poti (siehe oben)<br />
|-<br />
|4 <br />
|RS <br />
|PD4 am AVR<br />
|-<br />
|5 <br />
|RW <br />
|GND<br />
|-<br />
|6 <br />
|E <br />
|PD5 am AVR<br />
|-<br />
|7 <br />
|DB0 <br />
|GND<br />
|-<br />
|8 <br />
|DB1 <br />
|GND<br />
|-<br />
|9 <br />
|DB2 <br />
|GND<br />
|-<br />
|10 <br />
|DB3 <br />
|GND<br />
|-<br />
|11 <br />
|DB4 <br />
|PD0 am AVR<br />
|-<br />
|12 <br />
|DB5 <br />
|PD1 am AVR<br />
|-<br />
|13 <br />
|DB6 <br />
|PD2 am AVR<br />
|-<br />
|14 <br />
|DB7 <br />
|PD3 am AVR<br />
|-<br />
|15 <br />
|Beleu. <br />
|frei<br />
|-<br />
|16 <br />
|Beleu. <br />
|frei<br />
|}<br />
<br />
Die vier Datenleitungen vom Display, die wir nicht brauchen, legen wir auf Masse. Zu den vier Datenleitungen brauchen wir noch die Leitungen RS und E. Den Anschluss RW brauchen wir nicht und legen ihn deshalb auch auf Masse.<br />
<br />
Wir kommen somit für das Display mit 6 Datenleitungen aus, die wir alle an das Port D (vom Mega 8) anschließen.<br />
<br />
=== Das Programm für das LCD ===<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
<br />
Config Lcd = 16 * 2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
<br />
Cls<br />
Locate 1 , 1<br />
Lcd "Hallo Welt"<br />
</pre><br />
Dieses Programm gibt den Text „Hallo Welt“ auf dem Display aus.<br />
<br />
'''Erklärung:'''<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
</pre><br />
Definiert den Mega8 als Prozessor und einen 4 Mhz Quarz.<br />
<br />
<br />
<pre><br />
Config Lcd = 16 * 2<br />
</pre><br />
Definiert das LCD als 16*2 Anzeige.<br />
Sind somit zwei Zeilen mit jeweils 16 Zeichen.<br> <br />
Folgende weitere Typen von LCD’s könnte man angeben:<br />
16*1 , 16*2 , 16*4 , 20*2 , 20*4 , 40*4<br />
<br />
<br />
<pre><br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
</pre><br />
Definiert, wo das LCD an den AVR angeschlossen wird. Db4, Db5, Db6....., E , RS sind die Pins vom LCD (siehe Tabelle)<br><br />
Portd.0, Portd.1 u.s.w., sind die Ports vom Mega8 (Port D)<br><br />
Heißt also: Die Leitung Db4 vom LCD wird an den Port PD0<br />
angeschlossen (Pin 2 am Mega8)<br><br />
Mit diesem Befehl, kann man das LCD auch an andere Pins vom AVR anschließen<br />
<br />
<br />
<br />
<pre><br />
Cls<br />
Locate 1 , 1<br />
</pre><br />
Cls löscht das LCD und Locate 1,1 definiert die nächste Ausgabe mit 1.) Zeile, 1.)Position<br><br />
(Locate 2,10 wäre dann Ausgabe in Zeile 2 und an zehnter Position )<br />
<br />
<br />
<pre><br />
Lcd "Hallo Welt"<br />
</pre><br />
Mit LCD kann man nun den Text ausgeben. :-)<br />
<br />
== Sonderfall: LCDs mit mehr als 80 Zeichen ==<br />
(mehr kann der Hitachi Controller nicht verarbeiten) Dieses betrifft z.B. die Module mit 4 * 27, bzw. 4 * 40 Zeichen. Um das Problem zu lösen wurde diesen Displays eine zweite E Leitung spendiert, alle anderen Leitungen des zweiten Controllers sind parallel angeschlossen. In jedem Fall ist das Datenblatt des Herstellers zu Rate zu ziehen.<br />
In Bascom wird eine zusätzliche Bibliothek geladen um solche Displays ansprechen zu können. Dadurch ist es möglich quasi 2 Displays getrennt anzusteuern, bei einem 4 Zeilen-Display sind die beiden oberen und die zwei unteren getrennt zu selektieren.<br />
<br />
=== Das zusätzliche Programm für das LCD, bzw. die Änderungen ===<br />
<br />
<pre><br />
'Einbindung der LCD-Bibliothek für ein 2-Prozessor-Display<br />
$lib "lcd4e2.lbx"<br />
<br />
'Bascom kennt keine Display mit 27 * 4 Zeichen, daher 40 * 4 verwenden<br />
Config Lcd = 40 * 4<br />
<br />
'man achte auf die Ergänzung E2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , E2 = Portd.6 ,Rs = Portd.4<br />
<br />
' Systemvariable der LCD-Bibliothek (wichtig, bloß nicht ändern)<br />
Dim ___lcde As Byte<br />
<br />
' wählt die beiden oberen Zeilen aus<br />
___lcde = 0 <br />
<br />
' löscht die beiden oberen Zeilen<br />
Cls<br />
' wählt die obere Zeile aus<br />
Upperline<br />
' schreibt in die erste Zeile an Position 3<br />
Locate 1 , 3<br />
' den Text in Anführungszeichen<br />
Lcd "Zeile 1"<br />
' wählt die zweite Zeile aus<br />
Lowerline<br />
' schreibt in die zweite Zeile an Position 2<br />
Locate 2 , 2<br />
' in diesem Fall den Inhalt der Variablem mit dem Namen Variable<br />
Lcd Variable<br />
' unterdrückt den Cursor<br />
Cursor Off<br />
<br />
' wählt die beiden unteren Zeilen aus<br />
___lcde = 1<br />
Waitms 100<br />
Cls<br />
Thirdline<br />
Locate 1 , 1<br />
Lcd "Zeile 3"<br />
Fourthline<br />
Locate 2 , 1<br />
Lcd "Zeile 4"<br />
Cursor Off<br />
<br />
</pre><br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Bascom]]<br />
* [[LCD an RN-Control]]<br />
<br />
==Weblinks==<br />
* [http://www.sprut.de/electronic/lcd/index.htm#einleitung Sprut]<br />
<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Colindrovinhttps://rn-wissen.de/wiki/index.php?title=Bascom_und_LCD%27s&diff=19522Bascom und LCD's2012-04-30T20:21:03Z<p>Colindrovin: /* Mit Bascom, LCD-Displays ansteuern */</p>
<hr />
<div>== Mit Bascom, LCD’s ansteuern ==<br />
<br />
===LCD Display===<br />
<br />
Ein LCD kann man mit wenig Aufwand an einen AVR anschließen. Ein paar Leitungen, ein kleines Programm und schon hat man eine Anzeige für den AVR.<br />
<br />
Es gibt unter den Displays zwei große Gruppen. <br />
<br />
Die einen sind die Text-Displays (können nur Text und deren Sonderzeichen darstellen), die anderen sind die Grafik-Displays.<br />
<br />
Hier geht es um Text- Displays.<br />
<br />
====Anschlüsse:====<br />
<br />
Die meisten Text-LCD’s haben einen 14 poligen bzw. einen 16 poligen Anschluss. <br />
14 polig ist meist ein LCD ohne Hintergrundbeleuchtung und beim 16 poligen ist meist der Pin 15 und 16 die Beleuchtung.<br />
<br />
Die Anschlüsse vom LC-Display:<br />
<br />
{|{{Blauetabelle}} <br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2<br />
|Vcc<br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Kontrastspannung (0V bis 1,5V)<br />
|-<br />
|4 <br />
|RS <br />
|Register Select (Befehle/Daten)<br />
|-<br />
|5 <br />
|RW <br />
|Read/Write<br />
|-<br />
|6 <br />
|E <br />
|Enable<br />
|-<br />
|7 <br />
|DB0 <br />
|Datenbit 0<br />
|-<br />
|8 <br />
|DB1 <br />
|Datenbit 1<br />
|-<br />
|9 <br />
|DB2 <br />
|Datenbit 2<br />
|-<br />
|10 <br />
|DB3 <br />
|Datenbit 3<br />
|-<br />
|11<br />
|DB4<br />
|Datenbit 4<br />
|-<br />
|12<br />
|DB5<br />
|Datenbit 5<br />
|-<br />
|13 <br />
|DB6 <br />
|Datenbit 6<br />
|-<br />
|14 <br />
|DB7 <br />
|Datenbit 7<br />
|-<br />
|15 <br />
|Beleuchtung <br />
|GND<br />
|-<br />
|16 <br />
|Beleuchtung <br />
|5V über mindestens einen 5 Ohm Widerstand anschließen)<br />
|}<br />
<br />
<br />
<br />
In den meisten Displays wird der Controllerchip HD44780 von Hitachi eingesetzt, oder auch der kompatible Bruder SED1278 von Epson. Auch in Verbindung mit dem Chip HD44100. (Auf der Rückseite vom Display nachschauen) Für alle diese trifft das obige Anschlussbild zu.<br />
<br />
Hier ein LCD mit 16 Zeichen mal 2 Zeilen (16*2)<br />
[[Bild:LCD 16 2 Vorderseite.jpg|center]]<br />
<br />
<br />
Und davon die Rückseite, mit Chip HD44100 und HD44780<br />
[[Bild:LCD_16_2_Rückseite_kleiner.jpg|center]]<br />
<br />
<br />
<br />
<br />
Hier ein LCD mit 24 Zeichen in je 2 Zeilen<br />
[[Bild:LCD_24_2_Vorderseite_kleiner.jpg|center]]<br />
<br />
Und die Rückseite<br />
[[Bild:LCD_24_2_Rückseite_kleiner.jpg|center]]<br />
<br />
==== Anschluss ====<br />
Die Stromversorgung eines LCD sieht so aus:<br />
[[Bild:Stromversorgung.jpg|center]]<br />
<br />
<br />
<br />
Mit dieser Beschaltung kann man schon mal probieren, ob man durch verdrehen des Kontrast-Potie, dunkle Vierecke zu sehen bekommt. Wenn ja, ist bis hier her schon mal alles ok .<br />
Den Kontrast jetzt so einstellen, dass man gerade, diese dunklen Vierecke nicht mehr sieht.<br />
<br />
==== Anschlussmöglichkeiten des Displays ====<br />
<br />
Das Display besitzt neben der Stromversorgung noch die Anschlüsse: RW, RS , E und 8 Datenleitungen.<br />
<br />
Es gibt zwei Möglichkeiten, wie man die 8 Datenleitungen des Displays an den AVR anschließen kann.<br><br />
Einmal den 8-Bit Modus und einmal den 4-Bit Modus.<br />
Beim 8 Bit Modus schließt man alle 8 Datenleitungen an den AVR und kann in einem Schritt ein Zeichen (=1 Byte )in das Display übertragen.<br />
Oder man macht es im 4 Bit Modus mit nur 4 Datenleitungen und muss dafür 2*4 Bit für ein Zeichen übertragen (4 Bit = ein Nibble)<br />
<br />
Der Vorteil: <br><br />
Ich erspare mir somit 4 Leitungen des AVR’s und kann sie anderweitig nutzen.<br />
<br />
Der Nachteil:<br><br />
Ich muss für ein Zeichen nun 2*4 Bit übertragen (= langsamer)<br />
<br />
Aber da in diesem Fall die Geschwindigkeit nicht so eine große Rolle spielt und wir lieber 4 Leitungen mehr am AVR haben möchten, schließen wird das Display im 4Bit Modus an.<br />
<br />
<br />
Anschlussbelegung für das Display im 4-Bit Modus: (Als Beispiel am Port D)<br />
<br />
{|{{Blauetabelle}}<br />
|<br />
|Display <br />
|Am AVR<br />
|-<br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2 <br />
|Vcc <br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Poti (siehe oben)<br />
|-<br />
|4 <br />
|RS <br />
|PD4 am AVR<br />
|-<br />
|5 <br />
|RW <br />
|GND<br />
|-<br />
|6 <br />
|E <br />
|PD5 am AVR<br />
|-<br />
|7 <br />
|DB0 <br />
|GND<br />
|-<br />
|8 <br />
|DB1 <br />
|GND<br />
|-<br />
|9 <br />
|DB2 <br />
|GND<br />
|-<br />
|10 <br />
|DB3 <br />
|GND<br />
|-<br />
|11 <br />
|DB4 <br />
|PD0 am AVR<br />
|-<br />
|12 <br />
|DB5 <br />
|PD1 am AVR<br />
|-<br />
|13 <br />
|DB6 <br />
|PD2 am AVR<br />
|-<br />
|14 <br />
|DB7 <br />
|PD3 am AVR<br />
|-<br />
|15 <br />
|Beleu. <br />
|frei<br />
|-<br />
|16 <br />
|Beleu. <br />
|frei<br />
|}<br />
<br />
Die vier Datenleitungen vom Display, die wir nicht brauchen, legen wir auf Masse. Zu den vier Datenleitungen brauchen wir noch die Leitungen RS und E. Den Anschluss RW brauchen wir nicht und legen ihn deshalb auch auf Masse.<br />
<br />
Wir kommen somit für das Display mit 6 Datenleitungen aus, die wir alle an das Port D (vom Mega 8) anschließen.<br />
<br />
=== Das Programm für das LCD ===<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
<br />
Config Lcd = 16 * 2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
<br />
Cls<br />
Locate 1 , 1<br />
Lcd "Hallo Welt"<br />
</pre><br />
Dieses Programm gibt den Text „Hallo Welt“ auf dem Display aus.<br />
<br />
'''Erklärung:'''<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
</pre><br />
Definiert den Mega8 als Prozessor und einen 4 Mhz Quarz.<br />
<br />
<br />
<pre><br />
Config Lcd = 16 * 2<br />
</pre><br />
Definiert das LCD als 16*2 Anzeige.<br />
Sind somit zwei Zeilen mit jeweils 16 Zeichen.<br> <br />
Folgende weitere Typen von LCD’s könnte man angeben:<br />
16*1 , 16*2 , 16*4 , 20*2 , 20*4 , 40*4<br />
<br />
<br />
<pre><br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
</pre><br />
Definiert, wo das LCD an den AVR angeschlossen wird. Db4, Db5, Db6....., E , RS sind die Pins vom LCD (siehe Tabelle)<br><br />
Portd.0, Portd.1 u.s.w., sind die Ports vom Mega8 (Port D)<br><br />
Heißt also: Die Leitung Db4 vom LCD wird an den Port PD0<br />
angeschlossen (Pin 2 am Mega8)<br><br />
Mit diesem Befehl, kann man das LCD auch an andere Pins vom AVR anschließen<br />
<br />
<br />
<br />
<pre><br />
Cls<br />
Locate 1 , 1<br />
</pre><br />
Cls löscht das LCD und Locate 1,1 definiert die nächste Ausgabe mit 1.) Zeile, 1.)Position<br><br />
(Locate 2,10 wäre dann Ausgabe in Zeile 2 und an zehnter Position )<br />
<br />
<br />
<pre><br />
Lcd "Hallo Welt"<br />
</pre><br />
Mit LCD kann man nun den Text ausgeben. :-)<br />
<br />
== Sonderfall: LCDs mit mehr als 80 Zeichen ==<br />
(mehr kann der Hitachi Controller nicht verarbeiten) Dieses betrifft z.B. die Module mit 4 * 27, bzw. 4 * 40 Zeichen. Um das Problem zu lösen wurde diesen Displays eine zweite E Leitung spendiert, alle anderen Leitungen des zweiten Controllers sind parallel angeschlossen. In jedem Fall ist das Datenblatt des Herstellers zu Rate zu ziehen.<br />
In Bascom wird eine zusätzliche Bibliothek geladen um solche Displays ansprechen zu können. Dadurch ist es möglich quasi 2 Displays getrennt anzusteuern, bei einem 4 Zeilen-Display sind die beiden oberen und die zwei unteren getrennt zu selektieren.<br />
<br />
=== Das zusätzliche Programm für das LCD, bzw. die Änderungen ===<br />
<br />
<pre><br />
'Einbindung der LCD-Bibliothek für ein 2-Prozessor-Display<br />
$lib "lcd4e2.lbx"<br />
<br />
'Bascom kennt keine Display mit 27 * 4 Zeichen, daher 40 * 4 verwenden<br />
Config Lcd = 40 * 4<br />
<br />
'man achte auf die Ergänzung E2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , E2 = Portd.6 ,Rs = Portd.4<br />
<br />
' Systemvariable der LCD-Bibliothek (wichtig, bloß nicht ändern)<br />
Dim ___lcde As Byte<br />
<br />
' wählt die beiden oberen Zeilen aus<br />
___lcde = 0 <br />
<br />
' löscht die beiden oberen Zeilen<br />
Cls<br />
' wählt die obere Zeile aus<br />
Upperline<br />
' schreibt in die erste Zeile an Position 3<br />
Locate 1 , 3<br />
' den Text in Anführungszeichen<br />
Lcd "Zeile 1"<br />
' wählt die zweite Zeile aus<br />
Lowerline<br />
' schreibt in die zweite Zeile an Position 2<br />
Locate 2 , 2<br />
' in diesem Fall den Inhalt der Variablem mit dem Namen Variable<br />
Lcd Variable<br />
' unterdrückt den Cursor<br />
Cursor Off<br />
<br />
' wählt die beiden unteren Zeilen aus<br />
___lcde = 1<br />
Waitms 100<br />
Cls<br />
Thirdline<br />
Locate 1 , 1<br />
Lcd "Zeile 3"<br />
Fourthline<br />
Locate 2 , 1<br />
Lcd "Zeile 4"<br />
Cursor Off<br />
<br />
</pre><br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Bascom]]<br />
* [[LCD an RN-Control]]<br />
<br />
==Weblinks==<br />
* [http://www.sprut.de/electronic/lcd/index.htm#einleitung Sprut]<br />
<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Colindrovinhttps://rn-wissen.de/wiki/index.php?title=Bascom_und_LCD%27s&diff=19521Bascom und LCD's2012-04-24T14:45:46Z<p>Colindrovin: /* Das Programm für das LCD */</p>
<hr />
<div>== Mit Bascom, LCD-Displays ansteuern ==<br />
<br />
===LCD Display===<br />
<br />
Ein LCD-Display kann man mit wenig Aufwand an einen AVR anschließen. Ein paar Leitungen, ein kleines Programm und schon hat man eine Anzeige für den AVR.<br />
<br />
Es gibt unter den Displays zwei große Gruppen. <br />
<br />
Die einen sind die Text-Displays (können nur Text und deren Sonderzeichen darstellen), die anderen sind die Grafik-Displays.<br />
<br />
Hier geht es um Text- Displays.<br />
<br />
====Anschlüsse:====<br />
<br />
Die meisten Text-LCD’s haben einen 14 poligen bzw. einen 16 poligen Anschluss. <br />
14 polig ist meist ein LCD ohne Hintergrundbeleuchtung und beim 16 poligen ist meist der Pin 15 und 16 die Beleuchtung.<br />
<br />
Die Anschlüsse vom LC-Display:<br />
<br />
{|{{Blauetabelle}} <br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2<br />
|Vcc<br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Kontrastspannung (0V bis 1,5V)<br />
|-<br />
|4 <br />
|RS <br />
|Register Select (Befehle/Daten)<br />
|-<br />
|5 <br />
|RW <br />
|Read/Write<br />
|-<br />
|6 <br />
|E <br />
|Enable<br />
|-<br />
|7 <br />
|DB0 <br />
|Datenbit 0<br />
|-<br />
|8 <br />
|DB1 <br />
|Datenbit 1<br />
|-<br />
|9 <br />
|DB2 <br />
|Datenbit 2<br />
|-<br />
|10 <br />
|DB3 <br />
|Datenbit 3<br />
|-<br />
|11<br />
|DB4<br />
|Datenbit 4<br />
|-<br />
|12<br />
|DB5<br />
|Datenbit 5<br />
|-<br />
|13 <br />
|DB6 <br />
|Datenbit 6<br />
|-<br />
|14 <br />
|DB7 <br />
|Datenbit 7<br />
|-<br />
|15 <br />
|Beleuchtung <br />
|GND<br />
|-<br />
|16 <br />
|Beleuchtung <br />
|5V über mindestens einen 5 Ohm Widerstand anschließen)<br />
|}<br />
<br />
<br />
<br />
In den meisten Displays wird der Controllerchip HD44780 von Hitachi eingesetzt, oder auch der kompatible Bruder SED1278 von Epson. Auch in Verbindung mit dem Chip HD44100. (Auf der Rückseite vom Display nachschauen) Für alle diese trifft das obige Anschlussbild zu.<br />
<br />
Hier ein LCD mit 16 Zeichen mal 2 Zeilen (16*2)<br />
[[Bild:LCD 16 2 Vorderseite.jpg|center]]<br />
<br />
<br />
Und davon die Rückseite, mit Chip HD44100 und HD44780<br />
[[Bild:LCD_16_2_Rückseite_kleiner.jpg|center]]<br />
<br />
<br />
<br />
<br />
Hier ein LCD mit 24 Zeichen in je 2 Zeilen<br />
[[Bild:LCD_24_2_Vorderseite_kleiner.jpg|center]]<br />
<br />
Und die Rückseite<br />
[[Bild:LCD_24_2_Rückseite_kleiner.jpg|center]]<br />
<br />
==== Anschluss ====<br />
Die Stromversorgung eines LCD sieht so aus:<br />
[[Bild:Stromversorgung.jpg|center]]<br />
<br />
<br />
<br />
Mit dieser Beschaltung kann man schon mal probieren, ob man durch verdrehen des Kontrast-Potie, dunkle Vierecke zu sehen bekommt. Wenn ja, ist bis hier her schon mal alles ok .<br />
Den Kontrast jetzt so einstellen, dass man gerade, diese dunklen Vierecke nicht mehr sieht.<br />
<br />
==== Anschlussmöglichkeiten des Displays ====<br />
<br />
Das Display besitzt neben der Stromversorgung noch die Anschlüsse: RW, RS , E und 8 Datenleitungen.<br />
<br />
Es gibt zwei Möglichkeiten, wie man die 8 Datenleitungen des Displays an den AVR anschließen kann.<br><br />
Einmal den 8-Bit Modus und einmal den 4-Bit Modus.<br />
Beim 8 Bit Modus schließt man alle 8 Datenleitungen an den AVR und kann in einem Schritt ein Zeichen (=1 Byte )in das Display übertragen.<br />
Oder man macht es im 4 Bit Modus mit nur 4 Datenleitungen und muss dafür 2*4 Bit für ein Zeichen übertragen (4 Bit = ein Nibble)<br />
<br />
Der Vorteil: <br><br />
Ich erspare mir somit 4 Leitungen des AVR’s und kann sie anderweitig nutzen.<br />
<br />
Der Nachteil:<br><br />
Ich muss für ein Zeichen nun 2*4 Bit übertragen (= langsamer)<br />
<br />
Aber da in diesem Fall die Geschwindigkeit nicht so eine große Rolle spielt und wir lieber 4 Leitungen mehr am AVR haben möchten, schließen wird das Display im 4Bit Modus an.<br />
<br />
<br />
Anschlussbelegung für das Display im 4-Bit Modus: (Als Beispiel am Port D)<br />
<br />
{|{{Blauetabelle}}<br />
|<br />
|Display <br />
|Am AVR<br />
|-<br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2 <br />
|Vcc <br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Poti (siehe oben)<br />
|-<br />
|4 <br />
|RS <br />
|PD4 am AVR<br />
|-<br />
|5 <br />
|RW <br />
|GND<br />
|-<br />
|6 <br />
|E <br />
|PD5 am AVR<br />
|-<br />
|7 <br />
|DB0 <br />
|GND<br />
|-<br />
|8 <br />
|DB1 <br />
|GND<br />
|-<br />
|9 <br />
|DB2 <br />
|GND<br />
|-<br />
|10 <br />
|DB3 <br />
|GND<br />
|-<br />
|11 <br />
|DB4 <br />
|PD0 am AVR<br />
|-<br />
|12 <br />
|DB5 <br />
|PD1 am AVR<br />
|-<br />
|13 <br />
|DB6 <br />
|PD2 am AVR<br />
|-<br />
|14 <br />
|DB7 <br />
|PD3 am AVR<br />
|-<br />
|15 <br />
|Beleu. <br />
|frei<br />
|-<br />
|16 <br />
|Beleu. <br />
|frei<br />
|}<br />
<br />
Die vier Datenleitungen vom Display, die wir nicht brauchen, legen wir auf Masse. Zu den vier Datenleitungen brauchen wir noch die Leitungen RS und E. Den Anschluss RW brauchen wir nicht und legen ihn deshalb auch auf Masse.<br />
<br />
Wir kommen somit für das Display mit 6 Datenleitungen aus, die wir alle an das Port D (vom Mega 8) anschließen.<br />
<br />
=== Das Programm für das LCD ===<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
<br />
Config Lcd = 16 * 2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
<br />
Cls<br />
Locate 1 , 1<br />
Lcd "Hallo Welt"<br />
</pre><br />
Dieses Programm gibt den Text „Hallo Welt“ auf dem Display aus.<br />
<br />
'''Erklärung:'''<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
</pre><br />
Definiert den Mega8 als Prozessor und einen 4 Mhz Quarz.<br />
<br />
<br />
<pre><br />
Config Lcd = 16 * 2<br />
</pre><br />
Definiert das LCD als 16*2 Anzeige.<br />
Sind somit zwei Zeilen mit jeweils 16 Zeichen.<br> <br />
Folgende weitere Typen von LCD’s könnte man angeben:<br />
16*1 , 16*2 , 16*4 , 20*2 , 20*4 , 40*4<br />
<br />
<br />
<pre><br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
</pre><br />
Definiert, wo das LCD an den AVR angeschlossen wird. Db4, Db5, Db6....., E , RS sind die Pins vom LCD (siehe Tabelle)<br><br />
Portd.0, Portd.1 u.s.w., sind die Ports vom Mega8 (Port D)<br><br />
Heißt also: Die Leitung Db4 vom LCD wird an den Port PD0<br />
angeschlossen (Pin 2 am Mega8)<br><br />
Mit diesem Befehl, kann man das LCD auch an andere Pins vom AVR anschließen<br />
<br />
<br />
<br />
<pre><br />
Cls<br />
Locate 1 , 1<br />
</pre><br />
Cls löscht das LCD und Locate 1,1 definiert die nächste Ausgabe mit 1.) Zeile, 1.)Position<br><br />
(Locate 2,10 wäre dann Ausgabe in Zeile 2 und an zehnter Position )<br />
<br />
<br />
<pre><br />
Lcd "Hallo Welt"<br />
</pre><br />
Mit LCD kann man nun den Text ausgeben. :-)<br />
<br />
== Sonderfall: LCDs mit mehr als 80 Zeichen ==<br />
(mehr kann der Hitachi Controller nicht verarbeiten) Dieses betrifft z.B. die Module mit 4 * 27, bzw. 4 * 40 Zeichen. Um das Problem zu lösen wurde diesen Displays eine zweite E Leitung spendiert, alle anderen Leitungen des zweiten Controllers sind parallel angeschlossen. In jedem Fall ist das Datenblatt des Herstellers zu Rate zu ziehen.<br />
In Bascom wird eine zusätzliche Bibliothek geladen um solche Displays ansprechen zu können. Dadurch ist es möglich quasi 2 Displays getrennt anzusteuern, bei einem 4 Zeilen-Display sind die beiden oberen und die zwei unteren getrennt zu selektieren.<br />
<br />
=== Das zusätzliche Programm für das LCD, bzw. die Änderungen ===<br />
<br />
<pre><br />
'Einbindung der LCD-Bibliothek für ein 2-Prozessor-Display<br />
$lib "lcd4e2.lbx"<br />
<br />
'Bascom kennt keine Display mit 27 * 4 Zeichen, daher 40 * 4 verwenden<br />
Config Lcd = 40 * 4<br />
<br />
'man achte auf die Ergänzung E2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , E2 = Portd.6 ,Rs = Portd.4<br />
<br />
' Systemvariable der LCD-Bibliothek (wichtig, bloß nicht ändern)<br />
Dim ___lcde As Byte<br />
<br />
' wählt die beiden oberen Zeilen aus<br />
___lcde = 0 <br />
<br />
' löscht die beiden oberen Zeilen<br />
Cls<br />
' wählt die obere Zeile aus<br />
Upperline<br />
' schreibt in die erste Zeile an Position 3<br />
Locate 1 , 3<br />
' den Text in Anführungszeichen<br />
Lcd "Zeile 1"<br />
' wählt die zweite Zeile aus<br />
Lowerline<br />
' schreibt in die zweite Zeile an Position 2<br />
Locate 2 , 2<br />
' in diesem Fall den Inhalt der Variablem mit dem Namen Variable<br />
Lcd Variable<br />
' unterdrückt den Cursor<br />
Cursor Off<br />
<br />
' wählt die beiden unteren Zeilen aus<br />
___lcde = 1<br />
Waitms 100<br />
Cls<br />
Thirdline<br />
Locate 1 , 1<br />
Lcd "Zeile 3"<br />
Fourthline<br />
Locate 2 , 1<br />
Lcd "Zeile 4"<br />
Cursor Off<br />
<br />
</pre><br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Bascom]]<br />
* [[LCD an RN-Control]]<br />
<br />
==Weblinks==<br />
* [http://www.sprut.de/electronic/lcd/index.htm#einleitung Sprut]<br />
<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Colindrovinhttps://rn-wissen.de/wiki/index.php?title=Bascom_und_LCD%27s&diff=19520Bascom und LCD's2012-04-24T14:42:21Z<p>Colindrovin: /* Anschlüsse: */</p>
<hr />
<div>== Mit Bascom, LCD-Displays ansteuern ==<br />
<br />
===LCD Display===<br />
<br />
Ein LCD-Display kann man mit wenig Aufwand an einen AVR anschließen. Ein paar Leitungen, ein kleines Programm und schon hat man eine Anzeige für den AVR.<br />
<br />
Es gibt unter den Displays zwei große Gruppen. <br />
<br />
Die einen sind die Text-Displays (können nur Text und deren Sonderzeichen darstellen), die anderen sind die Grafik-Displays.<br />
<br />
Hier geht es um Text- Displays.<br />
<br />
====Anschlüsse:====<br />
<br />
Die meisten Text-LCD’s haben einen 14 poligen bzw. einen 16 poligen Anschluss. <br />
14 polig ist meist ein LCD ohne Hintergrundbeleuchtung und beim 16 poligen ist meist der Pin 15 und 16 die Beleuchtung.<br />
<br />
Die Anschlüsse vom LC-Display:<br />
<br />
{|{{Blauetabelle}} <br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2<br />
|Vcc<br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Kontrastspannung (0V bis 1,5V)<br />
|-<br />
|4 <br />
|RS <br />
|Register Select (Befehle/Daten)<br />
|-<br />
|5 <br />
|RW <br />
|Read/Write<br />
|-<br />
|6 <br />
|E <br />
|Enable<br />
|-<br />
|7 <br />
|DB0 <br />
|Datenbit 0<br />
|-<br />
|8 <br />
|DB1 <br />
|Datenbit 1<br />
|-<br />
|9 <br />
|DB2 <br />
|Datenbit 2<br />
|-<br />
|10 <br />
|DB3 <br />
|Datenbit 3<br />
|-<br />
|11<br />
|DB4<br />
|Datenbit 4<br />
|-<br />
|12<br />
|DB5<br />
|Datenbit 5<br />
|-<br />
|13 <br />
|DB6 <br />
|Datenbit 6<br />
|-<br />
|14 <br />
|DB7 <br />
|Datenbit 7<br />
|-<br />
|15 <br />
|Beleuchtung <br />
|GND<br />
|-<br />
|16 <br />
|Beleuchtung <br />
|5V über mindestens einen 5 Ohm Widerstand anschließen)<br />
|}<br />
<br />
<br />
<br />
In den meisten Displays wird der Controllerchip HD44780 von Hitachi eingesetzt, oder auch der kompatible Bruder SED1278 von Epson. Auch in Verbindung mit dem Chip HD44100. (Auf der Rückseite vom Display nachschauen) Für alle diese trifft das obige Anschlussbild zu.<br />
<br />
Hier ein LCD mit 16 Zeichen mal 2 Zeilen (16*2)<br />
[[Bild:LCD 16 2 Vorderseite.jpg|center]]<br />
<br />
<br />
Und davon die Rückseite, mit Chip HD44100 und HD44780<br />
[[Bild:LCD_16_2_Rückseite_kleiner.jpg|center]]<br />
<br />
<br />
<br />
<br />
Hier ein LCD mit 24 Zeichen in je 2 Zeilen<br />
[[Bild:LCD_24_2_Vorderseite_kleiner.jpg|center]]<br />
<br />
Und die Rückseite<br />
[[Bild:LCD_24_2_Rückseite_kleiner.jpg|center]]<br />
<br />
==== Anschluss ====<br />
Die Stromversorgung eines LCD sieht so aus:<br />
[[Bild:Stromversorgung.jpg|center]]<br />
<br />
<br />
<br />
Mit dieser Beschaltung kann man schon mal probieren, ob man durch verdrehen des Kontrast-Potie, dunkle Vierecke zu sehen bekommt. Wenn ja, ist bis hier her schon mal alles ok .<br />
Den Kontrast jetzt so einstellen, dass man gerade, diese dunklen Vierecke nicht mehr sieht.<br />
<br />
==== Anschlussmöglichkeiten des Displays ====<br />
<br />
Das Display besitzt neben der Stromversorgung noch die Anschlüsse: RW, RS , E und 8 Datenleitungen.<br />
<br />
Es gibt zwei Möglichkeiten, wie man die 8 Datenleitungen des Displays an den AVR anschließen kann.<br><br />
Einmal den 8-Bit Modus und einmal den 4-Bit Modus.<br />
Beim 8 Bit Modus schließt man alle 8 Datenleitungen an den AVR und kann in einem Schritt ein Zeichen (=1 Byte )in das Display übertragen.<br />
Oder man macht es im 4 Bit Modus mit nur 4 Datenleitungen und muss dafür 2*4 Bit für ein Zeichen übertragen (4 Bit = ein Nibble)<br />
<br />
Der Vorteil: <br><br />
Ich erspare mir somit 4 Leitungen des AVR’s und kann sie anderweitig nutzen.<br />
<br />
Der Nachteil:<br><br />
Ich muss für ein Zeichen nun 2*4 Bit übertragen (= langsamer)<br />
<br />
Aber da in diesem Fall die Geschwindigkeit nicht so eine große Rolle spielt und wir lieber 4 Leitungen mehr am AVR haben möchten, schließen wird das Display im 4Bit Modus an.<br />
<br />
<br />
Anschlussbelegung für das Display im 4-Bit Modus: (Als Beispiel am Port D)<br />
<br />
{|{{Blauetabelle}}<br />
|<br />
|Display <br />
|Am AVR<br />
|-<br />
|1 <br />
|Vss <br />
|GND<br />
|-<br />
|2 <br />
|Vcc <br />
|5V<br />
|-<br />
|3 <br />
|Vee <br />
|Poti (siehe oben)<br />
|-<br />
|4 <br />
|RS <br />
|PD4 am AVR<br />
|-<br />
|5 <br />
|RW <br />
|GND<br />
|-<br />
|6 <br />
|E <br />
|PD5 am AVR<br />
|-<br />
|7 <br />
|DB0 <br />
|GND<br />
|-<br />
|8 <br />
|DB1 <br />
|GND<br />
|-<br />
|9 <br />
|DB2 <br />
|GND<br />
|-<br />
|10 <br />
|DB3 <br />
|GND<br />
|-<br />
|11 <br />
|DB4 <br />
|PD0 am AVR<br />
|-<br />
|12 <br />
|DB5 <br />
|PD1 am AVR<br />
|-<br />
|13 <br />
|DB6 <br />
|PD2 am AVR<br />
|-<br />
|14 <br />
|DB7 <br />
|PD3 am AVR<br />
|-<br />
|15 <br />
|Beleu. <br />
|frei<br />
|-<br />
|16 <br />
|Beleu. <br />
|frei<br />
|}<br />
<br />
Die vier Datenleitungen vom Display, die wir nicht brauchen, legen wir auf Masse. Zu den vier Datenleitungen brauchen wir noch die Leitungen RS und E. Den Anschluss RW brauchen wir nicht und legen ihn deshalb auch auf Masse.<br />
<br />
Wir kommen somit für das Display mit 6 Datenleitungen aus, die wir alle an das Port D (vom Mega 8) anschließen.<br />
<br />
=== Das Programm für das LCD ===<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
<br />
Config Lcd = 16 * 2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
<br />
Cls<br />
Locate 1 , 1<br />
Lcd "Hallo Welt"<br />
</pre><br />
Dieses Programm gibt den Text „Hallo Welt“ auf dem Display aus.<br />
<br />
'''Erklärung:'''<br />
<pre><br />
$regfile = "m8def.dat"<br />
$crystal = 4000000<br />
</pre><br />
Definiert den Mega8 als Prozessor und einen 4 Mhz Quarz.<br />
<br />
<br />
<pre><br />
Config Lcd = 16 * 2<br />
</pre><br />
Definiert das LCD-Display als 16*2 Anzeige.<br />
Sind somit zwei Zeilen mit jeweils 16 Zeichen.<br> <br />
Folgende weitere Typen von LCD’s könnte man angeben:<br />
16*1 , 16*2 , 16*4 , 20*2 , 20*4 , 40*4<br />
<br />
<br />
<pre><br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , Rs = Portd.4<br />
</pre><br />
Definiert, wo das Display an den AVR angeschlossen wird. Db4, Db5, Db6....., E , RS sind die Pins vom LCD (siehe Tabelle)<br><br />
Portd.0, Portd.1 u.s.w., sind die Ports vom Mega8 (Port D)<br><br />
Heißt also: Die Leitung Db4 vom LCD wird an den Port PD0<br />
angeschlossen (Pin 2 am Mega8)<br><br />
Mit diesem Befehl, kann man das LCD auch an andere Pins vom AVR anschließen<br />
<br />
<br />
<br />
<pre><br />
Cls<br />
Locate 1 , 1<br />
</pre><br />
Cls löscht das LCD-Display und Locate 1,1 definiert die nächste Ausgabe mit 1.) Zeile, 1.)Position<br><br />
(Locate 2,10 wäre dann Ausgabe in Zeile 2 und an zehnter Position )<br />
<br />
<br />
<pre><br />
Lcd "Hallo Welt"<br />
</pre><br />
Mit LCD kann man nun den Text ausgeben. :-)<br />
<br />
== Sonderfall: LCDs mit mehr als 80 Zeichen ==<br />
(mehr kann der Hitachi Controller nicht verarbeiten) Dieses betrifft z.B. die Module mit 4 * 27, bzw. 4 * 40 Zeichen. Um das Problem zu lösen wurde diesen Displays eine zweite E Leitung spendiert, alle anderen Leitungen des zweiten Controllers sind parallel angeschlossen. In jedem Fall ist das Datenblatt des Herstellers zu Rate zu ziehen.<br />
In Bascom wird eine zusätzliche Bibliothek geladen um solche Displays ansprechen zu können. Dadurch ist es möglich quasi 2 Displays getrennt anzusteuern, bei einem 4 Zeilen-Display sind die beiden oberen und die zwei unteren getrennt zu selektieren.<br />
<br />
=== Das zusätzliche Programm für das LCD, bzw. die Änderungen ===<br />
<br />
<pre><br />
'Einbindung der LCD-Bibliothek für ein 2-Prozessor-Display<br />
$lib "lcd4e2.lbx"<br />
<br />
'Bascom kennt keine Display mit 27 * 4 Zeichen, daher 40 * 4 verwenden<br />
Config Lcd = 40 * 4<br />
<br />
'man achte auf die Ergänzung E2<br />
Config Lcdpin = Pin , Db4 = Portd.0 , Db5 = Portd.1 , Db6 = Portd.2 , Db7 = Portd.3 , E = Portd.5 , E2 = Portd.6 ,Rs = Portd.4<br />
<br />
' Systemvariable der LCD-Bibliothek (wichtig, bloß nicht ändern)<br />
Dim ___lcde As Byte<br />
<br />
' wählt die beiden oberen Zeilen aus<br />
___lcde = 0 <br />
<br />
' löscht die beiden oberen Zeilen<br />
Cls<br />
' wählt die obere Zeile aus<br />
Upperline<br />
' schreibt in die erste Zeile an Position 3<br />
Locate 1 , 3<br />
' den Text in Anführungszeichen<br />
Lcd "Zeile 1"<br />
' wählt die zweite Zeile aus<br />
Lowerline<br />
' schreibt in die zweite Zeile an Position 2<br />
Locate 2 , 2<br />
' in diesem Fall den Inhalt der Variablem mit dem Namen Variable<br />
Lcd Variable<br />
' unterdrückt den Cursor<br />
Cursor Off<br />
<br />
' wählt die beiden unteren Zeilen aus<br />
___lcde = 1<br />
Waitms 100<br />
Cls<br />
Thirdline<br />
Locate 1 , 1<br />
Lcd "Zeile 3"<br />
Fourthline<br />
Locate 2 , 1<br />
Lcd "Zeile 4"<br />
Cursor Off<br />
<br />
</pre><br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Bascom]]<br />
* [[LCD an RN-Control]]<br />
<br />
==Weblinks==<br />
* [http://www.sprut.de/electronic/lcd/index.htm#einleitung Sprut]<br />
<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Colindrovin