https://rn-wissen.de/wiki/api.php?action=feedcontributions&user=Holzi&feedformat=atomRN-Wissen.de - Benutzerbeiträge [de]2024-03-29T12:54:20ZBenutzerbeiträgeMediaWiki 1.25.1https://rn-wissen.de/wiki/index.php?title=Leuchtdiode&diff=15962Leuchtdiode2010-02-03T12:43:04Z<p>Holzi: </p>
<hr />
<div>[[Bild:SFH300.jpg|right|thumb|Standard Bauform]]Leuchtdioden (Lumineszenzdiode) oder auch LED abgekürzt (light emitting diodes) basieren auf Halbleiterverbindungen, die den Strom direkt in Licht umwandeln. Bezogen auf Größe, Effektivität, Haltbarkeit und Lebensdauer verhalten sich die Leuchtdioden zu konventionellen Glühlampen, wie Halbleiterdioden zu Röhrendioden. Sie werden die Beleuchtungstechnik in ähnlicher Weise verändern, wie die Halbleitertechnologie schon die Elektronik verändert hat.<br />
[[Bild:led.gif|right]]<br />
[[Bild:Schaltsymbol_Lunineszenzdiode.png|left|Schaltsymbol Lunineszenzdiode (LED)]]Ein großer Vorteil ist die hohe Leuchtkraft bei geringer Stromstärke. Daher werden LEDs fast in allen elektronischen Geräten zur Anzeige von Signalen/Zuständen genutzt. Gerade ist auch die neue weisse LED dabei sogar der Glühlampe etwas Konkurrenz zu machen.<br />
Gewöhnlich werden LED's mit maximal 20 mA betrieben. Bei der „SuperFlux LED“ und der „Luxeon“ von Lumileds ist der maximale Betriebsstrom höher, nämlich 70 mA und 350 mA. Dagegen gibt es auch Low-current Typen, die für 2mA ausgelegt sind. Weniger Strom ist kein Problem: die Helligkeit nimmt ungefähr proportional zum Strom ab.<br />
<br />
Die Durchlassspannung hängt von der Bandlücke ab und damit von der Lichtfarbe. Die Betriebsspannungen betragen 1,6V bis 4V. Entsprechend der steilen Diodenkennline ist die Spannung nur wenig vom Strom abhängig.<br />
Wegen des hohen Dotierungsunterschieds an der Sperrschicht vertragen Leuchtdioden nur geringe Sperrspannung von ca. 5 V. Wenn eine LED also an der Kathode positive Spannung abbekommt muss eine Diode antiparallel eingesetzt werden.<br />
<br />
Es ist eine große Vielfalt von Bauformen lieferbar. Neben diversen Metall-/Glas-Gehäusen werden hauptsächlich Plastikbauformen eingesetzt. Hier setzt der Kunststoffkörper zum einen den Grenzwinkel der Totalreflexion an der Chipoberfläche herab und erhöht damit die aus dem Kristall austretende Strahlungsleistung, zum anderen wirkt die gekrümmte Oberfläche als Linse und bündelt die Strahlung in Achsrichtung. Sie sind problemlos in großen Stückzahlen zu fertigen.<br />
<br />
Je nach Verlötungsverfahren wird bei elektronischen Bauteilen zwischen den auf der Rückseite der Platine verlöteten und den SMD (Surface Mounted Device) Bauformen unterschieden. Auch LED werden in beiden Bauformen angeboten.<br />
<br />
Die meisten LEDs kann man nicht direkt an eine Spannungsquelle anschließen. Man stellt den Strom über eine Konstantstromquellen oder einen Vorwiderstand ein. <br />
<br />
'''Praxistip:''' An einer Spannung von 5V (auch Digitalports) werden Leuchtdioden gewöhnlich mit einem Widerstand von min. 330 Ohm bis 1000 Ohm (je nach gewünschter Leuchtstärke) betrieben.<br />
<br />
'''Berechnung des Vorwiderstandes:''' Zur Berechnung des Vorwiderstandes benutzt man das Ohmsche Gesetz. Von der Versorgungsspannung wird die Spannung der LED abgezogen und dann durch den gwünschten Strom geteilt.<br />
Beispiel: Eine LED soll 20mA bekommen und braucht 2V. Unsere Versorgungsspannung hat 9V. Setzt man das in die Formel ein bekommt man 350 Ohm herraus.<br />
Da es die meisten errechneten Widerstände nicht gibt nimmt man sicherheitshalber den nächst höheren.<br />
Beim Rechnen sollte man immer in den Grundeinheiten Ampere, Volt und Ohm bleiben.<br />
Man rechnet also nicht mit 20mA, sondern mit 0,02A. <br />
<br />
<br />
[[Bild:LED.jpg|thumb|center|Weiße LED]] <br />
<br />
<br />
==IR-LEDs==<br />
Neben den LEDs für sichbares Licht gibt es auch LEDs für Infrarotlicht. Die üblichen Wellenlängen sind 880 nm und 950 nm. Diese LEDs haben einen recht hohen Wirkungsgrad und Silizium Fotodioden sind hier besonders empfindlich. Entsprechend eignen sich die IR-LEDs gut für Lichtschranken und die Datenübertragung, z.B. für Fernsteuerungen. Die typischen IR LEDs vertragen bis 100 mA, wenn für eine einigermaßene Wärmeableitung gesorgt wird.<br />
<br />
<br />
'''Funktionstest von IR-LEDs:''' Infrarotlicht ist für Menschen nicht sichtbar. Daher ist der Funktionstest einer IR-LED ohne Hilfsmittel nicht möglich. Neben der Messung der Stromaufnahme ist eine praxiserprobte Möglichkeit das Messgerät Digitalkamera. Warum? Die meisten Digitalkameras "sehen" Infrarotlicht. Eine Ausnahme bilden z.T. hochpreisige Systemkameras, aber die übliche Digicams oder Handikameras sind geeignet. Es muss einfach bei - vermutetem - Leuchten der IR-LED auf das Kameradisplay geschaut werden.<br />
<br />
'''ACHTUNG, extremes Verletzungsrisiko = Erblindungsgefahr :''' Bitte keinesfalls direkt in die leuchtende Infrarotdiode sehen - egal ob man denkt, dass die leuchtet oder nicht. Das Licht kann nicht erkannt werden; wenn man etwas merkt, ist der Augenschaden schon da.<br />
<br />
<br />
[[Bild:Gp2d-060608_1297.jpg]]<br />
<br />
Die Infrarot-LED, links im Bauteil, leuchtet nicht.<br />
<br />
[[Bild:Gpd2d-060608_1503.jpg]]<br />
<br />
Die Infrarot-LED, links im Bauteil, leuchtet.<br />
<br />
<br />
Wie bei jedem indirektem Test bietet sich eine Gegenprobe an. Ist ein Leuchten nicht zu erkennen, kann es sein, dass Spannung garnicht anliegt: Spannung prüfen oder Schalter in andere Position (oder Code ändern). Wenn beide Tests kein positives Ergebnis zeigen, macht ein Diodentest Sinn: wenn man den Minuspol (-) an die Kathode hält, siehe oben, kürzeres Bein, Marke "K" und den Pluspol (+) an die Anode, dann sollte das Instrument einen Wert um etwa 1 V anzeigen. Nach Wechsel der Anschlüsse ist der Durchgang gesperrt.<br />
<br />
<br />
==Parallelschalten von LEDs==<br />
Es kommt immer wieder die Frage auf, ob man LEDs paralelschalten kann: Die kurze Antwort ist besser nicht. <br />
<br />
Dafür gibt es 2 Gründe: Zum einen ist die Spannung der LEDs nicht immer hundertprozentig gleich, und schon etwa 20 mV Unterschied machen einen Faktor 2 beim Strom aus. <br />
Selbst wenn man gleiche Dioden ausgesucht hat, gibt es noch ein Temperaturproblem: Wie bei anderen Dioden auch, nimmt mit steigender Temperatur und konstanter Spannung der Strom relativ schnell zu. Schon bei etwa 5-10 Grad mehr kann sich der Strom verdoppeln. Wenn man jetzt LEDs parallel hat, steigt der Strom der wärmeren LED an und macht diese LED noch wärmer, bis prakisch der ganze Strom durch diese eine LEDs fließt und die LED dann eventuell schädigt.<br />
Ein ähnliches Problem hat man auch beim Parallelschalten von Gleichrichterdiode oder bipolaren Transistoren.<br />
<br />
Wenn man LEDs parallel betreiben will, muß man durch jeweils einen Serienwiderstand dafür sorgen, das der Strom durch den Widerstand, und weniger durch die recht steile Diodenkennlinie bestimmt wird. Der Spannungsabfall am Widerstand sollte dazu wenigstens 100-200 mV betragen.<br />
<br />
Bei den blauen und weissen LEDs gibt es einige Typen, die intern schon einen relativ hohen Serienwiderstand haben und deshalb unter günstigen Umständen direkt paralel geschaltet werden können. Ohne genaue Informationen aus dem Datenblatt sollte man das aber nicht machen und besser für jede LED eine Vorwiderstand spendieren.<br />
<br />
==Siehe auch==<br />
* [[Diode]]<br />
* [[Optokoppler]]<br />
* [[RN-Digi|7 Segment Anzeigen Bauanleitung]]<br />
<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/konstantstrom.php Konstantstromquelle mit LM317]<br />
* [http://www.mikrocontroller.net/articles/LED-Matrix Ansteuerung vieler LED als Matrix]<br />
* [http://www.ledshift.com/Lichtstaerke%20German.html Erklärung zur Lichtstärke ]<br />
<br />
* [http://de.wikipedia.org/wiki/Leuchtdiode LED bei Wikipedia]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Microcontroller&diff=15961Microcontroller2010-02-03T12:41:04Z<p>Holzi: </p>
<hr />
<div>'''Microcontroller''' (MCU oder µC) sind programmierbare integrierte Schaltungen mit Prozessoren, welche für die unterschiedlichsten Anwendungen eingesetzt werden können. Ein Programm (Software) steuert den<br />
Funktionsablauf der Schaltung. Microcontroller befindet sich in allen elektronisch kontrollierten Geräten, vom ABS-System im Auto, über das Videogerät, den Fotoapparat, die Harddiskeinheit im PC, den Telefonapparat bis hin zu Haushaltsgeräten. In all diesen Anwendungen können Microcontroller eingesetzt werden. Die unterschiedlichen Geräteanforderungen werden durch anwendungsspezifische Software und durch spezielle Interfaceschaltungen (Sensoren, Aktoren) abgedeckt.<br />
<br />
Microcontroller sind heute in verschiedenen Größen erhältlich und so billig, dass es sich<br />
lohnt, bereits kleine Schaltungen mit solchen Bauelementen aufzubauen. 4-, 8-, 16- und 32-Bit-Microcontroller werden von verschiedenen Herstellern angeboten und in Millionenstückzahlen produziert. Einfache Funktionen mit geringer Programmgröße können durch Microcontroller im<br />
'Single Chip Mode' gelöst werden. Das Programm wird dabei im [[Flash|Flash-EEPROM]] des Microcontrollers untergebracht, während für die Speicherung von temporären Daten das interne RAM Verwendung findet.<br />
<br />
Microcontroller unterscheiden sich von Microprocessoren durch zusätzliche Funktionen, welche<br />
auf dem gleichen Chip integriert sind. So findet man bei fast allen modernen Microcontrollern<br />
internen Speicher (RAM, Flash, EEPROM), [[Timer|Timersysteme]], Ereigniszähler, Interfaces für verschiedene Schnittstellen, [[ADC|Analog-Digital-Wandler]], [[PWM|Pulsweitenmodulatoren]], Pulsakkumulatoren, [[Watchdog]]-Systeme sowie digitale Ports.<br />
<br />
Am wirkungsvollsten werden solche Systeme in Assembler programmiert. Neuere<br />
Microcontroller eignen sich aber auch sehr gut für die Programmierung<br />
in einer Hochsprache. Teilweise achten die Hersteller von Microcontrollern bereits in der Designphase des Chips darauf, dass die Controller für den Einsatz mit Hochsprachen wie C gut vorbereitet sind. Dank der für Hochsprachen optimierten Befehlssätze der neuesten<br />
MCU-Generation werden heute praktisch alle Anwendungen in Hochsprachen &ndash; davon überwiegend in C, C++, Ada und Java &ndash; programmiert, was die Entwicklungszeiten gegenüber der klassischen Assembler-Programmierung drastisch beschleunigt.<br />
<br />
Microcontroller eignen sich wegen des kompakten Aufbaus und der geringen externen Beschaltung optimal für die Steuerung kleinerer Roboter.<br />
<br />
Es gibt eine ganze Reihe verschiedener Microcontroller. Zahlreiche Hersteller haben ganze Serien von Microcontrollern auf den Markt gebracht. Zu den Beliebtesten gehören die Serien:<br />
* [[8051]] - 8-Bit Microcontroller-Familie, alt - aber auch aktuelle Typen, diverse Hersteller, sehr vielfältig, zum Teil schnell<br />
* [[68HC08/68HC05]] - 8-Bit Mircrocontroller-Familie von Frescale (Motorola), alt - aber auch aktuelle Typen<br />
* [[AVR]] - 8-Bit Microcontroller-Familie der Firma [[Atmel]] <br />
* [[ARM]] - 32-Bit Microcontroller-Core, diverse Hersteller und Versionen <br />
* [[PIC]] - Mikrocontroller-Serie der Firma [[Microchip]]. PIC ist die Abkürzung für Programmable Interface Controller. <br />
<br />
Für kleinere Roboter dürften mit großem Abstand die AVR-Controller von Atmel am weitesten verbeitet sein.<br />
<br />
==Siehe auch==<br />
* [[AVR]]<br />
* [[ARM]]<br />
* [[Atmel]]<br />
<br />
[[Category:Robotikeinstieg]]<br />
[[Category:Grundlagen]]<br />
[[Category:Microcontroller]]<br />
[[Category:Elektronik]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=DAC&diff=15960DAC2010-02-03T12:39:30Z<p>Holzi: </p>
<hr />
<div>Ein Digital-Analog-Wandler (manchmal auch Digital-Analog-Umsetzer genannt), kurz DAC, wandelt digitale Werte in analoge Werte um. Er ist damit das Gegenstück zum [[ADC]].<br />
<br />
Im Microcontroller sind DA Wandler nur selten integriert. Oft kann aber ein [[PWM]]-Ausgang mit einem Tiefpaß-Filter als einfacher, langsamer DAC genutzt werde. Eine andere einfache Möglichkeit für einen DAC ist ein R2R-Netzwerk, vor allen für eine niedrige Auflösung, bis etwa 7 Bit.<br />
<br />
Eine Speziallfall von DA Wandlern sind elektronische Potentiometer, die sich z.B. per I2C oder SPI ansteuern lassen.<br />
<br />
<br />
===Siehe auch===<br />
<br />
*[[ADC]]<br />
<br />
[[Kategorie:Abkürzung]]<br />
[[Kategorie:Microcontroller]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Bascom_und_Timer&diff=15959Bascom und Timer2010-02-03T12:37:56Z<p>Holzi: </p>
<hr />
<div>== Bascom Timer (Mega8 und andere) ==<br />
<br />
<br />
=== Zweck ===<br />
[[Timer]] sind selbständige Zähler im Prozessor. Sie werden dort gebraucht, wo zeitkritische und genaue Aufgaben gefordert sind.<br />
<br />
=== Struktur: ===<br />
<br />
<pre><br />
Config TimerXXX = Timer, Prescale= XX ‘Konfiguriere TimerXXX<br />
Enable TimerXXX ‘schalte den Overflow-Interrupt zu TimerXXX ein<br />
On TimerXXX SprungXXX ‘verzweige bei TimerXXX überlauf zu SprungXXX<br />
Enable Interrupts ‘generell Interrupts zulassen<br />
<br />
Do<br />
....Hauptprogramm ‘Hauptprogramm<br />
Loop<br />
End<br />
<br />
SprungXXX: ‘Unterprogramm von TimerXXX<br />
....Ausführung ‘arbeitet hier etwas ab und springt mit Return <br />
Return ‘wieder zurück zum Hauptprogramm<br />
</pre><br />
<br />
<br />
Zuerst muss man den zu verwendeten Timer mit „Config“, konfigurieren. <br />
Dazu definiert man ihn als Timer (man könnte auch einen Counter daraus machen).<br />
Dazu muss man noch den Prescaler definieren. Der Prescaler ist der Teiler, der die Quarzfrequenz für den Timer reduziert .<br />
(Sonst würde der Timer immer mit der vollen Frequenz vom Quarz zählen und das würde meistens zu schnell sein.)<br />
<br />
Dann mit „Enable“ den gewünschten Interrupt des Timers einschalten. Der Timer selbst läuft auch schon so, mit dem definieren des Taktes.<br />
Mit „On“ das Unterprogramm (ISR) definieren, an die der Timer springen soll, <br />
wenn dieser überläuft(ISR= Interrupt Service Routine). Dann das generelle Einschalten von Interrupts.<br />
<br />
Jeder Zähler hat eine bestimmte, maximale Zählweite. Zählt er über diese, fängt er wieder bei Null an zu zählen (Überlauf).<br />
Wie weit ein Zähler zählen kann, ergibt sich aus seiner Struktur. Es gibt da 8-Bit Timer (Timer0 und Timer2, beim Mega8)und 16-Bit Timer (Timer1 beim Mega8).<br />
8-Bit Timer zählen von 0 bis 255, 16-Bit Timer von 0 bis 65535.<br />
<br />
Bei vielen Timern ist es möglich einzustellen bis zu welchen Wert der Timer zählt. Mit „CONFIG .... COMPARE A = CLEAR“ im Vergleichsregister A die Grenze eingestellt werden.<br />
<br />
Bei einem Interrupt (z.B. Überlauf), unterbricht der Timer das Hauptprogramm und springt in die ISR. Die ISR wird abgearbeitet und mit Return wird wieder an <br />
die Stelle zurückgesprungen, wo vorher das Hauptprogramm unterbrochen wurde. <br />
<br />
Man soll darauf achten, dass in der ISR immer nur kurze Anweisungen (d.h. insbesondere kein WAIT oder PRINT) abgearbeitet <br />
werden und der Hauptteil dann im Hauptprogramm bearbeitet wird. <br />
Sonst kann es sein, dass man den Prozessor damit blockiert.<br />
<br />
=== Timer Beispiel: ===<br />
<pre><br />
Config Timer0 = Timer, Prescale= 8 ‘Konfiguriere Timer0<br />
Enable Timer0 ‘schalte den Timer0 Overflow-interrupt ein<br />
On Timer0 Isr_von_Timer0 ‘verzweige bei Timer0 überlauf zu Isr_von_Timer0<br />
Enable Interrupts <br />
<br />
Do<br />
....Hauptprogramm<br />
Loop<br />
End<br />
<br />
Isr_von_Timer0: ‘ISR von Timer0<br />
.....Programm-Code<br />
Return<br />
</pre><br />
<br />
Timer0 ist nun so eingestellt, dass die Frequenz vom Quarz, durch den Prescaler, durch 8 geteilt wird.<br><br />
(Beim Prescaler kann man Teilungen von 1 , 8 , 64, 256, oder 1024 einstellen).<br> Diese Frequenz kommt nun zum Timer0 und der zählt nun mit dieser Frequenz bis 255.<br />
Ab 255 läuft der Timer über, fängt wieder bei Null an zu zählen, und verzweigt dabei in die ISR.<br />
Mit Return springt die ISR dann wieder zum Hauptprogramm zurück.<br />
In der ISR könnte man z.B. eine Variable hochzählen. Diese würde dann bei einem 8Mhz Quarz, ca. 3906mal in der Sekunde um 1 hochgezählt. ( (8000000Hz/8) /256=3906.26Hz)<br />
<br />
=== Timer im 1 Sekunden Takt ===<br />
<br />
Wenn man jetzt z.B. will, dass eine Variable nur alle Sekunden um 1 hochgezählt wird, muss man den Prescaler anpassen und auch noch die Zählweite vom Timer anpassen.<br />
Die Zählweite vom Timer kann man nur insofern verändern, dass man ihn nicht von Null weg zählen lässt, sondern von einem höheren Wert.(der Überlauf ist immer der maximale Wert vom Timer)<br />
<br />
Da der Timer0 aber mit 8-Bit jetzt zu kurz zählt (0-255) und wir mit einem grossen Prescaler auch nicht auf 1 Sekunde kommen, nehmen wir dazu den Timer1.<br />
<br />
Der Timer1 ist ein 16-Bit Timer und kann von 0-65535 zählen.<br />
<br />
Wenn ich jetzt einen Prescaler von 256 verwende, bekomme ich bei einem 8Mhz Quarz, eine Taktrate von 31250Hz. Das heißt, dass der Zähler in einer Sekunde von 0 bis 31250 zählt. Wenn ich jetzt will, dass der Timer nach 31250 Zählungen überläuft (weil nur beim Überlaufen springt er in die ISR und zählt somit meine Variable um 1 hoch), darf ich den Timer nicht von Null wegzählen lassen sondern von einem höheren Wert.<br />
<br />
Dazu muss ich die maximale mögliche Zählweite (16-Bit = 65535) von meiner gewünschten Zählweite, abziehen. Also 65535-31250 = 34285 .Der Timer muss also schon bei 34285 zu zählen anfangen und macht dann nach 1 Sekunde einen Überlauf. 34285+31250= 65535 = Überlauf<br />
<br />
Hier ein Beispiel mit dem Timer 1.<br />
Zur Kontrolle wird eine Led im Sekundentakt aus und ein geschalten.<br />
Man kann in der ISR auch eine Variable hochzählen lassen.<br />
<pre><br />
$regfile = "m8def.dat" 'für Mega8 <br />
$crystal = 8000000 'für 8MHz Quarz<br />
<br />
Config Portd = Output 'definiert Portd als Output<br />
<br />
Config Timer1 = Timer , Prescale = 256 'Konfiguriere Timer1<br />
Enable Timer1 'schalte den Timer1 ein<br />
On Timer1 Isr_von_timer1 'verzweige bei Timer1 überlauf zu Isr_von_Timer1<br />
Enable Interrupts<br />
Timer1 = 34285 'Timer1 soll schon von 34285 wegzählen<br />
<br />
Do<br />
'....Hauptprogramm<br />
Loop<br />
End<br />
<br />
Isr_von_timer1: 'ISR von Timer1<br />
Timer1 = 34285 'Timer1 soll wieder von 34285 wegzählen<br />
Toggle Portd.0 'schaltet Portd.0 im Sekundentakt<br />
'EIN und AUS<br />
'....oder z.B. incr Variable <br />
<br />
Return<br />
</pre><br />
<br />
Die Vorgabe (Timer1=34285) soll man vor dem Hauptprogramm reinsetzen und bei der ISR.<br />
Wenn man die Vorgabe nicht bei der ISR reinsetzen würde (ISR = Überlauf), würde er ja wieder bei 0 statt bei 34285 anfangen zu zählen.<br />
<br />
Um sich das Rechnen zu ersparen könnte man statt der Anweisung: Timer1 = 34286 , auch den Befehl "Load" verwenden. <br />
<br />
Man gibt dann ein: Load Timer1 , 31250 <br><br />
<br />
Mit Load rechnet sich der Compiler selber die Werte aus ( 65536-31250 ).Man gibt einfach nach dem Komma, die beabsichtigte Zählweite ein.<br />
<br />
Damit hat man nun einen Timer der alle Sekunden eine Variable hochzählt.<br />
<br />
Das nachladen des Startwertes gibt nur bei einem großen Prescaler (64 oder größer), und wenn keine anderen Interrupts aktiv sind genaue Zeitwerte. Beim Prescaler 64 müsste man eventuell noch die Zeiten für Sprung in die ISR u.s.w. mit einberechen. Aber für die meisten Anwendungen reicht diese Genauigkeit vollkommen aus ! :-)<br />
Besser macht man das ohnehin mit einem Vergleichsregister in Hardware.<br />
<br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Timer]]<br />
* [[Bascom]]<br />
* [[Interrupt]]<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&file_id=169 AvrTimer Windows Berechnungstool / Bascom Codegenerator]<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Timer/Counter_(Avr)&diff=15958Timer/Counter (Avr)2010-02-03T12:36:29Z<p>Holzi: </p>
<hr />
<div>Die Mikrocontroller der AVR-Familie besitzen je nach Typ eine unterschiedliche Anzahl an programmierbaren [[Timer|Timern]]. Bei den aktuellen ATmegas sind das mindestens ein 8-Bit Timer und ein 16-Bit Timer. Die Timer werden immer Timerx benannt, wobei x für die Timernummer steht (also 0, 1, 2, usw.). <br />
Die Konfigurationsmöglichkeiten sind von Timer zu Timer unterschiedlich.<br />
<br />
'''Hinweis:''' Die folgenden Code-Beispiele sind in C programmiert und wurden für einen [[ATMega32|ATmega32]] entwickelt. Sie lassen sich also ohne große Änderungen auch auf anderen Mikrocontrollern der AVR-Familie einsetzen.<br />
<br />
== Allgemeine Funktionsweise ==<br />
Timer funktionieren nach dem allgemeinen Prinzip, dass sie eine Ganzzahl (im weiteren als Zähler bezeichnet) je nach Betriebsmodus auf- oder abwärtszählen, d.h. inkrementieren bzw. dekrementieren.<br />
<br />
Angenommen, der Timer arbeitet im einfachsten Betriebsmodus, dem [[Timer/Counter (Avr)#Normaler Modus (Normal Mode)|Normalen Modus]]. Die Zählrichtung des Timers ist aufsteigend gerichtet. Je nach Auflösung, also 8-Bit oder 16-Bit, folgt auf den maximalen Zählerstand wieder die Null. Wenn z.B. bei einem 8-Bit Timer der Wert 255 inkrementiert wird folgt die Null (siehe Grafik).<br />
<br />
[[Bild:AbstrakterZaehlvorgang.png]]<br />
<br />
== Der Prescaler ==<br />
Der Prescaler (eng. = Vorteiler) wird dazu genutzt, den Takt, der den Timern zugeführt wird, zu verkleinern. U.a. kann damit der Timer so konfiguriert werden, damit diese in den unterschiedlichsten Frequenzen takten. Über den Prescaler kann auch der Timer angehalten werden. Hier eine Grafik die den Prescaler veranschaulicht:<br />
<br />
[[Bild:Prescaler.png]]<br />
<br />
Das obere Diagramm zeigt den Betrieb ohne Prescaler, das untere mit Prescaler. Die gestrichelte Linie zeigt, wann der Timer weiterzählt.<br />
<br />
Im Teil [[Timer/Counter (Avr)#Die Betriebsmodi|Die Betriebsmodi]] wird weiter auf die praktische Verwendung des Prescalers eingegangen.<br />
<br />
== Die Betriebsmodi ==<br />
Die AVR-Timer können in unterschiedlichen Betriebsmodi betrieben werden. Diese sind:<br />
* Normaler Modus<br />
* CTC Modus<br />
* PWM<br />
<br />
=== Normaler Modus (Normal Mode) ===<br />
Der einfachste Betriebsmodus ist der normale Modus. Er funktioniert wie im Abschnitt "[[Timer/Counter (Avr)#Allgemeine Funktionsweise|Allgemeine Funktionsweise]]" beschrieben. Die Zählrichtung des Timers ist immer aufsteigend, und irgendwann kommt es zu dem Interrupt Timer-Overflow (welcher in einer passend ISR aufgefangen werden kann). Im einfachsten Fall kann dieser Modus im folgendem Diagramm dargestellt werden:<br />
<br />
[[Bild:NormalerModus_1.png]]<br />
<br />
Der Zähler des Timers (im Diagramm oben, die aufsteigende und dann wieder zurückgesetzte Linie) ist in dem Register TCNTx gespeichert, wobei x für eine Zahl steht. Soll z.B. auf den Timer0 (siehe Datenblatt des jeweiligen Controllers) des Controllers zugegriffen werden, so ist an TCNT eine 0 anzuhängen, also TCNT0.<br />
Wie lange es braucht, bis der Zähler einen Overflow auslöst, ist von der Taktfrequenz des Controllers, dem eingestellten Prescaler-Wert und von der Timerauflösung abhängig. Nun wäre es ja sehr unpraktisch, wenn wir den Zähler nicht anpassen könnten. Denn sonst müssten wir unsere Software, die den Timer benutzt, evtl. anpassen und viel rechnen, um z.B. für 1000 ms zu schlafen. Deswegen kann auf den Zähler zugegriffen werden und ihn vorladen, bevor dieser wieder vom eigentlichen Timer hochgezählt wird. Dies veranschaulicht folgendes Diagramm:<br />
<br />
[[Bild:NormalerModus_1_Vorladen.png]]<br />
<br />
Dadurch kann eingestellt werden, wie lange es dauert, bis ein Overflow auftritt. Um zu berechnen, welchen Wert wir vorladen müssen, kann auch ein Java-Applet genutzt werden, siehe unter [[Timer/Counter (Avr)#Weblinks|Weblinks Java Applet]].<br />
<br />
Natürlich kann das auch "von Hand" berechnet werden. Die Berechnung des Preloader- sowie Prescalerwerts bei Verwendung der Overflow-Interrupts, eines Prescalers von 64 (nicht alle Prescaler können verwendet werden) und eines Quarzes mit der Frequenz von 8 MHz sieht folgendermaßen aus (gesuchte Frequenz beträgt 1000 Hz unter der Verwendung des Timer0 eines ATmega32):<br />
# <math>Prescale = Frequenz * 1000000 [Hz] = 8000000</math><br />
# Wir definieren den maximalen Zählerwert. Dieser ist bei einem 8-Bit Timer 256, bei einem 16-Bit Timer 65536. In unserem Fall ist der maximale Zählerwert 256, weil Timer0 verwendet wird.<br />
# Nun wird die Variable ''Prescale'' (s.o.) durch den verwendeten Prescaler (64) geteilt (<math>8000000 Hz / 64 = 125000</math>).<br />
# Als nächstes wird der im dritten Punkt errechnete Wert durch die gesuchte Frequenz geteilt <math>=125000 / 1000Hz = 125</math>.<br />
# Nun wird mathematisch überprüft, ob der errechnete Wert aus dem vierten Punkt kleiner als der maximale Zählerwert ist. Trifft dies zu, so wird der errechneten Wert vom maximalen Zählerwert subtrahiert(<math>= 256 - 125 = 131</math>).<br />
<br />
Damit haben wir den Wert errechnet, der bei jedem Interrupt, den der Timer0 auslöst, in TCNTx (in diesem Fall TCNT0) nachgeladen werden muss, damit die Interrupts in dem gewünschten Zeitabstand von einer Millisekunde ausgelöst werden.<br />
<br />
Zwischen dem Timer Overflow und dem tatsächlichen Aufrufen der ISR mit dem Nachladen des Timers ergibt sich eine kleine Verzögerung, die nicht einmal immer gleich ist. Besonders bei kleinen Prescalern kann es dadurch zu Fehlern in der Zeit kommen. Wenn möglich wird für die Erzeugung einer konstanten Interruptrate deshalb besser der CTC Moduls benutzt.<br />
<br />
Zusammenfassend ein Beispielprogramm:<br />
<br />
<pre><br />
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz mit 7,3728 MHz<br />
betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer einen Interrupt, also eine<br />
Frequenz von 100000 Hz (oder 100 kHz). Der Timer wird auf einen Prescaler von 1 und<br />
einem Preloader von 183 konfiguriert.*/<br />
<br />
volatile uint8_t countTimer2; // Speichert den aktuellen Zählerwert<br />
<br />
// ISR zum auffangen der Interrupts:<br />
SIGNAL(SIG_SIG_OVERFLOW2)<br />
{<br />
countTimer2++;<br />
TCNT2 = 183; // Nachladen<br />
}<br />
<br />
// Initialisierung:<br />
TCCR2 = (1<<CS22); // Prescaler von 1<br />
TCNT2 = 183; // Vorladen<br />
TIMSK |= (1<<TOIE2); // Interrupts aktivieren und damit Timer starten<br />
sei();<br />
<br />
// Funktionen zum benutzen der Timer:<br />
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.<br />
Bei t=100 schläft die Funktion 1 ms. */<br />
inline void sleep (uint8_t t)<br />
{<br />
// countTimer2 wird in der ISR oben inkrementiert<br />
countTimer2 = 0;<br />
while (countTimer2 < t);<br />
}<br />
<br />
/** Schläft x-Millisekunden. */<br />
inline void sleep_millisec(uint16_t msec)<br />
{<br />
uint16_t i;<br />
for(i=0; i<msec; i++) {<br />
sleep(100);<br />
}<br />
}<br />
</pre><br />
<br />
Viele Timer haben "Output-Compare" Register: OCRx oder OCRAx,OCRBx. Wenn der Zähler den darin eingestellten Wert erreicht hat, kann ein Interrupts ausgelöst werden. <br />
<br />
==== Input Capture ====<br />
<br />
Die 16 Bit Timer haben eine "Input Capture" Funktion. Dieser Hardwareteil dient zur genauen Zeitmessung. Außer in einigen PWM Betriebsarten, wo das ICP Register als TOP-wert für den Timer benutzt wird, ist die ICP-Funktion immer aktiv. Wenn am ICP Pin die über das Bit "ICESx" eingestellte Flanke auftritt, wird der aktuelle Zählerstand in das ICP Register kopiert. Außerdem kann ein Interrupt ausgelöst werden. Der Interrupt wird, wie die anderen Timer Interrupts, in den Registern TIMSK und TIFR an- oder abgestellt. Man kann zwar die ICP-Funktion selber nicht ohne weiteres abschalten, aber natürlich den dazugehörigen Interrupt. Als eine spezielle Funktion ("Noise Cancler") gibt es die Möglichkeit sehr kurze Pulse (unter 4 Zyklen) zu unterdrücken. In der Regel kann man diese Funktion angestellt lassen, denn so schnell kann man die Daten ohnehin nicht verarbeiten.<br />
<br />
Die typische Anwendung ist die Messung von kurze Zeiten, wie z.B. die Zeit für eine Motorumdrehung. Solange die 16 Bit des Timers ausreichen ist die Benutzung ganz einfach: Der Timer wird mit dem gewünschten Vorteiler im normalen Modus gestartet. Im ICP-Interrupt wird die Differenz aus zwei aufeinanderfolgenden Zeiten (Werte in ICP-Register) berechnet. Dazu wird jeweils die vorherige Zeit im RAM zwischengespeichert. Wenn man bei der Rechnung eventuelle Überläufe ignoriert, bekommt man die richtige Zeitdifferenz, auch wenn der Timer während der Messzeit einen Überlauf hatte. Das funktioniert so einfach, denn wenn noch weitere (höherwertige) Bytes vorhanden wären, damit es keinen Überlauf gibt, würde man genau so die unteren Bits berechnen.<br />
<br />
Etwas komplizierter wird es, wenn die 16 Bit Auflösung nicht mehr ausreicht. Dann kann der Timer-Überlauf benutzt werden, um auch längere Zeiten mit voller Auflösung zu messen. Die wesentliche Schwierigkeit ist es, den Fall zu berücksichtigen, dass ein Überlauf Interrupt und der ICP Interrupt fast gleichzeitig ausgelöst werden. Es kann passieren, dass der ICP-Interrupt aufgerufen wird, obwohl eigentlich erst der Overflow Interrupt dran gewesen wäre. Dieser seltene Fall läßt sich daran erkennen, dass das Overflow-Interrupt Flag gesetzt ist und der Wert im ICP Register klein ist (high Byte < 128, meistens 0).<br />
<br />
Beispielpropgramm (für GCC):<br />
(Bisher nur im Simulator getestet)<br />
<pre><br />
// Beispielprogramm für Zeitmessung mit ICP-Funktion<br />
// Erweiterung des Timers auf 32 Bit durch Software<br />
// Es wird die Periodendauer am ICP-Eingang gemessen und als ASCII via UART ausgegeben<br />
// Code für Mega48 / Mega88 / Mega 168 / ...<br />
// mit leichten Anpassungen auch für Tiny2313, Mega16, Mega32,...<br />
<br />
#include <stdlib.h> // für utoa<br />
#include <avr/io.h><br />
#include <avr/interrupt.h><br />
#include <avr/sleep.h> // Unterstützung für sleep mode<br />
<br />
// #define F_CPU 1000000UL // Definition der Frequenz ist normal in makefile<br />
#define BAUD 19200UL<br />
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)<br />
<br />
typedef union { // union erlaubt einen effektiven, seperaten Zugriff auf Teile der Variable<br />
unsigned long i32;<br />
struct {uint8_t i8l; // low<br />
uint8_t i8m; // mid<br />
unsigned int high; // high, soft timer <br />
};<br />
} convert32to8;<br />
<br />
volatile unsigned long timestamp; // volatile wegen Zugriff im Interrrupt<br />
volatile unsigned int softtimer;<br />
volatile unsigned long zeitdifferenz;<br />
unsigned long zeit;<br />
char puffer[12]; // puffer für Ausgabe als Ascii<br />
<br />
ISR(TIMER1_OVF_vect) // Timer1 Überlauf<br />
{ <br />
++softtimer; // zählen der Überläufe<br />
} <br />
<br />
ISR(TIMER1_CAPT_vect) // Flanke an ICP pin<br />
{ <br />
convert32to8 cap; // Variablendeklaration<br />
<br />
cap.i8l = ICR1L; // low Byte zuerst, high Byte wird gepuffert<br />
cap.i8m = ICR1H; <br />
// overflow verpasst, wenn ICR1H klein und wartender Overflow Interrupt<br />
if ((cap.i8m < 128) && (TIFR1 & (1<<TOV1)))<br />
{ // wartenden timer overflow Interrupt vorziehen<br />
++softtimer; <br />
TIFR1 = (1<<TOV1); // timer overflow int. löschen, da schon hier ausgeführt<br />
}<br />
cap.high = softtimer; // obere 16 Bit aus Software Zähler<br />
zeitdifferenz = cap.i32 - timestamp;<br />
timestamp = cap.i32; // Zeit merken<br />
}<br />
<br />
void uart_init(void) // USART initialisieren (Mega48 etc.)<br />
{<br />
// Baudrate einstellen (Normaler Modus)<br />
// kann bei älteren AVR Typen etwas anders sein (kein UBRR0H, dafür prescaler)<br />
UBRR0H = (uint8_t) (UBRR_BAUD>>8); // bei Mega32 anders !<br />
UBRR0L = (uint8_t) (UBRR_BAUD & 0x0ff); // bei Mega32 UBRRL<br />
UCSR0B = (1<<TXEN0); // Aktivieren des Senders, bei Mega32 UCSRB<br />
UCSR0C = (1<<UCSZ01)|(1<<UCSZ00)|(1<<USBS0); // bei Mega32 UCSRC<br />
// Einstellen des Datenformats: 8 Datenbits, 2 Stoppbit:<br />
}<br />
<br />
void putser(char c) // sende ein Byte via UART<br />
{<br />
while ( !( UCSR0A & (1<<UDRE0)) ) ; // Warten bis der Sendepuffer frei ist<br />
UDR0 = c;<br />
}<br />
<br />
void main(void)<br />
{<br />
unsigned char i;<br />
// Datenrichtungen:<br />
DDRB = 0; // Alles Eingänge, PB0 ist ICP<br />
PORTB = 0xFF - (1<<PB0); // Pullups an Eingängen außer ICP<br />
DDRC = 0; // Eingänge<br />
PORTC = 0xFF; // Pullups an Eingängen <br />
DDRD = (1<<PD1); // Eingänge, außer PD1 = Tx (UART)<br />
PORTC = 0xFF- (1<<PD1); // Pullups an alle Eingängen (außer TX)<br />
// Timer1 initialisieren:<br />
TCCR1A = 0; // normal mode, keine PWM Ausgänge<br />
TCCR1B = (1<< ICNC1) + (1<<CS10) // start Timer mit Systemtakt<br />
+ (1 << ICES1); // steigende Flanke auswählen<br />
TIMSK1 = (1<<TOIE1) + (1<<ICIE1); // overflow und Input-capture aktivieren, Mega32: TIMSK<br />
TIFR1 = (1<<TOIE1) + (1<<ICIE1); // Schon aktive Interrrupts löschen, Mega32: TIFR<br />
// UART initialisieren:<br />
uart_init(); <br />
<br />
zeitdifferenz = 0;<br />
softtimer = 0; // wird für Zeitdifferenzmessung nicht mal gebraucht,<br />
// denn Differenz geht auch über Überlauf bei Softtimer<br />
set_sleep_mode (SLEEP_MODE_IDLE); // idle Mode: timer läuft weiter, int zum aufwachen<br />
<br />
sei(); // Interrupts erlauben: Messung startet<br />
while (1)<br />
{<br />
sleep_enable (); <br />
sei();<br />
sleep_cpu(); // wartet auf irgendeinen Interrupt, z.B. ICP, timer_ovr,...<br />
sleep_disable(); <br />
cli(); // Interrupt sperren wegen Zugriff auf volatile Variable<br />
zeit = zeitdifferenz;<br />
zeitdifferenz = 0; // als Markierung für ungültigen Wert<br />
sei();<br />
if (zeit > 0)<br />
{ <br />
utoa(zeit,puffer,10); // nach ASCII umwandeln<br />
i = 0;<br />
while (puffer[i])<br />
{<br />
putser(puffer[i++]); // Ausgabe<br />
}<br />
putser(13); // Zeilenumbruch senden<br />
putser(10);<br />
}<br />
} // Ende von While-schleife<br />
}<br />
</pre><br />
<br />
=== CTC Modus (Clear Timer on Compare Match mode) ===<br />
Der CTC Modus ist eine Erweiterung des "Output-Compare"-Funktion. Der CTC Modus eignet sich besonders, um einen mit konstanter Frequenz wiederkehrenden Interrupt zu erzeugen. Wie im normalen Modus zählt der Timer hoch. Wenn der Wert im OCRx Register erreicht wird, wird zusätzlich zum möglichen Interrupt der Zähler wieder auf 0 gesetzt. Es kann also die maximalen Zählergrenze selber definiert werden.<br />
Dieses Diagramm veranschaulicht den CTC Modus.<br />
<br />
[[Bild:NormalerModus_CompareMatch.png]]<br />
<br />
Beispielprogramm:<br />
<br />
<pre><br />
/* Es wird der Timer2 (8-Bit) eines ATmega32 verwendet, der mit einem Quarz <br />
mit 7,3728 MHz betrieben wird. Im Abstand von 0,01 ms erzeugt der Timer <br />
einen Interrupt, also eine Frequenz von 100000 Hz (oder 100 kHz). <br />
Der Timer wird auf einen Prescaler von 1 und einem OCR2-Wert von 73 konfiguriert. */<br />
<br />
volatile uint8_t countTimer2; // Speichert den aktuellen Zählerwert<br />
<br />
// ISR zum auffangen der Interrupts:<br />
SIGNAL(SIG_OUTPUT_COMPARE2)<br />
{<br />
countTimer2++;<br />
}<br />
<br />
// Initialisierung:<br />
TCCR2 = (1<<CS22) | (1<<WGM21); // Prescaler von 1 | CTC-Modus (siehe unten für Beschreibung)<br />
OCR2 = 73; // Vergleichswert<br />
TIMSK |= (1<<OCIE2); // Interrupts aktivieren und damit Timer starten<br />
sei();<br />
<br />
// Funktionen zum benutzen der Timer:<br />
/** Diese Funktion nicht aufrufen. Wird von sleep_millisec aufgerufen.<br />
Bei t=100 schläft die Funktion 1 ms. */<br />
inline void sleep(uint8_t t)<br />
{<br />
// countTimer2 wird in der ISR oben inkrementiert<br />
countTimer2 = 0;<br />
while (countTimer2 < t);<br />
}<br />
<br />
/** Schläft x-Millisekunden. */<br />
inline void sleep_millisec(uint16_t msec)<br />
{<br />
uint16_t i;<br />
for(i=0; i<msec; i++) {<br />
sleep(100);<br />
}<br />
}<br />
</pre><br />
<br />
----<br />
<br />
=== PWM ===<br />
<br />
Eine häufige Aufgabe für Mikrocontroller ist die Erzeugung von [[PWM]]-Signalen, zum Beispiel für Motorsteuerungen. Daher sind in den meisten [[AVR|AVRs]] PWM-Einheiten als Hardware vorhanden. Sie sind direkt mit den Timern verbunden und nutzen diese als Taktquelle. Die Hardware-PWM-Einheiten haben den Vorteil, sehr wenig Rechenzeit in Anspruch zu nehmen. Es muss nur die PWM aktiviert werden und bei Änderungen den gewünschten Wert in ein Register schreiben. Der Rest läuft automatisch und unabhängig vom restlichen Programm, ohne den AVR ständig zu beschäftigen wie bei einer PWM-Lösung in Software. Allerdings stehen meist nur zwei bis drei solcher PWM-Kanäle zur Verfügung, die außerdem an bestimmte Pins gebunden sind. Für die meisten Roboter mit zwei Antriebsmotoren reicht dies aber für gewöhnlich aus. <br />
<br />
==== nutzbare Pins am AVR ====<br />
Die Hardware-PWM-Funktion steht nur an bestimmten Pins zur Verfügung. In der Pinbelegungsübersicht im Datenblatt ist erkenntbar, dass als Sonderfunktion in Klammern "OC..." angegeben ist. Beim Mega32 sind dies zb. OC0 an PB0, OC1A an PD5, OC1B an PD4 und OC2 an PD7. Der Mega32 hat also insgesamt vier Hardware-PWM-Kanäle. Die Zahl hinter dem "OC" gibt an, zu welchem der Timer dieser PWM-Kanal gehört. Wenn noch ein Buchstabe dahinter kommt, dann gehören mehrere PWMs zu diesem Timer. Beim Mega32 sind also OC1A und OC1B demselben Timer, nämlich Timer1, zugeordnet.<br />
<br />
'''Zu beachten ist, dass die für die PWM benutzten Pins zuvor explizit als Ausgang konfiguriert werden müssen! Ansonsten gelangt das PWM-Signal nicht nach draußen!'''<br />
<br />
==== Funktionsprinzip ====<br />
Das "OC" in den Pinbezeichnungen steht für "Output Compare Unit", also frei übersetzt Ausgangs-Vergleicher-Einheit. Dies beschreibt die Funktionsweise der PWM-Kanäle: der Zählerstand des Timers wird fortlaufend mit einen einstellbaren Referenzwert verglichen, und wenn beide Werte übereinstimmen, kann ein Ausgangspin des AVRs automatisch geschaltet werden (und ein Interrupt ausgelöst werden, was allerdings für die PWM-Funktion nicht relevant ist). Dies entspricht dem Verfahren im [[PWM#PWM_per_Software|Beispiel zur Software-PWM]]. Es läuft nun allerdings vollautomatisch im Hintergrund, sodass der Controller nicht damit belastet wird.<br />
<br />
==== Die verschiedenen PWM-Modi ====<br />
Es gibt -je nach AVR und Timer- etliche Betriebsarten, in denen die PWM-Einheit betrieben werden kann. Sie unterscheiden sich vor allem darin, wie schnell und mit welchen Nebeneffekten sich Änderungen des Sollwertes auf das Ausgangssignal auswirken. Für den Anfang sind diese Unterschiede erst einmal nebensächlich, und für eine einfache Motorsteuerung meist auch irrelevant. Daher wird hier zunächst der "Fast PWM Mode" ("Schneller PWM Modus", weil hier die größte Ausgangsfrequenz möglich ist) beschreiben, welcher der einfachste von allen ist.<br />
<br />
Hierbei zählt der Timer immer von Null an aufwärts, bis er den Maximalwert (teilweise einstellbar) erreicht hat. Dann läuft er über und fängt von vorne an. Wie schnell dies geschieht, wird, wie im normalen Modus, über den Prescaler eingestellt.<br />
Der gewünschte PWM-Ausgangswert wird im "OCRn"-Register abgelegt. Er darf zwischen Null und dem Maximalwert des Timers liegen. Er wird nun mit dem Timer-Wert verglichen. Was dann passiert, regeln die "COM..."-Bits. Sie bestimmen, wie der Ausgang geschaltet wird. Die übliche Konfiguration ist, dass bei Erreichen des Sollwertes die Ausgänge auf high geschaltet werden, und beim Überlauf auf low. Damit ergibt sich ein nichtinvertiertes PWM-Signal. Schließt man (über einem passenden Motortreiber!) einen Motor an, dreht er sich bei einem Sollwert von 0 gar nicht und beim Maximalwert mit voller Geschwindigkeit.<br />
<br />
Beispielcode für den Timer1 des Mega16/32 (und vieler anderer AVRs): <br />
<pre><br />
#include <avr/io.h><br />
#include <util/delay.h> // Warteschleife für die Demo. Für die eigentliche PWM nicht benötigt! <br />
<br />
/* PWM-Beispiel für Mega16/32 (beiden haben den gleichen Timer)<br />
Benutzt wird Timer1 im Fast PWM Mode, 8 Bit Auflösung<br />
Die PWM-Signale liegen auf PD5/OC1A und PD4/OC1B<br />
*/ <br />
<br />
// 1. Den Prescaler einstellen, der die Frequenz festlegt<br />
TCCR1B |= (1<<CS12); //Prescaler 256<br />
<br />
// 2. Den Timer in den Fast PWM Mode, 8 Bit schalten<br />
// ACHTUNG: Die WGM-Bits sind auf beide Konfigurationsregister verteilt!<br />
TCCR1A |= (1<<WGM10);<br />
TCCR1B |= (1<<WGM12);<br />
<br />
// 3. Compare Output mode einstellen: Pin geht auf high bei Compare match, auf low bei Überlauf. <br />
// Ergibt nichtinvertierte PWM. <br />
TCCR1A |= (1<<COM1A1) | (1<<COM1B1) ; <br />
<br />
// In diesen Registern wird der gwünschte PWM-Wert abgelegt. Erlaubter Bereich: 0 bis 255.<br />
OCR1A = 0;<br />
OCR1B = 0; <br />
<br />
// 4. Die Pins als Ausgänge konfigurieren. Erst jetzt liegt das PWM-Signal an den Pins an! <br />
DDRD |= (1<<PD4) | (1<< PD5);<br />
<br />
/*Nun ist der PWM-Modus aktiv! Der Ausgangswert kann nun über die Register OCR1A und OCR1B<br />
vorgegeben werden. Man könnte ihnen per define noch einen Zweitnamen verpassen, zb */<br />
#define MotorLinks OCR1A<br />
#define MotorRechts OCR1B<br />
//Und nun kann man per <br />
MotorLinks = 127;<br />
MotorRechts = 127;<br />
//seinen Roboter mit halber Kraft vorwärts fahren lassen.<br />
<br />
/*PWM-Demo: Die PWM-Werte werden erst bis zum Maximalwert erhöht und dann wieder verringert. <br />
Ein angeschlossener Motor wird beschleunigen und dann wieder abbremsen. */<br />
uint8_t wert;<br />
while(1)<br />
{<br />
for (wert=0; wert<255; wert++)<br />
{<br />
OCR1A = wert;<br />
OCR1B = wert;<br />
_delay_ms(10);<br />
}<br />
<br />
for (wert=255; wert>0; wert--)<br />
{<br />
OCR1A = wert;<br />
OCR1B = wert;<br />
_delay_ms(10);<br />
} <br />
}<br />
</pre><br />
<br />
Es sind also vier Einstellungen zu treffen:<br />
# Takt anlegen per Prescaler<br />
# PWM-Modus wählen<br />
# Ausgangs-Aktion festlegen<br />
# Pins als Ausgänge schalten<br />
<br />
Diese Schritte müssen bei jedem AVR-PWM-Kanal ausgeführt werden. Die genauen Registernamen und Werte können sich jedoch je nach Timer-Ausführung etwas unterscheiden.<br />
<br />
== Registerübersicht ==<br />
''Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden kann es sein, dass ein oder mehrere Register nicht existieren, oder sie eine andere Bezeichnung haben.''<br />
<br />
{| {{Blaueschmaltabelle}} width=100%<br />
|'''TIMSK'''<br />
|-<br />
|Mit diesem Register, der von allen Timern verwendet wird, lässt sich die Interruptausführung und Art des jeweiligen Timers bestimmen.<br/><br/><br />
<br />
{{Registertabelle8Bit|OCIE2|TOIE2|TICIE1|OCIE1A|OCIE1B|TOIE1|OCIE0|TOIE0}}<br />
<br />
|-<br />
|<br />
*'''OCIE2 (Timer/Counter2 Output Compare Match Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''TOIE2 (Timer/Counter2 Overflow Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter2 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''TICIE1 (Timer/Counter1, Input Capture Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Input Capture Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''OCIE1A (Timer/Counter1 Output Compare A Match Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare A Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''OCIE1B (Timer/Counter1 Output Compare B Match Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Output Compare B Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''TOIE1 (Timer/Counter1 Overflow Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, wird der Timer/Counter1 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''OCIE0 (Timer/Counter0 Output Compare Match Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Compare Match Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
*'''TOIE0 (Timer/Counter0 Overflow Interrupt Enable)'''<br/>Wenn dieses Bit gesetzt wird, so wird der Timer/Counter0 Overflow Interrupt aktiviert (vorrausgesetzt die Interrupts sind global aktiviert).<br />
|}<br />
<br />
<br />
== Siehe auch ==<br />
<br />
* [[Atmel]]<br />
* [[HEX Beispiel-Dateien für AVR]]<br />
* [[Bascom_und_Timer]]<br />
<br />
== Weblinks ==<br />
<br />
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]<br />
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]<br />
<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Abkürzung|AVR]]<br />
[[Kategorie:Quellcode C]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15885Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2010-01-01T08:25:47Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden. Natürlich könnten auch die installierten Schnittstellen aus der Regetry ausgelesen werden. Meine Erfahrung zeigt aber, dass dieses Vorgehen oft scheitert, da in der Regestry Ports noch eingetragen sind, die in Wirklichkeit nicht mehr vorhanden sind (es wird Software nicht deinstalliert, sondern nur von Hand gelöscht und somit werden die Regestry-Einträge auch nicht gelöscht). <br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
[[Bild:333.jpg]]<br />
COM-Port ist geöffnet. Die Button sind inaktiv und werden erst wieder aktiv, wenn die Verbindung getrennt wurde.<br />
== Das Programm samt Sourcecode kann hier [http://www.inter-save.com] im Downloadbereich herunter geladen werden ==<br />
<br />
<br />
== Lizenz-Bedingung ==<br />
<br />
Dieses Programm steht unter der folgenden CC BY-NC-SA-Lizenz .Dieser Quelltext einschließlich <br />
der darin verlinkten Inhalte steht unter der CC by-nc-sa Lizenz <br />
http://creativecommons.org/licenses/by-nc-sa/3.0/de/ <br />
<br />
Das bedeutet: Es ist gestattet: das Werk vervielfältigen, verbreiten und öffentlich <br />
zugänglich machen, Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen zu den folgenden <br />
Bedingungen: <br />
Namensnennung. Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten <br />
Weise nennen. Keine kommerzielle Nutzung. Dieses Werk darf nicht für kommerzielle Zwecke <br />
verwendet werden. Weitergabe unter gleichen Bedingungen. Wenn Sie den lizenzierten Inhalt <br />
bearbeiten oder in anderer Weise umgestalten, verändern oder als Grundlage für einen anderen <br />
Inhalt verwenden, dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von <br />
Lizenzbedingungen weitergeben, die mit denen dieses Lizenzvertrages identisch oder <br />
vergleichbar sind.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Spannungsregler&diff=15884Spannungsregler2010-01-01T08:20:03Z<p>Holzi: </p>
<hr />
<div>Die meisten Elektronikschaltungen brauchen eine bestimmte, stets gleichbleibende Betriebsspannung. Üblich sind hier 5V, bei einigen Bauteilen auch 3,3V. Oft stellt sich daher das Problem, dass eine schwankende Spannung auf einen festen Wert geregelt werden muss, um die Schaltung zu betreiben. Bei Batterien und Akkus sinkt die Spannung ab, wenn sie entladen werden, und bei einfachen Netzteilen und Trafos schwankt die Spannung je nach Belastung. <br />
Um dieses Problem zu lösen, gibt es die sogenannten Spannungsregler: Bauteile, die mit der ungeregelten, schwankenden Spannung versorgt werden und daraus die gewünschte, konstante Spannung erzeugen.<br />
<br />
<br />
=Lineare Spannungsregler=<br />
<br />
[[Bild:78s05.jpg|thumb|Spannungsregler 78S05]] Die wohl bekanntesten und sehr häufig eingesetzten Spannungsregler sind die der 78xx-Serie. Das xx steht hierbei für die Spannung, die die Regler erzeugen: 7805 für 5V, 7812 für 12V, und so weiter. Der große Vorteil dieser Regler ist ihr geringer Preis (ab etwa 20 cent) und die einfache Verwendung: in der Minimalvariante sind keine externen, zusätzlichen Bauteile nötig. Es wird aber trotzdem dringend empfohlen, zwei Kondensatoren anzuschließen, damit der Regler stabil arbeitet. <br />
<br />
Die Regler vergleichen die Ausgangsspannung mit einer intern erzeugen Referenzspannung. Wenn die Ausgangsspannung zu niedrig ist, wird ein [[Transistor]], durch den der Ausgangsstrom fließt, stärker angesteuert, sodass ein größerer Strom fließen kann, bis die gewünschte Spannung erreicht ist. <br />
[[Bild:Linearregler-Prinzip.png|thumb|Prinzipelle Arbeitsweise eines Linearreglers]]<br />
Steigt die Ausgangsspannung zu sehr an, wird über den Transistor der Strom reduziert, bis die Spannung sich wieder stabilisiert hat. Der Transistor wird also benutzt wie ein variabler Widerstand, der so eingeregelt wird, daß die "überflüssige" Spannungdifferenz zwischen Eingangsspannung und gewünschter Ausgangsspannung an ihm abfällt, und zwar unabhängig vom fliessenden Strom. <br />
<br />
Der Nachteil dieser linearen Spannungsregler liegt in ihrem schlechten Wirkungsgrad und ihrer großen Verlustleistung. Der Teil der Spannung, die am Eingang zugeführt wird und gerade nicht am Ausgang benötigt wird, fällt am Transistor ab und wird dort in Wärme umgewandelt. Je nach Stromfluss führt das zu einer starken Erwärmung des Reglers, so dass in den meisten Fällen ein Kühlkörper nötig wird, wodurch weitere Kosten entstehen und viel Platz in Anspruch genommen wird. Außerdem reduziert sich durch die großen Verluste die Betriebsdauer, wenn man den Regler mit Akkus oder Batterien versorgt.<br />
<br />
Linearregler gibt es als Festspannungsregler und Regler mit einstellbarer Ausgangsspannung. Viele der Regler sind kurzschlußfest.<br />
<br />
Bei den normalen Spannungsreglern muß die Eingangsspannung mindestens 2-3 Volt höher als die Ausgangsspannung sein. Bei "low-drop" Reglern ist nur eine extra Spannung ("dropout") von etwa 0,1-0,5 V nötig. Dafür fließt aber in der Regel mehr Strom über den Masseanschluss. Außerdem muss bei Low-drop Reglern genauer auf die Kapazität (oft >20 µF) hinter dem Regler geachtet werden.<br />
<br />
;Festspannungsregler:<br />
* 7805 (5V)<br />
* 78xx (xxV) , 1 A positiv, Gehäuse TO220<br />
* 78Sxx (xxV), 2 A positiv, Gehäuse TO220<br />
* 79xx (-xxV), 1 A negativ, Gehäuse TO220<br />
* LM2936-xx (xxV) Low drop, Dropout typ. 200mV, max. 50mA, Gehäuse TO220<br />
* LM2940-xx (xxV) Low drop, Dropout typ. 500mV, max. 1 A, Gehäuse TO220<br />
* LT1761ES5-xx (xxV) Low drop,Dropout typ. 300mV, max. 100mA, Verpolungsschutz, Gehäuse SOT23-5<br />
<br />
;Linerregler, einstellbar:<br />
* LM317: <br />
* VB408: Hochvolt<br />
* LP2951: low drop 100 mA<br />
<br />
Für die Widerstandsberechnung an einem LM317 siehe [http://people.freenet.de/gjl/pub/lm317/index.html].<br />
<br />
=Schaltregler=<br />
<br />
Schaltregler arbeiten nach einem komplett anderen Prinzip. Während bei Linearreglern die Spannungsdifferenz in Wärme umgewandelt wird und damit verloren ist, wird diese Energie bei Schaltreglern in einem Magnetfeld gespeichert und der Schaltung zu einem späteren Zeitpunkt wieder zugeführt.<br />
<br />
Dies erfordert einen komplizierteren Aufbau als beim Linearregler. Ein Schaltregler hat zwei Arbeitsphasen:<br />
;On-Phase: Eingangsenergie wird im Magnetfeld gespeichert<br />
;Off-Phase: Die im Magnetfeld gespeicherte Energie wird an den Ausgang abgegeben<br />
Je nach Konstruktionsprinzip kann in beiden Phasen auch Energie direkt vom Eingang zum Ausgang fliessen.<br />
<br />
Der wesentliche Vorteil eines Schaltreglers besteht in seinem hohen Wirkungsgrad, je nach Typ lassen sich etwa 70% bis über 90% erzielen. Zudem kann die Ausgangssannung über der Eingangsspannung liegen und ein anderes Vorzeichen haben. Dadurch ergeben sich längere Laufzeiten im Akku- und Batteriebetrieb und eine gegenüber linearen Reglern wesentlich geringere Erwärmung. Daher kommt man ohne oder mit einem vergleichsweise kleinen Kühlkörper aus.<br />
<br />
Der Nachteil liegt in einem höheren Preis. Übliche Schaltungen, die im Leistungsbereich eines 78xx liegen, kosten etwa 2 bis 5€. Außerdem brauchen diese Schaltungen teilweise mehr Platz, weil zum Regler-IC noch die Spule, Kondensatoren und oft eine Diode kommen. Auch das Platinenlayout erfordert etwas Sorgfalt, denn gewisse Leitungen sollten möglichst kurz und breit ausgeführt werden, um die einwandfreie Funktion sicherzustellen. Die Qualität der Spannung ist wegen der hohen Schaltfrequenzen in der Regel etwas schlechter als bei einem Linearregler und kann zu Problemen in der Schaltung führen wie z.B. die Störung vom Funkempfängern.<br />
<br />
==Abwärtswandler==<br />
[[Bild:smps-down.png|thumb|263px|Prinzipieller Aufbau eines Abwärtsreglers]]<br />
Am einfachsten zu verstehen ist der Abwärtswandler (Step-Down):<br />
<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei zum Ausgang. Über der Drossel fällt Spannung ab, daher ist V<sub>OUT</sub> kleiner als V<sub>IN</sub>. Die Energiedifferenz wird in der Drossel als Magnetfeld gespeichert. Mit der Zeit setzt die Drossel dem Strom einen immer geringer werdenden Widerstand entgegen: Die V<sub>OUT</sub> steigt immer weiter. Hat V<sub>OUT</sub> den gewünschten Wert erreicht, dann wird S geöffnet und die On-Phase beendet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel ist jetzt eine aus der Energie ihres Magnetfelds gespeiste Strompumpe, die den Kondensator C weiter mit Energie versorgt, indem sie Strom durch die Diode D saugt. In der Off-Phase zieht der Verbraucher seine Energie aus dem elektrischen Feld des Kondensators und dem Magnetfeld der Drossel. Sinkt der Strom durch die Drossel unter einen Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==Aufwärtswandler==<br />
[[Bild:smps-up.png|thumb|267px|Prinzipieller Aufbau eines Aufwärtswandlers]]<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei nach GND. Der Stromfluss baut ein Magnetfeld in der Drossel auf. In der On-Phase versorgt sich der Verbraucher aus dem Kondensator C. Erreicht der Strom durch die Drossel einen oberen Schwellwert, wird S geöffnet und die on-Phase endet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel pumpt Ladungsträger über die Diode D auf den Kondensator C. Die Energie dazu nimmt sie aus ihrem Magnetfeld. V<sub>OUT</sub> kann weit über V<sub>IN</sub> steigen. Sinkt der Strom durch die Drossel unter einen unteren Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==Invertierender Wandler==<br />
[[Bild:smps-neg.png|thumb|265px|Prinzipieller Aufbau eines invertierenden Wandlers]]<br />
Funktioniert vom Prinzip wie der Aufwärtswandler.<br />
<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei nach GND. Der Stromfluss baut ein Magnetfeld in der Drossel auf. In der On-Phase versorgt sich der Verbraucher aus dem Kondensator C. Erreicht der Strom durch die Drossel einen oberen Schwellwert, wird S geöffnet und die on-Phase endet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel saugt über die Diode D Ladungsträger vom Kondensator C. Die Energie dazu nimmt sie aus ihrem Magnetfeld. V<sub>OUT</sub> sinkt unter GND. Sinkt der Strom durch die Drossel unter einen unteren Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==praktische Umsetzung==<br />
<br />
Für Schaltregler gibt es spezielle ICs, die den größten Teil der Schaltung enthalten.<br />
Neben der Frequenz und dem Tastverhältnis sind auch die beteiligten Komponenten (Schalttransistor, Drossel, Diode, Kondensatoren) entscheidend für die Eigenschaften des Reglers (Effizienz, Störungen, Leistungbereich, Ausgangsspannung- und Strom, Ripple, Baugröße, etc.) <br />
<br />
[[Bild:lm2575.png|thumb|480px|Beispielschaltung für Schaltregler mit LM2575-5: 5 V bis ca. 1 A. Der 100µF Elko vor dem Regler sollte ein low ESR Typ sein und ggf. auch größer, um die nötige Strombelastbarkeit zu erreichen.]]<br />
<br />
Beispiele für Schaltregler ICs:<br />
* LM2574 N5 : 5 V, 0,5 A , Abwärtwandler, DIP8<br />
* LM2576 T12: 12 V, 3 A , Abwärtwandler, TO220-5<br />
* MC33063/MC34063 : variabel ca. 0,2-1 A, DIP8, SO8<br />
* LT1072 , variabel<br />
* MAX856, aufwärt, z.B. 3 V -> 5 V, ca. 100 mA, SO8 (SMD)<br />
* PR4401, aufwärt, LED-teiber ca. 20 mA, SOT23 (SMD)<br />
<br />
Im jeweiligen Datenblatt findet man in der Regel Informationen zur Schaltung und den benötigten Teilen, insbesondere der Induktivität.<br />
<br />
<br />
<br />
<br />
Noch zu ergänzen: <br />
* Fotos<br />
* Schaltpläne<br />
<br />
= Spannungsregler als Konstantstromquelle=<br />
<br />
Für viele Aufgaben sind konstante Ströme ebenso wichtig wie konstante Spannungen. Beispielsweise bei Leuchtdioden. Leuchtdioden benötigen in der Regel ca. 20 mA Strom, je nach Ausführung. Vorwiderstände sind oft nicht die beste Lösung, zumal diese bei fallender Spannung den Strom nicht mehr konstant halten und somit die Leuchtkraft unnötig reduzieren. Eine einfache und zugleich günstige Lösung ist die hier abgebildete Schaltung mit dem zweckentfremdeten Spannungsregler LM317K. <br />
Der LM317K ist normalerweise ein einstellbarer Spannungsregler. Über die untere Schaltung wird er auch zur Konstantstromquelle: Der Spannungsregler stellt sich so ein, daß zwischen "Vout" und "Adj." 1,25 V liegen. Dank R = U / I läßt sich leicht errechnen, daß bei einem betimmten Widerstandswert ein bestimmter Strom fließt. Und diesen lassen wir dann einfach durch unsere Verbraucher weiterfließen. <br />
Der LM 317K kann mit einer maximalen Eingangsspannung von ca. 4 bis 35 Volt betrieben werden. Die Strombegrenzung ist in einem Bereich von 1,25 - 0,01 Ampere einstellbar, R1 liegt somit zwischen 1 Ohm bis 120 Ohm. Siehe unten unter [[#Weblinks|Weblinks]], dort findet man ein Online-Formular im Roboternetz, mit der sich die Schaltung genau dimensionieren läßt.<br />
<br />
<br />
[[Bild:Konstantstromquellelm317.gif]] <br />
[[Bild:lm317.gif]]<br />
<br />
=Autoren=<br />
* [[Benutzer:Uwegw|Uwegw]] 15:09, 10. Sep 2006 (CEST)<br />
* [[Benutzer:SprinterSB|SprinterSB]]<br />
* [[Benutzer:Frank|Frank]]<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/konstantstrom.php Konstantstromregler mit Spannungsregler berechnen]<br />
* [http://schmidt-walter.fbe.fh-darmstadt.de/smps/smps.html Schaltnetzteile: Erklärung der verschiedenen SPMS-Topologien, Dimensionierung, Rechenhilfe, ...]<br />
<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Spannungsregler&diff=15883Spannungsregler2010-01-01T08:18:50Z<p>Holzi: </p>
<hr />
<div>Die meisten Elektronikschaltungen brauchen eine bestimmte, stets gleichbleibende Betriebsspannung. Üblich sind hier 5V, bei einigen Bauteilen auch 3,3V. Oft stellt sich daher das Problem, dass eine schwankende Spannung auf eine festen Wert geregelt muss, um die Schaltung zu betreiben. Bei Batterien und Akkus sinkt die Spannung ab, wenn sie entladen werden, und bei einfachen Netzteilen und Trafos schwankt die Spannung je nach Belastung. <br />
Um dieses Problem zu lösen, gibt es die sogenannten Spannungsregler: Bauteile, die mit der ungeregelten, schwankenden Spannung versorgt werden und daraus die gewünschte, konstante Spannung erzeugen.<br />
<br />
<br />
=Lineare Spannungsregler=<br />
<br />
[[Bild:78s05.jpg|thumb|Spannungsregler 78S05]] Die wohl bekanntesten und sehr häufig eingesetzten Spannungsregler sind die der 78xx-Serie. Das xx steht hierbei für die Spannung, die die Regler erzeugen: 7805 für 5V, 7812 für 12V, und so weiter. Der große Vorteil dieser Regler ist ihr geringer Preis (ab etwa 20 cent) und die einfache Verwendung: in der Minimalvariante sind keine externen, zusätzlichen Bauteile nötig. Es wird aber trotzdem dringend empfohlen, zwei Kondensatoren anzuschließen, damit der Regler stabil arbeitet. <br />
<br />
Die Regler vergleichen die Ausgangsspannung mit einer intern erzeugen Referenzspannung. Wenn die Ausgangsspannung zu niedrig ist, wird ein [[Transistor]], durch den der Ausgangsstrom fließt, stärker angesteuert, sodass ein größerer Strom fließen kann, bis die gewünschte Spannung erreicht ist. <br />
[[Bild:Linearregler-Prinzip.png|thumb|Prinzipelle Arbeitsweise eines Linearreglers]]<br />
Steigt die Ausgangsspannung zu sehr an, wird über den Transistor der Strom reduziert, bis die Spannung sich wieder stabilisiert hat. Der Transistor wird also benutzt wie ein variabler Widerstand, der so eingeregelt wird, daß die "überflüssige" Spannungdifferenz zwischen Eingangsspannung und gewünschter Ausgangsspannung an ihm abfällt, und zwar unabhängig vom fliessenden Strom. <br />
<br />
Der Nachteil dieser linearen Spannungsregler liegt in ihrem schlechten Wirkungsgrad und ihrer großen Verlustleistung. Der Teil der Spannung, die am Eingang zugeführt wird und gerade nicht am Ausgang benötigt wird, fällt am Transistor ab und wird dort in Wärme umgewandelt. Je nach Stromfluss führt das zu einer starken Erwärmung des Reglers, so dass in den meisten Fällen ein Kühlkörper nötig wird, wodurch weitere Kosten entstehen und viel Platz in Anspruch genommen wird. Außerdem reduziert sich durch die großen Verluste die Betriebsdauer, wenn man den Regler mit Akkus oder Batterien versorgt.<br />
<br />
Linearregler gibt es als Festspannungsregler und Regler mit einstellbarer Ausgangsspannung. Viele der Regler sind kurzschlußfest.<br />
<br />
Bei den normalen Spannungsreglern muß die Eingangsspannung mindestens 2-3 Volt höher als die Ausgangsspannung sein. Bei "low-drop" Reglern ist nur eine extra Spannung ("dropout") von etwa 0,1-0,5 V nötig. Dafür fließt aber in der Regel mehr Strom über den Masseanschluss. Außerdem muss bei Low-drop Reglern genauer auf die Kapazität (oft >20 µF) hinter dem Regler geachtet werden.<br />
<br />
;Festspannungsregler:<br />
* 7805 (5V)<br />
* 78xx (xxV) , 1 A positiv, Gehäuse TO220<br />
* 78Sxx (xxV), 2 A positiv, Gehäuse TO220<br />
* 79xx (-xxV), 1 A negativ, Gehäuse TO220<br />
* LM2936-xx (xxV) Low drop, Dropout typ. 200mV, max. 50mA, Gehäuse TO220<br />
* LM2940-xx (xxV) Low drop, Dropout typ. 500mV, max. 1 A, Gehäuse TO220<br />
* LT1761ES5-xx (xxV) Low drop,Dropout typ. 300mV, max. 100mA, Verpolungsschutz, Gehäuse SOT23-5<br />
<br />
;Linerregler, einstellbar:<br />
* LM317: <br />
* VB408: Hochvolt<br />
* LP2951: low drop 100 mA<br />
<br />
Für die Widerstandsberechnung an einem LM317 siehe [http://people.freenet.de/gjl/pub/lm317/index.html].<br />
<br />
=Schaltregler=<br />
<br />
Schaltregler arbeiten nach einem komplett anderen Prinzip. Während bei Linearreglern die Spannungsdifferenz in Wärme umgewandelt wird und damit verloren ist, wird diese Energie bei Schaltreglern in einem Magnetfeld gespeichert und der Schaltung zu einem späteren Zeitpunkt wieder zugeführt.<br />
<br />
Dies erfordert einen komplizierteren Aufbau als beim Linearregler. Ein Schaltregler hat zwei Arbeitsphasen:<br />
;On-Phase: Eingangsenergie wird im Magnetfeld gespeichert<br />
;Off-Phase: Die im Magnetfeld gespeicherte Energie wird an den Ausgang abgegeben<br />
Je nach Konstruktionsprinzip kann in beiden Phasen auch Energie direkt vom Eingang zum Ausgang fliessen.<br />
<br />
Der wesentliche Vorteil eines Schaltreglers besteht in seinem hohen Wirkungsgrad, je nach Typ lassen sich etwa 70% bis über 90% erzielen. Zudem kann die Ausgangssannung über der Eingangsspannung liegen und ein anderes Vorzeichen haben. Dadurch ergeben sich längere Laufzeiten im Akku- und Batteriebetrieb und eine gegenüber linearen Reglern wesentlich geringere Erwärmung. Daher kommt man ohne oder mit einem vergleichsweise kleinen Kühlkörper aus.<br />
<br />
Der Nachteil liegt in einem höheren Preis. Übliche Schaltungen, die im Leistungsbereich eines 78xx liegen, kosten etwa 2 bis 5€. Außerdem brauchen diese Schaltungen teilweise mehr Platz, weil zum Regler-IC noch die Spule, Kondensatoren und oft eine Diode kommen. Auch das Platinenlayout erfordert etwas Sorgfalt, denn gewisse Leitungen sollten möglichst kurz und breit ausgeführt werden, um die einwandfreie Funktion sicherzustellen. Die Qualität der Spannung ist wegen der hohen Schaltfrequenzen in der Regel etwas schlechter als bei einem Linearregler und kann zu Problemen in der Schaltung führen wie z.B. die Störung vom Funkempfängern.<br />
<br />
==Abwärtswandler==<br />
[[Bild:smps-down.png|thumb|263px|Prinzipieller Aufbau eines Abwärtsreglers]]<br />
Am einfachsten zu verstehen ist der Abwärtswandler (Step-Down):<br />
<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei zum Ausgang. Über der Drossel fällt Spannung ab, daher ist V<sub>OUT</sub> kleiner als V<sub>IN</sub>. Die Energiedifferenz wird in der Drossel als Magnetfeld gespeichert. Mit der Zeit setzt die Drossel dem Strom einen immer geringer werdenden Widerstand entgegen: Die V<sub>OUT</sub> steigt immer weiter. Hat V<sub>OUT</sub> den gewünschten Wert erreicht, dann wird S geöffnet und die On-Phase beendet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel ist jetzt eine aus der Energie ihres Magnetfelds gespeiste Strompumpe, die den Kondensator C weiter mit Energie versorgt, indem sie Strom durch die Diode D saugt. In der Off-Phase zieht der Verbraucher seine Energie aus dem elektrischen Feld des Kondensators und dem Magnetfeld der Drossel. Sinkt der Strom durch die Drossel unter einen Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==Aufwärtswandler==<br />
[[Bild:smps-up.png|thumb|267px|Prinzipieller Aufbau eines Aufwärtswandlers]]<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei nach GND. Der Stromfluss baut ein Magnetfeld in der Drossel auf. In der On-Phase versorgt sich der Verbraucher aus dem Kondensator C. Erreicht der Strom durch die Drossel einen oberen Schwellwert, wird S geöffnet und die on-Phase endet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel pumpt Ladungsträger über die Diode D auf den Kondensator C. Die Energie dazu nimmt sie aus ihrem Magnetfeld. V<sub>OUT</sub> kann weit über V<sub>IN</sub> steigen. Sinkt der Strom durch die Drossel unter einen unteren Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==Invertierender Wandler==<br />
[[Bild:smps-neg.png|thumb|265px|Prinzipieller Aufbau eines invertierenden Wandlers]]<br />
Funktioniert vom Prinzip wie der Aufwärtswandler.<br />
<br />
;On-Phase (Schalter S geschlossen): Über S und die Drossel L fliesst Strom an der Diode D vorbei nach GND. Der Stromfluss baut ein Magnetfeld in der Drossel auf. In der On-Phase versorgt sich der Verbraucher aus dem Kondensator C. Erreicht der Strom durch die Drossel einen oberen Schwellwert, wird S geöffnet und die on-Phase endet.<br />
<br />
;Off-Phase (Schalter S geöffnet): Die Drossel ist ein induktives Bauelement. Daher kann der Strom durch sie nicht sofort stoppen; er muss weiterfliessen: Die Drossel saugt über die Diode D Ladungsträger vom Kondensator C. Die Energie dazu nimmt sie aus ihrem Magnetfeld. V<sub>OUT</sub> sinkt unter GND. Sinkt der Strom durch die Drossel unter einen unteren Schwellwert, dann folgt die nächste On-Phase.<br />
<br />
==praktische Umsetzung==<br />
<br />
Für Schaltregler gibt es spezielle ICs, die den größten Teil der Schaltung enthalten.<br />
Neben der Frequenz und dem Tastverhältnis sind auch die beteiligten Komponenten (Schalttransistor, Drossel, Diode, Kondensatoren) entscheidend für die Eigenschaften des Reglers (Effizienz, Störungen, Leistungbereich, Ausgangsspannung- und Strom, Ripple, Baugröße, etc.) <br />
<br />
[[Bild:lm2575.png|thumb|480px|Beispielschaltung für Schaltregler mit LM2575-5: 5 V bis ca. 1 A. Der 100µF Elko vor dem Regler sollte ein low ESR Typ sein und ggf. auch größer, um die nötige Strombelastbarkeit zu erreichen.]]<br />
<br />
Beispiele für Schaltregler ICs:<br />
* LM2574 N5 : 5 V, 0,5 A , Abwärtwandler, DIP8<br />
* LM2576 T12: 12 V, 3 A , Abwärtwandler, TO220-5<br />
* MC33063/MC34063 : variabel ca. 0,2-1 A, DIP8, SO8<br />
* LT1072 , variabel<br />
* MAX856, aufwärt, z.B. 3 V -> 5 V, ca. 100 mA, SO8 (SMD)<br />
* PR4401, aufwärt, LED-teiber ca. 20 mA, SOT23 (SMD)<br />
<br />
Im jeweiligen Datenblatt findet man in der Regel Informationen zur Schaltung und den benötigten Teilen, insbesondere der Induktivität.<br />
<br />
<br />
<br />
<br />
Noch zu ergänzen: <br />
* Fotos<br />
* Schaltpläne<br />
<br />
= Spannungsregler als Konstantstromquelle=<br />
<br />
Für viele Aufgaben sind konstante Ströme ebenso wichtig wie konstante Spannungen. Beispielsweise bei Leuchtdioden. Leuchtdioden benötigen in der Regel ca. 20 mA Strom, je nach Ausführung. Vorwiderstände sind oft nicht die beste Lösung, zumal diese bei fallender Spannung den Strom nicht mehr konstant halten und somit die Leuchtkraft unnötig reduzieren. Eine einfache und zugleich günstige Lösung ist die hier abgebildete Schaltung mit dem zweckentfremdeten Spannungsregler LM317K. <br />
Der LM317K ist normalerweise ein einstellbarer Spannungsregler. Über die untere Schaltung wird er auch zur Konstantstromquelle: Der Spannungsregler stellt sich so ein, daß zwischen "Vout" und "Adj." 1,25 V liegen. Dank R = U / I läßt sich leicht errechnen, daß bei einem betimmten Widerstandswert ein bestimmter Strom fließt. Und diesen lassen wir dann einfach durch unsere Verbraucher weiterfließen. <br />
Der LM 317K kann mit einer maximalen Eingangsspannung von ca. 4 bis 35 Volt betrieben werden. Die Strombegrenzung ist in einem Bereich von 1,25 - 0,01 Ampere einstellbar, R1 liegt somit zwischen 1 Ohm bis 120 Ohm. Siehe unten unter [[#Weblinks|Weblinks]], dort findet man ein Online-Formular im Roboternetz, mit der sich die Schaltung genau dimensionieren läßt.<br />
<br />
<br />
[[Bild:Konstantstromquellelm317.gif]] <br />
[[Bild:lm317.gif]]<br />
<br />
=Autoren=<br />
* [[Benutzer:Uwegw|Uwegw]] 15:09, 10. Sep 2006 (CEST)<br />
* [[Benutzer:SprinterSB|SprinterSB]]<br />
* [[Benutzer:Frank|Frank]]<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/konstantstrom.php Konstantstromregler mit Spannungsregler berechnen]<br />
* [http://schmidt-walter.fbe.fh-darmstadt.de/smps/smps.html Schaltnetzteile: Erklärung der verschiedenen SPMS-Topologien, Dimensionierung, Rechenhilfe, ...]<br />
<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Bascom_Interrupts&diff=15877Bascom Interrupts2009-12-30T18:00:43Z<p>Holzi: </p>
<hr />
<div>== Bascom Interrupts (Mega8 und andere) ==<br />
Was ist das eigentlich und wie wird mit [[Interrupt|Interrupts]] unter Bascom gearbeitet? Die hier gezeigten Beispiele lassen sich eigentlich auf alle [[AVR]]-Boards bzw. Controller übertragen.<br><br />
<br />
<br />
=== Allgemein ===<br />
Interrupts werden immer dort verwendet, wo zeitkritische Anwendungen gefordert sind.<br />
Wenn man z.B. ein ganz kurzes Signal an einem Pin messen/detektieren will, kann man es mit dem normalem Hauptprogramm leicht übersehen. (z.B. durch eine Wait-Anweisung o.ä.)<br />
<br />
Bei Verwendung eines Interrupts, reagiert der Prozessor, bei auftreten des Signals, unbedingt und verzweigt zu seiner ISR (Interrupt Service Routine), um dort darauf zu reagieren. <br />
(Anschliessend springt er wieder in das Hauptprogramm zurück)<br />
<br />
<br />
<br />
=== Etwas genauer ===<br />
Microcontroller heissen so, weil sich in ihnen eine Reihe von recht eigenständigen Geräten für Timer, PWM, ADC, etc. befinden. Diese Geräte werden irgendwann mal konfiguriert ("CONFIG device-name"), dann in irgendeiner Form gestartet (z.B. "START ADC"), ja, und dann werden sie natürlich irgendwann mal mit ihrer Aufgabe fertig. Das zeigen sie durch Setzen eines bestimmten Bits in einem I/O Register an.<br />
*Wir kriegen das mit, wenn wir gelegentlich oder öfter diese "FERTIG"-Bits abfragen<br />
*Oder wir erlauben dem Gerät, einen [[Interrupt|Interrupt]] auszulösen ("ENABLE device-name").<br />
<br />
Ganz vorne im Programmspeicher ist eine Tabelle von sogenannten "ISR" (=Interrupt-Service-Routinen), jeder Eintrag davon ist einem bestimmten Gerät zugeordnet. (Die Tabelle ist keine Idee von den Bascom-Leuten, das haben die AVR-Hersteller so festgelegt, und das gilt daher auch für alle anderen Programmiersprachen). Der Ablauf ist nun folgender:<br />
*Ein Gerät wird fertig und setzt sein "fertig" Bit <br />
*Der Controller schaut, ob diese Gerät Interrupts auslösen darf<br />
*Der Controller schaut, ob das "global interrupt enable"-Bit gesetzt ist (eine Art Hauptschalter)<br />
Trifft das alles zusammen, wird zwar noch der gerade laufende Maschinenbefehl fertig gemacht, aber dann gibt es kein Halten mehr: <br />
*Weitere Interrupts werden "disabled", damit dem Controller jetzt keiner in die Suppe spucken kann, denn ein paar Befehle lang steht der Controller jetzt "auf dem linken Bein".<br />
*Die eigentlich nächste fällige Befehlsadresse wird auf den Stack gelegt ("PUSH")<br />
*der Adresse der ISR aus der ob. Tabelle wird in den Befehlszähler geladen<br />
*und ausgeführt. <br />
Die weitere Kontrolle liegt nun vollständig in der Hand der ISR. <br />
<br />
Tritt in dieser Zeit nun noch ein anderer Interrupt auf, merkt sich das der <br />
Controller zwar, tut aber weiter nichts, da ja die Interrupts jetzt global "disabled" sind<br />
<br />
Erst, wenn die ISR den Maschinen-Befehl "RETI" durchführt, <br />
*wird die ursprüngliche Befehlsadresse vom Stack wieder runtergeholt ("POP") <br />
*in den Befehlszähler geladen<br />
*Interrupts werden wieder global "enabled"<br />
Und es geht wieder "normal" weiter, wenn nicht schon ein weiterer Interrupt lauert, denn dann wiederholt sich das alles. <br />
<br />
<br />
<br />
<br />
=== Struktur: ===<br />
<br />
<pre><br />
Config InterruptXXX ‘Konfiguriere Interrupt<br />
Enable Interrupts ‘generell Interrupts zulassen<br />
Enable InterruptXXX ‘schalte speziell den InterruptXXX ein<br />
On InterruptXXX SprungXXX ‘verzweige bei InterruptXXX zu SprungXXX<br />
<br />
Do<br />
....Hauptprogramm ‘Hauptprogramm<br />
Loop<br />
End<br />
<br />
SprungXXX: ‘Unterprogramm von InterruptXXX<br />
....Ausführung ‘arbeitet hier etwas ab und springt mit Return <br />
Return ‚ wieder zurück, zum Hauptprogramm<br />
</pre><br />
<br />
<br />
Am Anfang muss man den beabsichtigten Interrupt mit „Config“, konfigurieren. <br />
Dann das generelle Einschalten von Interrupts. <br />
Dann mit „Enable“ den bestimmten Interrupt einschalten. <br />
Mit „On“ das Unterprogramm (ISR) definieren, an die der Interrupt springen soll, <br />
wenn dieser ausgelöst wird. (ISR= Interrupt Service Routine) <br />
<br />
Grundsätzlich kann man das so betrachten, dass es das Hauptprogramm gibt <br />
(mit eventuellen Unterprogrammen) und die Interrupt Service Routinen (ISR).<br />
<br />
Bei einem Interrupt, wird das Hauptprogramm unterbrochen und der Prozessor <br />
springt in die ISR. Die ISR wird abgearbeitet und mit Return wird wieder an <br />
die Stelle zurückgesprungen, wo vorher das Hauptprogramm unterbrochen wurde. <br />
<br />
Man soll darauf achten, dass in der ISR immer nur kurze Anweisungen abgearbeitet <br />
werden und der Hauptteil dann im Hauptprogramm bearbeitet wird. <br />
Sonst kann es sein, dass man den Prozessor damit blockiert. Insbesondere Befehle wie "Wait" oder "Print" sollte man in der ISR vermeiden.<br />
<br />
Für die ISR muß der Zustand des Hauptprogramms gespeichert werden. Dazu ist zusätzlicher Platz (bis 35 Bytes) auf dem HW-Stack nötig, der entsprechend reserviert werden muß.<br />
<br />
=== Interrupt: Int0 ===<br />
<pre><br />
Config Int0 = Low Level ‘Configuriere Int0 auf Low Level<br />
Enable Interrupts ‘einschalten der Interrupts<br />
Enable Int0 ‘einschalten von Interrupt Int0<br />
On Int0 Isr_von_Int0 ‘springe zu Isr_von _Int0 <br />
<br />
Do<br />
....Hauptprogramm<br />
Loop<br />
End<br />
<br />
Isr_von_Int0: ‘ISR von Int0<br />
.....Programm-Code<br />
Return<br />
</pre><br />
<br />
Int0 ist ein Interrupt, der ausgelöst wird, wenn am INT0 (Pin.d2 beim Mega8),<br />
eine Veränderung auftritt. (Int1 bei Pin.d3)<br />
<br />
Es gibt für diesen Interrupt drei Einstellmöglichkeiten auf die er reagieren kann:<br />
<br />
:'''Low Level:''' reagiert solange der Pin auf Masse gesetzt wird.<br/><br />
:'''Falling:''' reagiert nur auf eine fallende Flanke<br/><br />
:'''Rising:''' reagiert nur auf eine steigende Flanke<br/><br />
<br />
==Autor==<br />
* [[Benutzer:Roberto|Roberto]]<br />
* [[Benutzer:PicNick|PicNick (Ergänzungen)]]<br />
<br />
==Siehe auch==<br />
* [[Avr]]<br />
* [[Bascom]]<br />
* [[Interrupt]]<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Quellcode Bascom]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=UART&diff=15876UART2009-12-30T17:59:41Z<p>Holzi: </p>
<hr />
<div>Als UART wird der Teil eines µC oder Computers bezeichnet, der ein asychrone serielle Datenübertragung erlaubt. <br />
<br />
UART heißt '''"Universal Asynchronous serial Receiver and Transmitter"'''<br />
<br />
Die wichtigste Anwendung sind Schnittstellen wie [[RS232]] oder [[RS485]].<br />
Die Signale direkt am µC sind dabei (fast immer) noch CMOS- (bzw. TTL) Pegel. Direkt angeschlossen werden darf also eine RS232 oder ähnliches in der Regel nicht. Für die verschiedenen Schnittstellen gibt es passende Treiber/Reciever ICs wie MAX232 für RS232, MAX485 für RS485, und viele andere. Für kurze Strecken, z.B. auf einer Platine können die UART Signale direkt mit den Logikpegel benutzt werden. Man hat dann aber halte noch keine RS232 Schnittstelle.<br />
Der serielle UART benötigt 2 Daten-Leitungen und natürlich GND: <br />
* "TxD" (Tranceive Data = Daten Senden)<br />
* "RxD" (Receive Data = Daten Empfangen)<br />
<br />
Die Übertragungsgeschwindigkeit wird in Baud angeben. Obwohl über die Register zahlreiche Baudraten einstellbar sind, so haben sich gewisse Baudraten als Standard etabliert. Bei Controlleranwendungen ist das sehr oft 9600 Baud. <br />
Baudrate Bitlänge <br />
300 Baud 3,33 ms <br />
2400 Baud 417 µs <br />
9600 Baud 104 µs <br />
38400 Baud 26,04 µs <br />
Für ein Datenbyte werden 1 Startbit, die 8 Datenbits und 1-2 Stopbits übertragen.<br />
<br />
Damit eine Asyncrone Übertragung funktioniert, müssen Sender und Empfänger die gleiche (oder wenigstens fast) Geschwindigkeit benutzen. Für die üblichen Datenpakete von 8-10 Bits kann eine Abweichung bis etwa 4% gerade noch gehen. Für eine sichere Übertragung sollte die Geschwindigkeit aber besser (2%) stimmen, damit etwas Reserve für Laufzeitfehler und ähnliches da ist. Die Anforderunge sind so, das es mit dem internen Takt der meisten µCs oft geht, aber nicht immer zuverlässig. Um die Standart Baudraten (besonders die höheren) genau zu erreichen, gibt es spezielle Quarze mit krummen Frequenzen wie: 3.6864 MHz, 7.3728 MHz, 11.0592 MHz.<br />
<br />
<br />
Bei vielen der AVR Controllern gibt es die Erweiterung, <br />
<br />
USART = '''"Universal Synchronous and Asynchronous serial Receiver and Transmitter"'''.<br />
Die UART ist hier ergänzt um Fähigkeit einer synchronen Datenübertragung (z.B. SPI).<br />
Bei synchroner Übertragung kommt eine Taktleitung dazu und man ist entspechend nicht mehr auf einen genauen Takt beim Sender und Empfänger angewiesen.<br />
<br />
<br />
Einsatzzwecke:<br />
* Kommunikation mit dem PC<br />
* Kommunikation unter Roboter-On-Board-(Sub)Systemen<br />
* Datenübertragung<br />
<br />
Der UART wird gerne zur Daten-Ausgabe auf dem PC eingesetzt. Hierzu benötigt man am PC ein [[Terminalprogramm]]. Man kann so auch leicht im eigenen Code Fehler suchen, indem man sich an den Problemstellen Variablen über den UART ausgeben lässt. (Debuggen)<br />
<br />
''Artikel von tobimc''<br />
<br />
==Siehe auch==<br />
* [[Terminalprogramm]]<br />
* [[Terminals]]<br />
* [[RS232]]<br />
* [[Software-UART mit avr-gcc]]<br />
* [[UART mit avr-gcc]]<br />
<br />
==WebLinks==<br />
* [http://www.gjlay.de/helferlein/avr-uart-rechner.html AVR-Baudraten-Rechner (JavaScript)]<br />
<br />
[[Kategorie:Abkürzung]]<br />
[[Kategorie:Kommunikation]]<br />
[[Kategorie:Microcontroller]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Gleitender_Mittelwert_in_C&diff=15875Gleitender Mittelwert in C2009-12-30T17:58:10Z<p>Holzi: </p>
<hr />
<div>Der gleitende Mittelwert, auch gleitender Durchschnitt genannt, wird verwendet, um zeitlich aufeinander folgende Reihen von Werten zu glätten; eben den Mittelwert über n aufeinader folgende Werte zu bilden. <br />
<br />
{{Ausbauwunsch| viel mehr erklärender Text}}<br />
<br />
== Verwendung ==<br />
Um die Einwirkung von veränderlichen äußeren Einflüssen auf die Genauigkeit von Messungen zu reduzieren, wird häufig der Mittelwert über die letzten gemessenen Werte gebildet. Das gleitende Mittel ist ein einfacher digitaler Tiefpaßfilter und kann so "hochfrequente" Störungen unterdrücken. Besonders gut unterdrückt werden Störfrequenzen, bei denen gerade eine ganze Zahl an Perioden in die Mittelungszeit passen. Es ist unerheblich, woher diese äußeren Einflüsse stammen, sei es z.B. aus Schwankungen der Versorgungsspannung, thermisches Rauschen oder Störungen aus der Umgebung.<br/> Die Bildung eines gleitenden Mittelwertes hat jedoch wenig bis keinen Einfluß auf die Genauigkeit der Ergebnisse, wenn diese durch nahezu konstante äußere Einflüsse (wie z.B. Temperaturdrift eines Verstärkers) verfälscht werden.<br />
<br />
Eine denkbare sinnvolle Anwendung: Ein Roboter ist mit einer größeren Solarzelle ausgerüstet und soll für diese die hellste Stelle in einer halbschattigen Umgebung (im Freien unter Laubbäumen) finden. Jede Positionsänderung kann eine gravierende Änderung der Zellenspannung bewirken.<br />
<br />
== Alternativen zu gleitenden Mittel ==<br />
<br />
Wenn nicht so viele Ausgabewerte gebraucht werden wie gemessen werden, kann besser eine normale Mittelung durchgeführt werden. Gegebenenfalls kann man dies auch mit einem gleitenden Mittel kombinieren. Für ein einfaches Voltmeter ist es z.B. sinnvoll jeweils 1024 Werte des AD-Wandlers zu mitteln und dann aus je 4 dieser Mittelwerte das gleitende Mittel berechnen.<br />
<br />
Relativ einfach und schnell zu berechenen ist auch ein einfacher digitaler Tiefpass erster Ordnung. Vorteilhaft ist dabei, dass man die alten Werte nicht speichern muß, es reicht ein alter Wert. Der Ausgabewert ist dabei einfach das gewichtete Mittel aus dem Ergebnis des letzten Schrittes und dem neuen Messwert.<br />
<br />
== Beispiel ==<br />
Hier ein Beispiel für die Auswirkungen auf eine Messung. Im Bild werden gestörte Messwerte in rot und die durch den gleitenden Mittelwert geglätteten Werte in grün dargestellt. Ein Nachteil bei der Glättung über viele Werte ist die langsame Reaktion auf Sprünge, wie am Anfang beim Sprung von 0 auf 50 zu sehen ist.<br />
<br />
[[Bild:GleitenderMittelwert.png]]<br />
<br />
== C-Code ==<br />
Auf Optimierungen, inline-Funktionen etc. wurde vorerst zugunsten der Lesbarkeit verzichtet.<br />
Für manche Anwendungen ist es Sinnvoll für den gleitenden Mittelwert einen anderen Datentyp als für die Einzelwerte vorzusehen. Z.B. kann der Mittelwert von ganzen Zahlen durchaus signifikante Nachkommastellen haben. <br />
<br />
=== Header ===<br />
;FloatingAverage.h<br />
<br />
#ifndef FLOATING_AVERAGE_H<br />
#define FLOATING_AVERAGE_H<br />
<br />
#include <inttypes.h><br />
<br />
{{ccomment|Ueber wieviele Werte soll der gleitende Mittelwert berechnet werden?}}<br />
{{ccomment|Zulaessige Werte 1..255}}<br />
#define SIZE_OF_AVG 8<br />
<br />
{{ccomment|Datentyp, ueber den der gleitende Mittelwert berechnet werden soll.}}<br />
typedef uint16_t tFloatAvgType;<br />
{{ccomment|typedef float tFloatAvgType;}}<br />
<br />
{{ccomment|Wird nur intern fuer die Durchschnittsberechnung benutzt.}}<br />
{{ccomment|Muss Zahlen fassen koennen, die SIZE_OF_AVG mal groesser als tFloatAvgType sind.}}<br />
typedef uint32_t tTempSumType;<br />
{{ccomment|typedef float tTempSumType;}}<br />
<br />
{{ccomment|Die Struktur, in der die Daten zwischengespeichert werden}}<br />
typedef struct<br />
{<br />
tFloatAvgType aData[SIZE_OF_AVG];<br />
uint8_t IndexNextValue;<br />
} tFloatAvgFilter;<br />
<br />
<br />
{{ccomment|Initialisiert das Filter mit einem Startwert.}}<br />
void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,<br />
tFloatAvgType i_DefaultValue);<br />
<br />
{{ccomment|Schreibt einen neuen Wert in das Filter.}}<br />
void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,<br />
tFloatAvgType i_ui16NewValue);<br />
<br />
{{ccomment|Berechnet den Durchschnitt aus den letzten SIZE_OF_AVG eingetragenen Werten.}}<br />
tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter);<br />
<br />
#endif<br />
<br />
<br />
<br />
=== Quellcode ===<br />
;FloatingAverage.c<br />
<br />
#include "FloatingAverage.h"<br />
<br />
void InitFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter, <br />
tFloatAvgType i_DefaultValue)<br />
{ <br />
{{ccomment|Den Buffer mit dem Initialisierungswert fuellen:}}<br />
for (uint8_t i = 0; i < SIZE_OF_AVG; ++i)<br />
{<br />
io_pFloatAvgFilter->aData[i] = i_DefaultValue;<br />
}<br />
{{ccomment|Der naechste Wert soll an den Anfang des Buffers geschrieben werden:}}<br />
io_pFloatAvgFilter->IndexNextValue = 0;<br />
} <br />
<br />
<br />
void AddToFloatAvg(tFloatAvgFilter * io_pFloatAvgFilter,<br />
tFloatAvgType i_NewValue)<br />
{ <br />
{{ccomment|Neuen Wert an die dafuer vorgesehene Position im Buffer schreiben.}}<br />
io_pFloatAvgFilter->aData[io_pFloatAvgFilter->IndexNextValue] =<br />
i_NewValue;<br />
{{ccomment|Der naechste Wert wird dann an die Position dahinter geschrieben.}}<br />
io_pFloatAvgFilter->IndexNextValue++;<br />
{{ccomment|Wenn man hinten angekommen ist, vorne wieder anfangen.}}<br />
io_pFloatAvgFilter->IndexNextValue %= SIZE_OF_AVG;<br />
} <br />
<br />
<br />
tFloatAvgType GetOutputValue(tFloatAvgFilter * io_pFloatAvgFilter)<br />
{<br />
tTempSumType TempSum = 0;<br />
{{ccomment|Durchschnitt berechnen}}<br />
for (uint8_t i = 0; i < SIZE_OF_AVG; ++i)<br />
{<br />
TempSum += io_pFloatAvgFilter->aData[i];<br />
}<br />
{{ccomment|Der cast is OK, wenn tFloatAvgType und tTempSumType korrekt gewaehlt wurden.}}<br />
tFloatAvgType o_Result = (tFloatAvgType) (TempSum / SIZE_OF_AVG);<br />
return o_Result;<br />
}<br />
<br />
<br />
<br />
=== Anwendungsbeispiel ===<br />
Hier folgt ein Beispiel, das die Anwendung in einem PC-Konsolen-Programm demonstriert<br />
<br />
<br />
#include <stdio.h><br />
#include "FloatingAverage.h"<br />
<br />
int main(void)<br />
{<br />
{{ccomment|Datenstruktur anlegen:}}<br />
tFloatAvgFilter FilterVoltageBatt;<br />
<br />
{{ccomment|initialisieren und mit 0 fuellen}}<br />
InitFloatAvg(&FilterVoltageBatt, 0);<br />
<br />
AddToFloatAvg(&FilterVoltageBatt, 100);<br />
{{ccomment|jetzt steht 1 mal 100 und 7 mal 0 im Buffer:}}<br />
printf("100/8 = %d\n", GetOutputValue(&FilterVoltageBatt));<br />
<br />
AddToFloatAvg(&FilterVoltageBatt, 200);<br />
{{ccomment|jetzt steht 1 mal 100, 1 mal 200 und 6 mal 0 im Buffer:}}<br />
printf("300/8 = %d\n", GetOutputValue(&FilterVoltageBatt));<br />
<br />
AddToFloatAvg(&FilterVoltageBatt, 300);<br />
AddToFloatAvg(&FilterVoltageBatt, 200);<br />
{{ccomment|jetzt steht 1 mal 100, 2 mal 200, 1 mal 300 und 4 mal 0 im Buffer:}}<br />
printf("800/8 = %d\n", GetOutputValue(&FilterVoltageBatt));<br />
<br />
return 0;<br />
}<br />
<br />
== Weblinks ==<br />
* [http://de.wikipedia.org/wiki/Gleitender_Mittelwert Wikipedia - Gleitender Mittelwert]<br />
<br />
[[Kategorie:Quellcode C]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15817Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:48:57Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
[[Bild:333.jpg]]<br />
COM-Port ist geöffnet. Die Button sind inaktiv und werden erst wieder aktiv, wenn die Verbindung getrennt wurde.<br />
== Das Programm samt Sourcecode kann hier [http://www.inter-save.com] im Downloadbereich herunter geladen werden ==<br />
<br />
<br />
== Lizenz-Bedingung ==<br />
<br />
Dieses Programm steht unter der folgenden CC BY-NC-SA-Lizenz .Dieser Quelltext einschließlich <br />
der darin verlinkten Inhalte steht unter der CC by-nc-sa Lizenz <br />
http://creativecommons.org/licenses/by-nc-sa/3.0/de/ <br />
<br />
Das bedeutet: Es ist gestattet: das Werk vervielfältigen, verbreiten und öffentlich <br />
zugänglich machen, Abwandlungen bzw. Bearbeitungen des Inhaltes anfertigen zu den folgenden <br />
Bedingungen: <br />
Namensnennung. Sie müssen den Namen des Autors/Rechteinhabers in der von ihm festgelegten <br />
Weise nennen. Keine kommerzielle Nutzung. Dieses Werk darf nicht für kommerzielle Zwecke <br />
verwendet werden. Weitergabe unter gleichen Bedingungen. Wenn Sie den lizenzierten Inhalt <br />
bearbeiten oder in anderer Weise umgestalten, verändern oder als Grundlage für einen anderen <br />
Inhalt verwenden, dürfen Sie den neu entstandenen Inhalt nur unter Verwendung von <br />
Lizenzbedingungen weitergeben, die mit denen dieses Lizenzvertrages identisch oder <br />
vergleichbar sind.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15816Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:43:59Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
[[Bild:333.jpg]]<br />
COM-Port ist geöffnet. Die Button sind inaktiv und werden erst wieder aktiv, wenn die Verbindung getrennt wurde.<br />
== Das Programm samt Sourcecode kann hier [http://www.inter-save.com] im Downloadbereich herunter geladen werden ==</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15815Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:41:30Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
<br />
== Das Programm samt Sourcecode kann hier [http://www.inter-save.com] im Downloadbereich herunter geladen werden ==</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15814Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:39:36Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
<br />
== Das Programm samt Sourcecode kann hier im Downloadbereich herunter geladen werden ==<br />
[http://www.inter-save.com]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15813Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:34:52Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
<br />
== Hier kann das Programm samt Sourcecode herunter geladen werden ==</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15812Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:33:52Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.<br />
<br />
Hier kann das Programm samt Sourcecode herunter geladen werden.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Datei:333.jpg&diff=15811Datei:333.jpg2009-12-11T11:27:31Z<p>Holzi: COM-Port ist geöffnet. Die Button sind inaktiv und werden erst wieder aktiv, wenn die Verbindung getrennt wurde.</p>
<hr />
<div>COM-Port ist geöffnet. Die Button sind inaktiv und werden erst wieder aktiv, wenn die Verbindung getrennt wurde.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15810Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:26:17Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.<br />
<br />
[[Bild:222.jpg]]<br />
COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Datei:222.jpg&diff=15809Datei:222.jpg2009-12-11T11:25:13Z<p>Holzi: COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.</p>
<hr />
<div>COM-Port ist ausgewählt. Alle anderen Parameter sind eingestellt.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15808Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:23:32Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[bild:111.jpg|111.jpg]]<br />
Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Datei:111.jpg&diff=15807Datei:111.jpg2009-12-11T11:20:25Z<p>Holzi: Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.</p>
<hr />
<div>Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15806Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:19:45Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==<br />
[[Bild:111.jpg]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15805Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:18:53Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}<br />
<br />
<br />
== '''Screenshots des Programms''' ==</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15804Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:16:45Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== '''Zur Vollständigkeit hier das ganze Programm''' ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15803Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:15:55Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
Das ist schon das ganze Prinzip, um nur die zur Verfügung stehenden COM-Ports des Computers zu finden. <br />
<br />
== Zur Vollständigkeit hier das ganze Programm ==<br />
<br />
<br />
using System;<br />
<br />
using System.Collections.Generic;<br />
<br />
using System.ComponentModel;<br />
<br />
using System.Data;<br />
<br />
using System.Drawing;<br />
<br />
using System.Linq;<br />
<br />
using System.Text;<br />
<br />
using System.Windows.Forms;<br />
<br />
namespace WindowsFormsApplication1<br />
<br />
{<br />
public partial class Form1 : Form<br />
{<br />
public Form1()<br />
{<br />
InitializeComponent();<br />
}<br />
//******************************************************************<br />
//* Programm beenden *<br />
//******************************************************************<br />
private void button3_Click(object sender, EventArgs e)<br />
{<br />
Application.Exit(); /* Komplette Programm beenden */<br />
}<br />
//******************************************************************<br />
//* Hauptprogramm *<br />
//******************************************************************<br />
private void Form1_Load(object sender, EventArgs e)<br />
{<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i;<br />
ComPort.PortName = (Port);<br />
ComPort.Open();<br />
cmdPortName.Items.Add(Port);<br />
ComPort.Close(); <br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}<br />
// Button setzen<br />
Exit.Enabled = true;<br />
Connect.Enabled = true;<br />
Disconnect.Enabled = false;<br />
// Zur Verfügung stehende COM-Ports suchen<br />
/* Voreinstellungen für den zu öffnenden COM-Port */<br />
cmdPortName.Items.Add("No COM-Port haved available");<br />
cmdPortName.SelectedIndex = 0; <br />
cmdBaudrate.Items.Add("4800"); /* Baudrate */<br />
cmdBaudrate.Items.Add("9600");<br />
cmdBaudrate.Items.Add("19200");<br />
cmdBaudrate.Items.Add("38400");<br />
cmdBaudrate.Items.Add("57600");<br />
cmdBaudrate.Items.Add("115200");<br />
cmdBaudrate.SelectedIndex = 1; /* Setzen auf 9600 Baud */<br />
cmdDataBits.Items.Add("4"); /* Anzahl der Datenbits*/<br />
cmdDataBits.Items.Add("5");<br />
cmdDataBits.Items.Add("6");<br />
cmdDataBits.Items.Add("7");<br />
cmdDataBits.Items.Add("8");<br />
cmdDataBits.SelectedIndex = 4; /* Setzen auf 8 Datenbits */<br />
cmdParity.Items.Add("Even"); /* Parity */<br />
cmdParity.Items.Add("Odd");<br />
cmdParity.Items.Add("None");<br />
cmdParity.Items.Add("Marquage");<br />
cmdParity.Items.Add("Plaque");<br />
cmdParity.SelectedIndex = 2; /* Setzen auf None */<br />
cmdStopBits.Items.Add("1"); /* Anzahl der Stopbits */<br />
cmdStopBits.Items.Add("1.5");<br />
cmdStopBits.Items.Add("2");<br />
cmdStopBits.SelectedIndex = 0; /* Setzen auf 1 Stopbit */<br />
}<br />
//******************************************************************<br />
//* COM-Port öffnen *<br />
//******************************************************************<br />
private void button2_Click(object sender, EventArgs e)<br />
{<br />
// Button setzen<br />
Connect.Enabled = false;<br />
Disconnect.Enabled = true;<br />
Exit.Enabled = false;<br />
// Setzen der Parameter des COM-Ports gemäss gewählten Einstellungen<br />
if (ComPort.IsOpen)<br />
{<br />
ComPort.Close(); // COM-Port ist geöffnet ==> schließen<br />
}<br />
else<br />
{ // COM-Port kann nun geöffnet werden<br />
ComPort.BaudRate = int.Parse(cmdBaudrate.Text);<br />
ComPort.DataBits = int.Parse(cmdDataBits.Text);<br />
ComPort.StopBits = (System.IO.Ports.StopBits)Enum.Parse(typeof(System.IO.Ports.StopBits), cmdStopBits.Text);<br />
ComPort.Parity = (System.IO.Ports.Parity)Enum.Parse(typeof(System.IO.Ports.Parity), cmdParity.Text);<br />
ComPort.PortName = cmdPortName.Text;<br />
ComPort.ReceivedBytesThreshold = 1;<br />
ComPort.NewLine = "\0x13";<br />
ComPort.WriteTimeout = 1000;<br />
ComPort.ReadTimeout = 5000;<br />
ComPort.DtrEnable = true;<br />
ComPort.RtsEnable = false;<br />
//ComPort.Open();<br />
} <br />
}<br />
//***************************************************************************<br />
//* COM-Port schließen *<br />
//***************************************************************************<br />
private void button1_Click(object sender, EventArgs e)<br />
{<br />
ComPort.Close();<br />
// Button setzen<br />
Disconnect.Enabled = false;<br />
Connect.Enabled = true;<br />
Exit.Enabled = true;<br />
}<br />
private void textBox2_TextChanged(object sender, EventArgs e)<br />
{<br />
}<br />
}<br />
}</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15802Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T11:09:26Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
Die Variable Port muss als String deklariert werden. <br />
<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Datei:111.JPG&diff=15801Datei:111.JPG2009-12-11T11:03:26Z<p>Holzi: Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.</p>
<hr />
<div>Nach dem Programmstart stehen in der ComboBox alle zur Verfügung stehenden COM-Ports.</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feststellung_der_zur_Verf%C3%BCgung_stehenden_COM-Ports_auf_dem_Computer&diff=15800Feststellung der zur Verfügung stehenden COM-Ports auf dem Computer2009-12-11T10:42:29Z<p>Holzi: </p>
<hr />
<div>== '''Warum dieses Tutorial?''' ==<br />
<br />
Immer wieder stelle ich fest, dass in einer entwickelten Software, die die seriellen Schnittstellen unterstützt, einfach alle erdenklichen COM-Ports angegeben werden. Vor allem auch Ports, die auf dem Computer gar nicht zur Verfügung stehen. Wird ein solcher Port dann ausgesucht, kommt es entweder innerhalb des Programms zu einer Meldung, dass es den ausgewählten Port nicht gibt oder es kommt sogar zum Absturz des Programms. Das muss alles nicht sein. Auf eine einfache Art und Weise ist es möglich, nur die COM-Ports innerhalb eines Programms anzugeben, die auf dem jeweiligen Computer zur Verfügung stehen.<br />
<br />
<br />
== '''Entwicklungsumgebung''' ==<br />
<br />
Für das hier zu beschreibende Beispiel benutze ich Visual C# 2008. Da dieses Beispiel sehr einfach gehalten ist, kann es schnell auf eine andere Programmiersprache portiert werden. Außerdem ist C# 2008 unter der folgenden Adresse kostenlos zu beziehen.<br />
[http://www.microsoft.com/germany/Express/]<br />
<br />
<br />
== '''Grundgedanke''' ==<br />
<br />
Um alle 255 möglichen COM-Schnittstellen zu finden, soll eine Schnittstelle nach der anderen geöffnet werden. Lässt sie sich öffnen, dann schreibe sie in eine Liste, ansonsten mache nichts und nehme die nächste Schnittstelle. Das ganze muss beim Programmstart durch geführt werden.<br />
<br />
<br />
== '''Das Programm''' ==<br />
<br />
Beim Programmstart wird über eine FOR-Schleife versucht, alle 255 möglichen COM-Ports zu öffnen. Dieses geschieht in der try-Anweisung. Gibt es auf dem Computer die jeweilige Schnittstelle nicht, läuft es auf einen Fehler, der in der catch-Anweisung abgefangen wird. Da aber bei einem Fehler nichts gemacht werden soll, ist die catch-Anweisung leer und es wird versucht, den nächsten COM-Port zu öffnen. Beim Öffnen eines COM-Ports gibt es aber etwas zu beachten. Der jeweilige Port besteht nicht nur aus einer Ziffer (1-255), sondern aus COM1 –COM255. Aus diesem Grunde muss der Portname aus dem String COM und der jeweiligen Nummer zusammen gesetzt werden. Dieses wird mit der Zeile<br />
Port = „COM“ + i;<br />
gemacht. Der so definierte Portname wird zugeordnet und anschließend wird dieser COM-Port geöffnet. Gibt es nun diesen Port nicht, tritt ein Fehler auf und es wird gleich in die catch-Anweisung gesprungen. Da dort aber nichts durchgeführt werden soll, wird i um 1 erhöht und somit wird versucht, den nächsten COM-Port zu öffnen. Ließ sich nun aber der Port öffnen, wird vor dem Schließen des Ports dieser in die ComboBox cmdPortName hinzugefügt.<br />
<br />
// Welche COM-Ports stehen zur Verfügung?<br />
String Port;<br />
for (int i = 1; i < 256; i++)<br />
{<br />
try<br />
{// Öffne den jeweiligen COM-Port und trage den Gefundenen in die ComboBox ein<br />
Port = "COM" + i; // Zusammensetzung des Ports aus COM und der Ziffer<br />
ComPort.PortName = (Port); // Zuordnung des Ports<br />
ComPort.Open(); // Öffnen des Ports<br />
cmdPortName.Items.Add(Port); // Gefundener Port in ComboBox hinzufügen<br />
ComPort.Close(); // Schließen des Ports<br />
}<br />
catch<br />
{<br />
// Der Com-Port kann nicht geöffnet werden<br />
//MessageBox.Show("COM-Port kann nicht geöffnet werden!");<br />
}<br />
}</div>Holzihttps://rn-wissen.de/wiki/index.php?title=AVR-Einstieg_leicht_gemacht&diff=15023AVR-Einstieg leicht gemacht2009-06-21T06:27:36Z<p>Holzi: </p>
<hr />
<div>[[Bild:avr8.jpg|thumb|300px|Einen Controller zum Leben zu erwecken ist nicht schwer, manchmal reichen ein paar Teile! Beispiel mit Mega8]]<br />
==Wir starten mit einem ATMega32== <br />
Immer wieder gibt es in Foren, wie dem Roboternetz, Einsteiger, die das erstemal mit einem [[Microcontroller]] in Berührung kommen. Trotz zahlreicher Einstiegsbeiträge im Forum wiederholen sich doch bestimmte Anfängerfragen immer wieder. Daher soll dieser Artikel noch einmal aufzeigen, wie der ersten Schritt aussieht und einen Controller zum Leben erweckt. Es werden verschiedene Grundschaltungen aufgezeigt und erläutert, welche Bauteile welche Funktion besitzen.<br />
Als Controller verwenden wir einen [[AVR]] [[ATMega32]], der derzeit größte [[AVR]]-Controller, welcher noch im bastlerfreundlichen DIP-Gehäuse verfügbar ist. Für kleine bis mittlere Projekte ein sehr empfehlenswerter Controller, zumal er preislich mit ca. 3-4 Euro noch sehr günstig ist und zudem mit seinem 40-Pin-Gehäuse reichlich Anschlussmöglichkeiten besitzt.<br />
<br />
[[Bild:Mega1632.gif|center]]<br />
<br />
Wie auf dem Bild zu sehen, verfügt auch der etwas günstigere ATMega16 über die gleiche Pinbelegung, daher könnten wir in diesem Tutorial auch diesen Typ verwenden. Der ATMega32 hat aber doppelt soviel Speicherplatz für Programmdaten (Flash), daher hat man für eine geringe Preisdifferenz doch mehr Möglichkeiten.<br />
Wer noch 1-2 Euro sparen will, dem sei der [[ATMega8]] oder [[ATMega168]] empfohlen, diese Typen sind sehr ähnlich, so dass das Tutorial weitgehend auch auf diese Typen bezogen werden kann. Allerdings haben diese Typen deutlich weniger Anschlussmöglichkeiten (28 Pin DIP Gehäuse). <br />
<br />
Die Frage, ob man mit einem fertigen Controllerboard, einer Experimentierplatine oder einem Steckbrett beginnen sollte, wurde ja in dem RN-Wissen Wiki Beitrag "[[Mit welchem Controllerboard fang ich an]]" angesprochen. In den meisten Fällen favorisiert der Autor dieses Artikels ein fertiges Controllerboard. Warum das so ist, dazu am Ende noch ein paar Anmerkungen. Dennoch soll diese Einführung schrittweise anhand eines Steckbrettes erläutert werden.<br />
<br />
==Start mit handelsüblichem Steckbrett==<br />
Ein Steckbrett hat den Vorteil, dass man theoretisch ohne Löten alle Bauteile relativ zügig zusammenstecken kann. Bestimmte Steckkontakte innerhalb einer Reihe sind im Steckbrett miteinander verbunden, so dass man nachher pro Bauteilbeinchen noch einige Steckkontakte zum Verdrahten mit Schaltdraht oder speziell konfektionierter Litze verwenden kann.<br />
<br />
'''Die Vorteile eines Steckbretts:'''<br />
<br />
*Bauteile können ohne Löten eingesetzt und verdrahtet werden<br />
*recht zügiger Schaltungsaufbau<br />
*eine Schaltung kann leicht geändert oder korrigiert werden, defekte Teile sind leicht tauschbar<br />
*ein Steckbrett kann auch für ganz andere Schaltungen verwendet werden<br />
'''Die Nachteile eines Steckbretts gegenüber gedruckten Schaltungen und Experimentierplatinen sind:'''<br />
<br />
*nicht alle Bauteile passen, so dass wir doch noch etwas löten müssen<br />
*nur geringer Schaltungsumfang möglich, da es schnell unübersichtlich wird<br />
*sehr störanfällig wegen grosser Kabellängen, dadurch oft Funktionsstörungen<br />
*Bauteile müssen zum Teil verbogen werden, damit sie passen<br />
<br />
Man beginnt, indem man den Controller AVR [[ATMega32]] auf das Board aufsetzt:<br />
<br />
[[Bild:avrtutorial_steckbrettmega32.jpg|center]]<br />
<br />
==Die Grundschaltung==<br />
Damit ein Controller erst mal zum Laufen kommt, benötigt man zumindest einen 10-k-Widerstand, einen 100-nF-Kondensator und eine 5V-Spannungsquelle. Das Ganze muss entsprechend dem unteren Schaltplan verschaltet werden, man spricht von einer sogenannten Grundschaltung. In dem Schaltplan wurde der Controller im Übrigen pinkompatibel als Schaltzeichen verwendet, die Pinreihenfolge ist also im Schaltplan identisch mit der echten Bauteilpin-Reihenfolge. Diese Darstellung erleichtert den Nachbau der Schaltung auf einem Steckbrett aber auch einer Experimentierplatine ungemein. Gewöhnlich verwendet man in Schaltplänen eine etwas andere Darstellung, bei der die Pins nach Funktionsgruppen geordnet sind. Bei solchen Schaltplänen muss man sich dann anhand der Pin-Nummern orientieren, man wird dies am Ende des Artikels noch bei dem IC MAX232 sehen.<br />
<br />
[[Bild:avrtutorial_grundschaltung_mega32.gif|center|500px]]<br />
<br />
<br />
Wenn man schon einige Grundschaltungen in anderen Tutorials gesehen hat, dann wird man bemerken, dass unsere doch noch etwas einfacher ist und weniger Bauteile benötigt. Hier wird beispielsweise kein Quarz verwendet, da der ATMega32 auch intern einen Takt generieren kann. Wer mit dem ADC genau messen will, sollte statt der Beschaltung im Bild, zwischen Vcc und AVcc eine Spule von 10uH und einen Kondensator von 100nF zwischen AVcc und GND schalten. Will man AVcc als Referenzspannung verwenden, muss noch ein 100nF Kondensator von ARef nach GND.<br />
<br />
Auf dem Steckbrett sieht die obere Schaltung wie folgt aus:<br />
<br />
[[Bild:avrtutorial_steckbrett1.jpg|center]]<br />
<br />
<br />
Um den Controller in Betrieb zu nehmen, benötigt man bei dieser Schaltung ein Netzteil, das eine stabilisierte Spannung von 4 bis 5V liefert. Wir gehen erst einmal davon aus, dass man über dieses verfügt. <br />
Erwähnenswert ist noch, dass der Kondensator als [[Abblockkondensator]] zur Unterdrückung von Störungen dient. Er muss so nah wie möglich an die Spannungszuführung am Controller selbst gesetzt werden. Ohne Kondensator enstehen erhebliche Störungen in der Versorgungsspannung, das Bild verdeutlicht es:<br />
<br />
[[Bild:Abblockkondensator OhneC amAVR.jpg|center]]<br />
<br />
<br />
Der Widerstand in der Grundschaltung dient dazu, die Reset-Leitung konstant auf definiertem High-Pegel zu halten. Verbindet man diesen RESET-Pin später kurz mit GND (Masse), dann wird das Programm im Controller neu gestartet.<br />
<br />
==Woran merkt man, dass der Controller funktioniert?==<br />
Gute Frage! Man merkt es garnicht. Genau genommen funktioniert ja auch trotz korrekter Schaltung noch immer nix, denn es muss zuerst ein Programm in den Controller geladen werden, damit er überhaupt weiss, was zu tun ist. Ohne Programm ist der Controller quasi tot.<br />
<br />
==Wie bekommt man das Programm in den Controller?==<br />
Der Controller verfügt über eine sogenannte [[ISP]]-Schnittstelle. Das bedeutet, über bestimmte Pins ([[SPI]]) kann der Controller mit einer geeigneten PC-Software (zum Beispiel Bascom) programmiert werden. Zum Anschluss an den PC benötigt man jedoch einen sogenannten ISP-Dongle, auch Programmieradapter genannt. Hier gibt es verschiedene Lösungen, serielle und parallele Adapter. Original von Atmel oder kompatible Lösungen. Der am meisten verwendete ISP-Dongle wird am Druckerport betrieben. Diese gibt es inzwischen recht preiswert, sodass sich das Selbstbauen eigentlich nicht lohnt. Da man auch gern auf ein paar Fehlerquellen verzichten sollte, würde ich eine Fertiglösung empfehlen. Wer ihn selbst bauen möchte, findet ([[AVR-ISP_Programmierkabel|hier]] eine ISP-Dongle-Bauanleitung und sogar eine fertige Platine dafür ([[AVR-ISP_Programmierkabel]]).<br />
<br />
Sowas sieht dann so aus:<br />
<br />
[[Bild:Avrtutorial_ispkabel.jpeg|center]]<br />
<br />
<br />
Der Schaltplan eines solchen Programmierkabels:<br />
<br />
<br />
[[Bild:ispschaltplan.gif|center|thumb|400px|Schaltplan des ISP-Dongels nach unserem Wiki-Bauplan, mit SUB-D Buchse. Bitte beachten, dass das IC1 hier im Plan als verschiedene Blöcke (IC1A/IC1B) dargestellt wird. Dies dient nur zur Übersicht, es handelt sich nur um ein IC, einfach auf die Pinnummern achten. Zum vergrößern anklicken.]]<br />
<br />
Ein noch einfacheres Programmierkabel ist auf der Seite http://thomaspfeifer.net/ beschrieben.<br />
Dort findet man unter "AVR-Projekte" den Artikel "Ein einfaches Programmierkabel für Atmel-AVR Mikrocontroller".<br />
Will man dieses Kabel verwenden, sollte man in BASCOM unter "Options/Programmer" den Programmertyp "Samples Electronic Programmer" wählen, sonst funktioniert das Autodetect, das die eingestzte Version des AVR (Mikrocontroller) erkennt nicht.<br />
<br />
<br />
Das Problem ist nun, wie schließe ich einen handelsüblichen ISP-Programmieradapter an den Controller auf dem Steckbrett an? Der normale 10-polige Wannenstecker (nach [[RN-Definitionen]]) passt nicht in ein Steckbrett. Das ist wieder so ein typischer Nachteil bei Steckbrettern! In unserem Beispiel haben wir dazu auf einem kleinen Stück Experimentierplatine einen steckbaren Adapter für das Steckboard gelötet.<br />
Somit kann man die Schaltung um einen üblichen 10-poligen ISP-Programmieranschluss ergänzen:<br />
<br />
<br />
[[Bild:avrtutorial_grundschaltung_mitisp.gif|center|500px]]<br />
<br />
<br />
<br />
Auf dem Steckbrett sieht das gleiche so aus:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_mitisp.jpg|center]]<br />
<br />
<br />
Jetzt endlich ist es soweit, jetzt kann man den Controller über einen ISP-Programmieradapter mit dem PC verbinden. Aber unbedingt darauf achten, dass auch alles korrekt nach Schaltplan gesteckt wurde und dass die Betriebsspannung 5V nicht übersteigt. Ansonsten könnte man sich Dongle oder sogar die PC-Schnittstelle beschädigen.<br />
Als Entwicklungsumgebung nutzen wir hier im Tutorial [[Bascom]]. [[Bascom]] ist ein sehr beliebter Basic-[[Compiler]], der zahlreiche [[AVR]] Controllertypen programmieren kann. Da auch ein [[Terminalprogramm]] und ein Programmer integriert ist, enthält diese PC-Software alles, was man braucht, das erleichtert den Einstieg zusätzlich. Die Software gibts kostenlos als Demo bis 4K Code, für unsere Beispiele und den Einstieg reicht das allemal, siehe dazu Artikel Bascom.<br />
<br />
Wie man ein Programm schreibt, kompiliert und überträgt, wurde schon in diesem Beitrag [[Bascom - Erstes Programm in den AVR Controller übertragen]] ausführlich behandelt, wir ersparen uns deshalb diese Details. Man sollte aber bei Unklarheiten zum Kompilieren und Übertragen diesen Artikel auf jeden Fall lesen.<br />
<br />
Als erstes kompilieren und übertragen wir folgendes Programm:<br />
<br />
<br />
<pre><br />
'###################################################<br />
'step1.bas.BAS<br />
'für<br />
'RoboterNetz.de AVR Tutorial in RN-Wissen<br />
'<br />
'Autor: Frank Brall<br />
'Weitere Beispiele und Beschreibung der Hardware<br />
'unter<br />
' http://www.Roboternetz.de oder<br />
' http://www.Roboternetz.de/wissen<br />
'#######################################################<br />
<br />
$regfile = "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 32<br />
$crystal = 1000000<br />
<br />
Do<br />
Loop<br />
<br />
End<br />
</pre><br />
<br />
Das Programm macht eigentlich nichts, außer dass es eine Endlosschleife ausführt. Aber da wir noch überhaupt nix am Controller angeschlossen haben, können wir eh noch nicht sehen, ob ein Programm nun richtig ausgeführt wird oder nicht.<br />
Allerdings können wir schonmal üben, das Programm mit Bascom zu übertragen. Wenn wir alles richtig aufgebaut haben und Spannung anliegt, dann sollte automatisch der Controller in Bascom erkannt werden. Die Übertragung sollte dann ohne Fehlermeldung erfolgen können. Wenn wir das geschafft haben, geht’s weiter.<br />
<br />
==Läuft die Schaltung und das Programm?==<br />
Damit wir nun endlich sehen, ob sich bei unserer Schaltung auch was tut, schließen wir eine LED über einen 1K-Vorwiderstand an einen Port an. Da wir die Kathode an den Controllerpin und die Anode an Plus legen, leuchtet die LED immer dann, wenn dieser Pin auf Low geschaltet wird.<br />
<br />
[[Bild:avrtutorial_grundschaltung_mitled.gif|center|500px]]<br />
<br />
<br />
Auf dem Steckbrett sieht's nun so aus:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_mitled.jpg|center]]<br />
<br />
<br />
Damit man nun auch wirklich sieht, ob das Programm läuft, schreiben wir ein kleines Basic-Programm, welches eine LED abwechselnd ein– und ausschaltet. Wir kompilieren und übertragen also folgendes Programm:<br />
<br />
<pre><br />
'###################################################<br />
'step2.bas.BAS<br />
'für<br />
'RoboterNetz.de AVR Tutorial in RN-Wissen<br />
'<br />
'Autor: Frank Brall<br />
'Weitere Beispiele und Beschreibung der Hardware<br />
'unter<br />
' http://www.Roboternetz.de oder<br />
' http://www.Roboternetz.de/wissen<br />
'#######################################################<br />
<br />
$regfile = "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 32<br />
$crystal = 1000000<br />
<br />
Config Portc.0 = Output 'Ein Pin wird als Ausgang konfiguriert PC0 (also Pin0 von Port C)<br />
<br />
Do<br />
Portc.0 = 1 'Pin wird auf High, also 5V geschaltet<br />
Waitms 100<br />
Portc.0 = 0 'Pin wird auf Low, also 0V geschaltet<br />
Waitms 100<br />
Loop<br />
<br />
End<br />
</pre><br />
<br />
<br />
Wenn die LED nun schnell blinkt, dann funktioniert die aufgebaute Schaltung perfekt. Wir haben gleichzeitig gelernt, wie man einen Ausgangsport, also Controllerpin, ein- und ausschalten kann. Nahezu alle Pins beim ATMega32 können auf diese Weise als Ausgangsport betrieben werden. Somit lassen sich nicht nur viele Leds, sondern unter Zuhilfenahme eines Treibers (z.B. Transistors) auch Relais und andere Aktoren schalten.<br />
<br />
==Eingangsport fragt Taster ab==<br />
Nun erweitern wir die Schaltung noch um einen Taster. Nahezu jedes Port kann bei einem ATMega32 auch per Software als Eingangsport konfiguriert werden. Wir schließen z.B. einen Taster an Port-Pin PA7 an. <br />
<br />
<br />
[[Bild:avrtutorial_grundschaltung_mittaster.gif|center|500px]]<br />
<br />
<br />
Das Port wird in der Software so konfiguriert, dass es als Eingang arbeitet und intern über einen hohen Widerstand (Pullup-Widerstand) ständig auf High-Pegel gelegt wird. Wird nun eine Taste gedrückt, so wird der Pegel auf Low gezogen.<br />
Das Beispielprogramm ist nun so gestaltet, dass bei gedrückter Taste die LED leuchtet und beim Loslassen wieder ausgeht.<br />
<br />
<br />
<pre><br />
'###################################################<br />
'step3.bas.BAS<br />
'für<br />
'RoboterNetz.de AVR Tutorial in RN-Wissen<br />
'<br />
'Autor: Frank Brall<br />
'Weitere Beispiele und Beschreibung der Hardware<br />
'unter<br />
' http://www.Roboternetz.de oder<br />
' http://www.Roboternetz.de/wissen<br />
'#######################################################<br />
<br />
<br />
$regfile = "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 32<br />
$crystal = 1000000<br />
<br />
Config Portc.0 = Output 'Ein Pin wird als Ausgang konfiguriert PC0 (also Pin0 von Port C)<br />
<br />
Config Pina.7 = Input 'Ein Pin (PA0) wird als Eingang definiert<br />
Porta.7 = 1 'Interner Pullup Widerstand ein<br />
<br />
<br />
Do<br />
If Pina.7 = 1 Then<br />
Portc.0 = 1 'Pin wird auf High, also 5V geschaltet<br />
Else<br />
Portc.0 = 0 'Pin wird auf Low, also 0V geschaltet<br />
End If<br />
Loop<br />
<br />
<br />
End<br />
</pre><br />
<br />
==Grundschaltung mit Quarz==<br />
Obwohl wir ab der letzten Schaltung schon einiges mit dem Controller anfangen können, so fehlt doch noch etwas Wichtiges. Oft ist es nämlich notwendig, dass ein Controller sehr genaue Frequenzen mißt oder ganz genaue Taktraten ausgeben kann. Leider ist der interne Taktgenerator nicht 100% exakt, was bei manchen Anwendungen störend ist. Zum Beispiel können über die RS232-Schnittstelle Daten nicht immer ganz fehlerfrei übertragen werden, wenn die Taktfrequenz nicht genau stimmt. Daher wird in den meisten Anwendungsfällen ein Quarz zur Takterzeugung genutzt, Sie kennen das sicher aus anderen Grundschaltungen. Also erweitern wir unsere Schaltung gleich noch um einen Quarz mit den zugehörigen 22pF-Kondensatoren.<br />
<br />
<br />
[[Bild:avrtutorial_grundschaltung_mitquarz.gif|center|500px]]<br />
<br />
<br />
Auf unserem Steckbrett wird's langsam voller, hier sieht's also inzwischen so aus:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_mitquarz.jpg|center|500px]]<br />
<br />
<br />
Normalerweise sollte der Quarz genauso wie die beiden 22pF-Kondensatoren, die zum Anschwingen des Quarzes dienen, möglichst nahe am Controller platziert werden. Auf dem Steckbrett ist das manchmal gar nicht so einfach, insbesondere wenn man wie in diesem Fall den Quarz erst später hinzufügt. Wichtig ist nämlich, dass die Leitungen vom Quarz zum Controller möglichst kurz sind, bei gedruckten Schaltungen oft nur 1 bis 2 cm! Auch die einzelnen Bauteilbeinchen, z.B. der Kondensatoren, sollten normalerweise so kurz wie möglich sein.<br />
Ist dies nicht der Fall, wie auch in unserem Bild, dann fungieren diese Leitungen fast wie eine Funkantenne. Dies führt in der Regel zu starken Hochfrequenzsignalen, die nicht nur unsere Schaltung, sondern auch andere Schaltungen in der Nähe stören könnten. Man merkt dies auch oft daran, dass sich ein Board bei höherer Quarzfrequenz immer seltener fehlerfrei ohne Übertragungsfehler programmieren läßt.<br />
Grundsätzlich sind daher Schaltungen mit Quarz auf einem Steckbrett nicht sonderlich zu empfehlen, die Betriebssicherheit ist nicht immer gegeben. <br />
<br />
Auch wenn nun ein Quarz angeschlossen ist, so wird er noch immer nicht genutzt. Noch immer arbeitet der [[ATMega32]] mit seiner intern voreingestellten 1 Mhz Taktfrequenz. Um dies umzustellen, muss man ein sogenanntes [[Fusebits|Fusebit]] im Controller umprogrammieren. Auch dies wurde schon im Beitrag [[Bascom - Erstes Programm in den AVR_Controller übertragen]] näher beschrieben. Hier sei daher nur nochmals gesagt, dass dies auch sehr bequem in [[Bascom]] erfolgt:<br />
<br />
<br />
[[Bild:avrtutorial_bascomfusebitquarz.gif|center]]<br />
<br />
<br />
Sobald wir das umgestellt haben, müssen wir auch in dem Programm die Anweisung <br />
<br />
$crystal = 1000000 <br />
<br />
durch <br />
<br />
$crystal = 16000000 <br />
<br />
ersetzen, denn unser Quarz taktet nun mit 16 MHz.<br />
<br />
==Spannung stabilisieren==<br />
Auch wenn unsere Basis-Schaltung für Experimente inzwischen schon ganz nett ist, so ist es doch etwas ungünstig, dass wir stets 5V zur Verfügung haben müssen. Nicht immer steht ein geeignetes Netzteil zur Verfügung, zudem soll ein Controller auch oft mit Batterien versorgt werden. Aus diesem Grund verfügen fast alle Entwicklungsboards wie ([[RN-Control]], STK500 etc.) über einen [[Spannungsregler]].<br />
[[Bild:78s05.jpg|thumb|Spannungsregler 78S05]] Dieser wandelt eine höhere Eingangsspannung (ca. 7 bis 20 V) immer genau in 5V um. Sowas erhöht die Betriebssicherheit einer Schaltung nochmals immens. Als [[Spannungsregler]] (IC2) wird oft der 7805 genutzt.<br />
Die beiden 100nF-Kondensatoren sind wichtig, sie sollen HF-Störungen und Schwingungen vermeiden. Der Elko vor dem Spannungsregler ist vor allem dann wichtig, wenn die Spannung von einem Netzgerät kommt und noch etwas geglättet werden muss. Je höher der Strombedarf der Schaltung, desto größer muss man die Kapazität wählen. Es schadet nicht, wenn man den Elko einige Nummern größer wählt, man ist dann quasi für alle Fälle gerüstet. So sind Werte zwischen 100 uF und 2200 uF durchaus denkbar.<br />
<br />
Wir erweitern unsere Schaltung somit wie folgt:<br />
<br />
<br />
[[Bild:avrtutorial_grundschaltung_spannung.gif|center|500px]]<br />
<br />
<br />
Auf dem Steckbrett sieht's wie folgt aus:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_spannung.jpg|center]]<br />
<br />
==Daten und Texte zum PC übertragen==<br />
In vielen Programmen müssen Daten oder Texte vom Controller an den PC oder umgekehrt gesendet werden. Insbesondere bei komplexen Programmen kann man auf diese Weise Variableninhalte ausgeben und somit auch Fehler im Programmcode schneller finden und korrigieren. In der Regel ist das ganz einfach, denn der [[Microcontroller]] [[ATMega32]] verfügt über einen internen [[UART]], also ein Modul, das Daten über die [[RS232]]-Schnittstelle zum PC senden bzw. auch von ihm empfangen kann. Leider arbeitet jedoch die Controllerschnittstelle mit 5V und die PC-Schnittstelle der Norm entsprechend mit +-12V. Daher muss unbedingt ein Schaltkreis dazwischen, welcher die Pegel anpasst. Gewöhnlich nimmt man hier das IC MAX232(CPE), welches inzwischen sehr preiswert erhältlich ist.<br />
<br />
Wir müssen also die Schaltung nochmals erweitern.<br />
<br />
<br />
[[Bild:avrtutorial_grundschaltung_max232.gif|center|500px]]<br />
<br />
<br />
Das IC Max232 ist im Schaltplan in der üblichen funktionsorientierten Darstellung gezeichnet. Zur besseren Übersichtlichkeit wurden die immer benötigten Anschlüsse für VCC (Pin 16) und GND (Pin 15) getrennt oben rechts im Schaltplan dargestellt. Also nicht vergessen !!<br />
<br />
Auf dem Steckbrett sieht's so aus:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_max232.jpg|center|500px]]<br />
<br />
<br />
Über eine dreipolige Stiftleiste ([[RN-Definitionen]]) wird nun das Steckboard mit der [[RS232]]-Schnittstelle des PC verbunden. Es ist nun ein Leichtes, mit einem Programm Daten zum PC zu senden. Das nachfolgende Programm gibt Hinweise mit der Anweisung '''PRINT''' aus:<br />
<br />
<br />
<pre><br />
'###################################################<br />
'step5.bas.BAS<br />
'für<br />
'RoboterNetz.de AVR Tutorial in RN-Wissen<br />
'<br />
'Autor: Frank Brall<br />
'Weitere Beispiele und Beschreibung der Hardware<br />
'unter<br />
' http://www.Roboternetz.de oder<br />
' http://www.Roboternetz.de/wissen<br />
'#######################################################<br />
<br />
<br />
$regfile = "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 32<br />
$crystal = 16000000<br />
$baud = 9600<br />
<br />
Config Portc.0 = Output 'Ein Pin wird als Ausgang konfiguriert PC0 (also Pin0 von Port C)<br />
<br />
Config Pina.7 = Input 'Ein Pin (PA0) wird als Eingang definiert<br />
Porta.7 = 1 'Interner Pullup Widerstand ein<br />
<br />
<br />
Do<br />
If Pina.7 = 1 Then<br />
Portc.0 = 1 'Pin wird auf High, also 5V geschaltet<br />
Print "Schalter nicht gedrückt"<br />
Else<br />
Portc.0 = 0 'Pin wird auf Low, also 0V geschaltet<br />
Print "Schalter gedrückt"<br />
End If<br />
Wait 1<br />
Loop<br />
<br />
End<br />
</pre><br />
<br />
==Möglichkeiten des Steckbrettes erreicht==<br />
Inzwischen füllt der Schaltplan fast ein DIN-A4-Blatt und auf dem Steckbrett sieht's auch schon recht wirr aus, dabei haben wir nur die wichtigsten Grundelemente auf dem Steckbrett. Für eine Roboter-Steuerung oder andere Anwendung fehlt doch noch einiges. Zum Beispiel weitere Taster, weitere LEDs, Motortreiber, damit der Controller auch Motoren ansteuern kann und ein [[I2C]]-Bus-Anschluss.<br />
Dies alles noch auf einem Steckbrett zu realisieren macht wenig Sinn, zumal bereits jetzt schon durch die doch recht langen Leitungen/Verkabelungen erhebliche Störungen auftreten. In der letzten Phase ist es immer öfters zu Übertragungsfehlern beim Programmieren gekommen, oft musste dies 20mal wiederholt werden. Dies zeigt, dass ein Steckbrett bestenfalls für ganz kleine Controller-Experimente herhalten kann. Für größere Dinge sollte man dann doch zu einer Lösung auf einer gedruckten Platine greifen. Spezielle Experimentierboards bieten mehr Sicherheit und haben neben den Grundelementen, die hier beschrieben wurden, noch eine ganze Menge mehr drauf. Bei [[RN-Control]] zum Beispiel 5 Tasten, 8 Leds, Motortreiber, Lautsprecher, diverse Anschlüsse etc. <br />
Der Größenunterschied wird im Bild deutlich:<br />
<br />
<br />
[[Bild:avrtutorial_steckbrett_rncontrol.jpg|center|500px]]<br />
<br />
<br />
Auch wenn das Steckbrett also kein Controllerboard ersetzen kann, so hat das kleine Tutorial doch gezeigt, wie eine [[Avr]]-Schaltung aufzubauen ist. Dieses Wissen sollte man auch besitzen, wenn man ein Controllerboard nutzt. <br />
<br />
<br />
==Was braucht man, wenn man mit einem Controllerboard den Einstieg startet?==<br />
[[Bild:avrtutorial_ispkabel.jpg|thumb|ISP-Programmierkabel]]Neben dem eigentlichen Board braucht man, wie schon zuvor angesprochen, ein [[AVR-ISP Programmierkabel]]. Wenn der PC noch einen Parallelport oder RS232 Port on Board hat, kann man ein einfaches Programmierkabel nutzen. Das kann man selbst bauen oder auch fertig mitzubestellen (siehe Bild). <br />
Wenn man nur USB zur verfügung hat, wird man den Programmer wohl kaufen müssen, denn USB-RS232 oder USB-LPT Adapter funktionieren fast nie mit den einfachen Programmern, die man gut selber bauen kann. Die Kombination aus eine USB-RS232 und einem Intelligenten Seriellen Programmer (z.B. STK500) funktioniert dagegen.<br />
<br />
Als zweites braucht man natürlich eine Stromversorgung. Ideal sind Gleichspannungsnetzgeräte, die zwischen 9 und 12V liefern, vorausgesetzt, das Board hat einen Spannungsregler wie in der Regel die RN-Boards. Man kann hier ein normales Steckernetzteil oder ein komfortables Labornetzteil nehmen. Um etwas Reserve zu haben, wäre es gut, wenn das Netzteil mindestens 200 mA (mit Motoren besser 1 A) liefern kann. Der Controller selber baucht nur etwa 1 mA je MHz Taktfrequenz.<br />
Alternativ kann man auch Akkupacks oder Batterien nutzen, allerdings mindestens 7,2V sollten die schon liefern können, sicherer sind 8,4-, 9,6- oder 12V-Akkus.<br />
Das wäre eigentlich schon das Wichtigste, um ein Board in Betrieb zu nehmen und Experimente zu machen. <br />
<br />
Allerdings, ein RS232-Kabel ist ebenfalls noch sehr empfehlenswert. Dieses erlaubt die Ausgabe von Texten und Variablen auf den PC, wir haben es ja oben im Steckbrettbeispiel schon gesehen. Dazu wird auf dem PC ein [[Terminalprogramm]] gestartet und über die [[RS232]] Schnittstelle mit dem PC verbunden. Bei manchen Boards ist sowieso ein RS232 Kabel unerläßlich, wie z.B. RN-Motor, RN-Speak etc. Nützlich ist es aber überall. Man kann ein solches Kabel selbst bauen oder gleich beim Kauf eines Boardes mitbestellen.<br />
<br />
Also nochmal die Zusammenfassung für den Einstieg:<br />
<br />
* Controllerboard<br />
* [[AVR-ISP Programmierkabel]] mit 10-poligem Wannenstecker<br />
* RS-232-Kabel (mit 3-poligem Adapter, wenn Board [[RN-Definitionen]] erfüllt)<br />
* Netzgerät oder Akku (ideal 9 bis 12V, notfalls auch 7,2 bis 20V)<br />
* [[Bascom]]-Compiler-Vollversion ist nur nötig, wenn man gleich größere Sachen anstrebt, ansonsten reicht das Demo, genauso wie ein [[Avr-gcc]]-Compiler. Bei RN-Boards sind diese Programme beim Board- oder Platinenkauf sowieso dabei, ansonsten kann man diese im Internet downloaden.<br />
* Ein gutes Buch ist immer gut, siehe [[Buchvorstellungen]]<br />
<br />
==Autor==<br />
*[[Benutzer:Frank|Frank]]<br />
<br />
<br />
===Quellen===<br />
* [[Abblockkondensator]] Artikel von Uwegw<br />
* RN-Board Dokumentationen aus [[:Kategorie:Projekte]]<br />
* diverse Datenblätter<br />
<br />
==Siehe auch==<br />
*[[AVR-ISP Programmierkabel]]<br />
*[[Mit welchem Controllerboard fang ich an]]<br />
*[[Abblockkondensator]]<br />
*[[Bascom]]<br />
*[[Bascom - Erstes Programm in den AVR_Controller übertragen]]<br />
*[[Avr]]<br />
*[[Atmel Controller Mega16 und Mega32]]<br />
*[[Spannungsregler]]<br />
<br />
<br />
[[Kategorie:Robotikeinstieg]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Projekte]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=ATmega48_ATmega88_ATmega168_ATmega328&diff=15022ATmega48 ATmega88 ATmega168 ATmega3282009-06-21T06:25:42Z<p>Holzi: </p>
<hr />
<div>Diese Controllertypen sind bis auf einige spezielle Funktionen pinkompatibel<br />
<br />
===Mega8===<br />
*ATMega AVR 8-16 PDIP<br />
*Gehäuse: DIL-28<br />
*MHz: 16<br />
*Flash: 8<br />
*EEProm: 512<br />
*RAM: 1K<br />
*I/ O: 23 <br />
*Betriebsspannung: 4.5 - 5.5V, bzw. 2,7 - 5.5V in L Version (max. 8 MHz)<br />
<br />
===Mega48===<br />
*ATMega AVR 48-20 PDIP<br />
*Gehäuse: DIL-28<br />
*MHz: 20<br />
*Flash: 4 kByte<br />
*EEProm: 256 Byte<br />
*RAM: 512 Byte<br />
*I/ O: 23<br />
*Betriebsspannung: 2.7 - 5.5V ; 1.8 -5.5 in "V" Version<br />
<br />
===Mega88===<br />
*ATMega AVR 88-20 PDIP<br />
*Gehäuse: DIL-28<br />
*MHz: 20<br />
*Flash: 8 kByte<br />
*EEProm: 512 Byte<br />
*RAM: 1024 Byte<br />
*I/ O: 23<br />
*Betriebsspannung: 2.7 - 5.5V ; 1.8 -5.5 in "V" Version<br />
<br />
===Mega168===<br />
*ATMega AVR 168-20 PDIP<br />
*Gehäuse: DIL-28<br />
*MHz: 20<br />
*Flash: 16 kByte<br />
*EEProm: 512 Byte<br />
*RAM: 1 kByte<br />
*I/ O: 23<br />
*Betriebsspannung: 2.7 - 5.5V ; 1.8 -5.5 in "V" Version<br />
<br />
http://www.roboternetz.de/wiki/uploads/Main/pinbelegungmega8_168.gif<br />
<br />
=== Unterschiede zwischen Mega8 und Mega88===<br />
<br />
Der Mega88 ist zwar nicht als Ersatz für den Mega8 entwickelt worden, kann aber auf Grund der <br />
Pin-Kompatibilität sehr leicht in bestehenden Schaltungen ersetzt werden.<br />
Einige Besonderheiten müssen dabei bei der Programmierung berücksichtigt werden.<br />
<br />
Die wichtigsten Verbesserungen des ATmega88 gegenüber dem ATmega8 im Überblick:<br />
<br />
*Schnellere Taktfrequenz bis 20MHz<br />
*Geringerer Energieverbrauch<br />
*Schnellere EEPROM Schreibzugriffe<br />
*On-Chip Deggugging möglich mit DebugWire (über den RESET Pin)<br />
*Pin Change Interrupt auf allen Eingangs Pins<br />
*1.1V kalibrierte Referenzspannung im ADC gegnüber 2.56V beim Mega8; (Signalspannungen sind leichter teilbar als multiplizierbar)<br />
*Timer 0,2 erweitert um PWM und Compare Einheit<br />
*Ausgabe des Systemtaktes auf einen I/O Pin<br />
*Extra Register für UBRRnH (UART Teiler)<br />
*Programmierbarer Teiler für den Takt<br />
<br />
=== Mega88P, Mega88PA ===<br />
Dies sind neue leicht verbesserte Versionen: <br />
* noch geringerer Stromverbrauch <br />
* 32 kHz Oszillator Mode mit weniger Amplitude<br />
* keine seperate Version für niedrige Spannung mehr<br />
<br />
=== Unterschiede zwischen Mega48, Mega88 und Mega 168===<br />
<br />
Die Unterschiede beschränken sich im wesentlichen auf den internen Speicher:<br />
<br />
{| {{Blauetabelle}}<br />
|<br />
|'''ATmega48'''<br />
|'''ATmega88'''<br />
|'''ATmega168'''<br />
|-<br />
|FLASH(bytes)<br />
|4096<br />
|8192<br />
|16384<br />
|-<br />
|EEPROM(bytes)<br />
|256<br />
|512<br />
|512<br />
|-<br />
|SRAM(bytes)<br />
|512<br />
|1024<br />
|1024<br />
|-<br />
|Boot Sector Größe(bytes)<br />
|n.v<br />
|256..2048<br />
|256..2048<br />
|-<br />
|FLASH Page Größe(bytes) <br />
|64<br />
|64<br />
|128<br />
|}<br />
<br />
<br />
==Siehe auch==<br />
* [[Atmel]]<br />
* [[AVR]]<br />
* [[HEX Beispiel-Dateien für AVR]]<br />
* [[RN-Mega8]] - Bauanleitung für geeignetes Entwicklungsboard <br />
* [[RN-MiniControl]] - Bauanleitung für geeignetes Entwicklungsboard <br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Elektronik]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Programmer&diff=15021Programmer2009-06-21T06:23:07Z<p>Holzi: </p>
<hr />
<div>== Einführung ==<br />
Als '''Programmer''' wird die Hardwarekomponente bezeichnet, mit der das ausführbare Mikrocontrollerprogramm (Firmware, HEX-File) auf den Controller übertragen wird. Es gibt verschiedene Konzepte der Programmübertragung. Neben dem Konzept des Bootloaders, der Parallelprogrammierung und des [[JTAG]]-Interfaces, spielt bei [[Atmel]] Mikrocontrollern das Verfahren des "serial Download" eine große Rolle. Bekannt ist diese Variante der Programmierung als ISP (In System Programmierung). Dabei wird das [[SPI]] (Serial Processor Interface) genutzt, welches bei fast allen [[AVR]]-Controllern zu finden ist. ISP-Programmer zeichnen sich dadurch aus, dass der Hardwareaufwand für diese sehr gering ist. Das hat natürlich Auswirkungen auf den Preis. Für einen "Standard" [[ISP]] Parallel-Programmer liegen die Materialkosten im Cent-Bereich. Bei solchen "billig" Programmern werden die eigentlichen Programmierprotokolle (siehe Abschnitt Memory Programing in AVR Datenblättern) durch ein entsprechendes Programm auf dem PC erzeugt ([[AVR]]-Prog, PonyProg, YAAP, AVRDUDE, [[Bascom]] usw.) und die Programmerhardware ist bestenfalls zur Pegelanpassung da. Letztlich gibt es sogar derartige Programmer, die nur aus drei Schutzwiderständen bestehen. Meist wird aber ein kleiner preiswerter Treiberbaustein eingebaut, der für eine sichere Datenübertragung auch bei längeren Programmierkabeln sorgt. Damit ist ein extrem günstiger Einstieg in die Programmierung von [[Atmel]] AVR-Controllern möglich. Aufwendiger werden dann Programmer, die tatsächlich über eigene "Intelligenz" verfügen. Dabei handelt es sich in der Regel um so genannte Serial-Programmer. Hier erfolgt die Datenübertragung an den Programmer per serieller Schnittstelle oder über [[USB]]. Der Programmer selbst besitzt einen Controller, der die Daten empfängt und das Programmierprotokoll ausführt. Der weit verbreitete SI-Prog (siehe PonyProg) wird zwar an die Serielle Schnittstelle angeschlossen, ist dem Wesen nach aber den Parallelprogrammern äquivalent (einfache Pegelanpassung, keine eigene Intelligenz). Darin liegt auch die Ursache, warum der SI-Prog nie an einem handelsüblichen [[USB]] zu Serial-Adapter laufen wird.<br />
<br />
== Parallelport ISP Programmer ==<br />
<br />
=== STK 200 kompatible Programmer ===<br />
Bei den Parallelportprogrammern handelt es sich oft um Nachbauten von Programmierintrefaces der ersten Starterkits von ATMEL dem STK200 oder STK300. Damit wird auch geworben in dem man diese als STK200 kompatibel oder als sogenannte Standard-ISP-Programmer bezeichnet. Der Vorteil dieser Programmer liegt tatsächlich darin, dass so ziemlich jede Programmersoftware diese unterstützt. <br />
Die Kompatibilität bezieht sich hier auf die Belegung der Leitungen am LPT-Port. Es hat nichts mit der Verwendung eines Treiberschaltkreises bei den meisten dieser Programmer zu tun. <br />
<br />
LPT-Pinning des STK200<br />
SCK = 6;<br />
MOSI = 7;<br />
RESET = 9;<br />
MISO = 10;<br />
<br />
=== SP12 kompatible Programmer ===<br />
Bei dem SP12 (von Steve Bolt) Programmer handelt es sich ursprünglich um eine extrem einfache Lösung, bei der nur drei Schutzwiderstände und keine weitere Pegelanpassung benutzt wurde. Dieser Programmer, zum fast Nulltarif, erfreut sich großer Beliebtheit. Der Hauptgrund dafür liegt aber in seiner Schaltungslösung, die es erlaubt, das Zielsystem über den LPT-Port mit Spannung zu versorgen. Bei der STK200 Schaltung muss der Programmer vom Zielsystem versorgt werden. Es wird beim SP12 also zum Programieren kein zusätzliches Netzteil benötigt. Inzwischen werden ernsthafte SP12 Programmer auch mit einem Bustreiber versehen. <br />
<br />
LPT-Pinning des SP12<br />
VCC = 4,5,6,7,8;<br />
RESET = 3;<br />
SCK = 2;<br />
MOSI = 9;<br />
MISO = 11;<br />
<br />
== Pseudo serielle Programmer (SI-Prog) ==<br />
Ein Programmer, der vor allem wegen seiner guten Unterstützung durch das beliebte PonyProg eine weite Verbreitung erfahren hat, ist der SI-Prog. Dieser wird oft als serieller Programmer bezeichnet. Richtig ist, dass er an den COM-Port des PCs angeschlossen wird. Aber die Schaltung verrät, daß hier die Steuerleitungen wie DTR, RTS und CTS des COM-Ports verwendet werden, um ein [[SPI]]-Protokoll zu fahren. Die eigentlichen Signalleitungen TxD und RxD sind bei diesem Adapter gar nicht angeschlossen. Damit ist es auch beim besten USB-RS232-Adapter nicht möglich, diesen Programmer an einem modernen Notebook anzuschließen, der nur noch über USB verfügt. Deshalb kann PonyProg dann nicht mehr als Programmiertool verwendet werden.<br />
<br />
== Echte serielle Programmer ==<br />
Echte serielle Programmer basieren oft entweder auf dem Atmel Application-Note AN910 oder sind STK500 kompatible Programmer. Allen gemeinsam ist das Vorhandensein eines Controllers mit entsprechender AVR910 oder STK500 kompatibler Firmware. Diese kann meist über einen Bootloader aktualisiert werden. Da ein Controller und eine reguläre RS232 Pegelanpassung (z.B. mit einem MAX232) empfindlich kostenintensiver als das Material für einen Parallelprogrammer ist, sind diese in der Regel auch teurer. Dafür ist aber eine kompatible Lösung erhältlich, die, wie der STK200, durch die meisten Flash-Tools unterstützt wird und es kann diese mit einem handelsüblichen USB-Serial-Adapter auch an Systemen betrieben werden, die, wie viele Notebooks heute, nur noch über USB verfügen. Wichtige Weiterentwicklungen bei den Serialprogrammern ist das AVR911 und das STK500v2 Protokoll. Es sollte beim Neuerwerb darauf geachtet, dass eines dieser aktuellen Protokolle unterstützt wird.<br />
<br />
== USB Programmer ==<br />
Bei USB-Programmern handelt es sich eigentlich nicht um eine eigenständige Gruppe von Programmern, sondern um AVR910 oder STK500 kompatible Lösungen. Das besondere ist hier, dass der Programmer selbst über einen USB-Controller verfügt. Dabei muss ein Treiber für diesen Controller installiert werden, der im System einen virtuellen COM-Port zur Verfügung stellt. Beim Betrieb dieser Programmer gibt es keine Unterschiede zu den seriellen Programmern. Leider sind USB Programmer dadurch, dass die USB Controller recht teuer und ausschließlich in SMD verfügbar sind, als Selbstbauprojekte für Anfänger ungeeignet.<br />
<br />
Für die langsamste USB-Geschwindigkeit kann ein AVR Controller das USB Interface auch emulieren. Es gibt Baupläne für billige Programmierer, die so auf den extra USB Controller verzichten (z.B. USB AVR-Lab). Das USB interface ist allerdings wohl nicht 100% normconform und es könnte dadurch zu Inkompatibilitäten kommen.<br />
<br />
== ISP-Anschluss ==<br />
<br />
=== 10poliger ISP Anschluss ===<br />
Die am meisten verwendete Steckerbelegung, nicht nur Im Roboternetz. Genauere Beschreibung unter [[RN-Definitionen]]. Nahezu alle RN-Bauanleitungen nutzen diese Belegung.<br />
<br />
1 - MOSI<br />
2 - VCC<br />
3 - LED (oft auch unbelegt)<br />
4 - GND<br />
5 - RST<br />
6 - GND<br />
7 - SCK<br />
8 - GND<br />
9 - MISO<br />
10 - GND<br />
<br />
=== 6poliger ISP Anschluss ===<br />
Nur in wenigen Roboternetz-Projekten gebräuchlich. Dieser Stecker spart etwas Platz, ist aber deutlich schwieriger (und teurer) zu bekommen als die zehnpolige Variante. <br />
1 - MISO<br />
2 - VCC<br />
3 - SCK<br />
4 - MOSI<br />
5 - RST<br />
6 - GND<br />
<br />
== Autor ==<br />
*[[Benutzer:Martin Fiedler|Martin Fiedler]]<br />
*Kleinere Änderungen Frank<br />
<br />
<br />
==Siehe auch==<br />
* [[AVR-ISP Programmierkabel]]- Bauanleitung Bauanleitung Parallel Programmer ISP<br />
* [[ISP]]<br />
* [[RN-Definitionen]]<br />
<br />
<br />
==Weblinks==<br />
* [http://www.rowalt.de/mc/avr/progd.htm Rowalt Bauanleitung Parallel Programmer]<br />
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0943.PDF Atmel Serialprogrammer ]<br />
* [http://www.klaus-leidinger.de/mp/Mikrocontroller/AVR-Prog/AVR-Programmer.html Klaus-Leidinger Serialprogrammer Bauanleitung ]<br />
* [http://www.siwawi.arubi.uni-kl.de/avr_projects/evertool/ Bauanleitung Serialprogrammer Englisch Evertool]<br />
* [http://www.fischl.de/usbasp/ USBasp von fischl.de: USB-Programmer für Atmel AVR Controller] - Bauanleitung, Weblinks zu Schaltplänen und Layouts (Eagle, PDF), Linux und Win32, Firmware mit Quelldateien, Win32-Treiber.<br />
* [http://www.avr-projekte.de/isp.htm USB-Programmer Bauanleitung]<br />
* [http://www.matwei.de/doku.php?id=de:elektronik:usbisp USB-Programmer Bauanleitung]<br />
* [http://www.obdev.at/products/avrusb/avrdoper.html USB-Programmer Bauanleitung] - AVR Doper - High Voltage Programmierung<br />
* [http://www.ullihome.de/index.php/Hauptseite#USB_AVR-Lab USB AVR Lab]<br />
* [http://shop.embedit.de/browse_030001002_66__.php embedit.de] Bezugsquelle für sechspoligen Stecker<br />
<br />
<br />
[[Kategorie:Microcontroller]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=EEPROM&diff=15020EEPROM2009-06-21T06:22:22Z<p>Holzi: </p>
<hr />
<div>''Electrically Erasable Programmable Read Only Memory'' <br><br />
Nur-Lese-Speicher, der durch Programmierung löschbar ist. Die Daten bleiben nach abschalten der Betriebsspannung erhalten. EEPROM´s lassen sich mehrfach neu programmieren, allerdings nicht unendlich oft. <br />
Die meisten Controller beinhalten neben Flash-Speicher für den Programmcode auch einen EEPROM-Speicher für wichtige Daten. <br />
<br />
==Siehe auch==<br />
* [[EPROM]]<br />
* [[Flash]]<br />
* [[Atmel]] <br />
* [[avr-gcc#String ins EEPROM legen|avr-gcc: Daten ins EEPROM legen]]<br />
<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Abkürzung]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=AT90S2313&diff=15019AT90S23132009-06-21T06:20:28Z<p>Holzi: </p>
<hr />
<div>'''Versorgungspannung:''' <br />
::AT90S2313-4: 2.7V - 6V<br />
::AT90S2313-10: 4V - 6V<br />
::ATTiny2313-20: 1.8V - 5.5V<br />
'''Flash-Programm-Speicher:''' 2kByte <br><br />
'''EEPROM-Datenspeicher:''' 128Byte <br><br />
'''SRAM-Datenspeicher:''' 128 Byte <br><br />
'''Taktfrequenz:'''<br />
::AT90S2313-4: bis 4MHz<br />
::AT90S2313-10: bis 10MHz<br />
::ATTiny2313-20: bis 20MHz<br />
'''Features:'''<br />
* Full Duplex UART<br />
* ein 8-bit Timer<br />
* ein 16-bit Timer mit PWM, InputCapture, external Clock<br />
* Analog-Comparator<br />
* 15 digitale I/O-Ports<br />
* programmierbarer Watchdog-Timer<br />
'''weitere Features beim Tiny2313:'''<br />
* 4 PWM Kanäle beim Tiny2313<br />
* 18 digitale I/O-Ports, wenn kein externer Quarz und kein Reset benutzt werden<br />
* [[USI (Avr)|Universelle serielle Schnittstelle (USI)]], damit kann [[TWI]] oder [[SPI]] nachgebildet werden<br />
* Pin Change Interrupts an PortB<br />
* Debug-wire<br />
* Interner RC-Oszillator bis 8 MHz<br />
* erweiterte USART, mit Parity-Bit usw.<br />
<br />
<br />
Der AT90S2313 ist heute veraltet. Der Hersteller empfiehlt, für neue Designs den [[ATtiny2313]] zu verwenden.<br />
<br />
<br />
[[Bild:at90s2313tiny.png|center]]<br />
<br />
<br />
==Siehe auch==<br />
* [[Atmel]]<br />
* [[AVR]]<br />
* [[HEX Beispiel-Dateien für AVR]]<br />
<br />
== Packages==<br />
* PDIP 20<br />
* SOIC 20 <br />
<br />
==Weblinks==<br />
* [http://www.atmel.com/dyn/resources/prod_documents/DOC0839.PDF Datenblatt des AT90S2313 (englisches PDF, 92 Seiten, 1.6 MByte)]<br />
* [http://www.atmel.com/dyn/resources/prod_documents/doc4298.pdf AVR091: Replacing AT90S2313 by ATtiny2313 (englisches PDF, 11 Seiten, 118 kByte)]<br />
* [http://www.atmel.com/dyn/resources/prod_documents/doc2543.pdf Datenblatt des ATTiny2313 (englisches PDF, 231 Seiten, 2MB)]<br />
<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Bascom_I2C_Master&diff=15018Bascom I2C Master2009-06-21T06:18:50Z<p>Holzi: </p>
<hr />
<div>In diesem Artikel folgen verschiedene Programmbeispiele, um einen [[AVR]] mit [[Bascom]] zu einem [[I2C]]-Master zu schlumpfen.<br />
<br />
In allen Beispielen wird einem PCF8574 jeweils der Wert &HAA nach einer Pause &H55 gesendet, was als Blinken, evtl. auch als Lauflicht zu erkennen sein kann, falls LEDs an dessen Ports angeschlossen sind.<br />
<br />
[[Bild:RN-Control_PCF8574.JPG|thumb|Beispielumgebung mit PCF8574]]<br />
<br />
<br />
== Software I2C ==<br />
<br />
Die Softwareversion der I2C-Implementierung kann auf allen AVR programmiert werden, man kann sich die Ports auf denen Data (SDA) und Clock (SCL) angeschlossen werden selbst aussuchen.<br />
<br />
Standardmäßig wird von Bascom die Software-Version verwendet um auf den I2C-Bus zuzugreifen, d.H. die einzelnen Bits der zu übertragenden Daten werden per Software auf High- oder Low-Pegel an den Ports ausgegeben. Der AVR kann in dieser Zeit keine anderen Aufgaben erledigen.<br />
<br />
Bei dieser Art I2C zu implementieren wird eine aktuelle Aktivität auf dem Bus nicht beachtet, dies kann zu Problemen führen falls mehr als ein Master am Bus hängt. Siehe Links unter "[[#Siehe_auch|Siehe auch]]".<br />
<br />
<br />
$regfile = "M32def.dat" {{vbcomment|the used chip}}<br />
$crystal = 16000000 {{vbcomment|frequency used}}<br />
$baud = 9600<br />
<font color="#a01010"><br />
Config Scl = Portb.0 {{vbcomment|Ports fuer IIC-Bus, nicht Standard !}}<br />
Config Sda = Portb.1<br />
<!-- das "=" immer mit &#061; angeben, sonst gibts keinen Kommentar !! --><br />
{{vbcomment|Config I2cdelay &#061; 10 ' je höher der Wert umso langsamer der Bus}}<br />
<br />
I2cinit<br />
</font><br />
Const Pcf_write = &H40 {{vbcomment|Slaveadresse}}<br />
Const Pcf_read = &H41<br />
<br />
{{vbcomment|Startausgabe}}<br />
Print<br />
Print "I2C-Soft Demo mit PCF 8574"<br />
Print<br />
<br />
Do<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &HAA<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &H55<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
Loop<br />
<br />
End<br />
<br />
Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).<br />
<br />
Falls mehr als nur ein Byte an einen Slave gesendet werden sollte, und nach dem letzten Byte ERR=1 ist, sollte anschließend ein I2Cstop folgen, da der Slave kein weiteres Byte haben will !<br />
<br />
== Hardware TWI ==<br />
<br />
AVR Controller, die [[I2C]] hardwaremäßig Unterstützen, haben das [[TWI]]-Modul, die Ports für Data und Clock sind dabei vorgegeben. TWI ist bei den meisten ATMegas vorhanden, z.B. dem [[ATMega32]].<br />
<br />
Damit Bascom das TWI-Modul verwendet muss die <tt>i2c_twi.lib</tt> (bzw. <tt>.lbx</tt>, bei der Bascom-Demo) eingebunden werden, ansonsten ist, bis auf die Initialisierung, alles genauso wie bei Software-I2C.<br />
Bei Verwendung der Bascom-I2C-Befehle macht es Performancemäßig keinen großen Unterschied, ob man Software-I2C oder TWI verwendet, denn bei beiden Versionen wird solange darauf gewartet, bis das Byte über den Bus gesendet ist, und ein ACK oder NACK empfangen ist.<br />
<br />
Der Vorteil von TWI ist aber, das es in Multimasterumgebungen besser verträglich ist (z.B. I2CStart). Gibt es nur einen Master, kann man sich für eine der beiden Versionen entscheiden.<br />
<br />
Der Master bestimmt wie schnell die Daten auf dem Bus übertragen werden (Ausnahme: [[Clock_Stretching]] ).<br />
Dafür ist hier die Zeile mit '''<tt>Config TWI</tt>''' zuständig, Bascom berechnet aus der angegebenen Taktfrequenz den richtigen Wert für TWBR um an den gewünschten I2C-Takt zu kommen.<br />
<br />
$regfile = "M32def.dat" {{vbcomment|the used chip}}<br />
$crystal = 16000000 {{vbcomment|frequency used}}<br />
$baud = 9600<br />
<font color="#a01010"><br />
$lib "i2c_twi.lbx" {{vbcomment|Für Hardware TWI}}<br />
<br />
Config Twi = 400000 {{vbcomment|Init TWBR und TWSR}}<br />
<br />
{{vbcomment|TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart !}}<br />
TWCR = &B00000100 {{vbcomment|nur TWEN setzen}}<br />
</font><br />
Const Pcf_write = &H40 {{vbcomment|Slaveadresse}}<br />
Const Pcf_read = &H41<br />
<br />
{{vbcomment|Startausgabe}}<br />
Print<br />
Print "I2C-TWI Demo mit PCF 8574"<br />
Print<br />
<br />
Do<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &HAA<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &H55<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
Loop<br />
<br />
End<br />
<br />
Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).<br />
<br />
Mit der TWI-Lib wird zwar die Hardware benutzt um die Bytes auf den I2C-Bus auszugeben bzw. von dort einzulesen, es wird aber kein Status von TWSR abgefragt, ob die erwartete Reaktion eingetreten ist !<br />
<br />
Unter Zuhilfenahme des Datenblattes könnte eine Highend-Version so aussehen:<br />
<br />
$regfile = "M32def.dat" {{vbcomment|the used chip}}<br />
$crystal = 16000000 {{vbcomment|frequency used}}<br />
$baud = 9600<br />
<font color="#a01010"><br />
$lib "i2c_twi.lbx" {{vbcomment|Für Hardware TWI}}<br />
<br />
Config Twi = 400000 {{vbcomment|Init TWBR und TWSR}}<br />
<br />
{{vbcomment|TWI gleich einschalten, das macht Bascom ansonsten erst beim I2CStart !}}<br />
TWCR = TWEN<br />
</font><br />
Const Pcf_write = &H40 {{vbcomment|Slaveadresse}}<br />
Const Pcf_read = &H41<br />
<br />
{{vbcomment|Startausgabe}}<br />
Print<br />
Print "I2C-TWI High-Demo mit PCF 8574"<br />
Print<br />
<br />
Do<br />
I2cstart<br />
If TWSR = &H08 Then {{vbcomment|Start wurde abgesetzt}}<br />
I2cwbyte Pcf_write {{vbcomment|Slaveadresse ausgeben}}<br />
<br />
If TWSR = &H18 Then {{vbcomment|Slave hat sich gemeldet}}<br />
I2cwbyte &HAA {{vbcomment|Datenbyte ausgeben}}<br />
<br />
If TWSR <> &H28 Then {{vbcomment|Byte erfolgreich übertragen}}<br />
Print "Byte mit NACK quittiert !"<br />
End If<br />
Else<br />
Print "kein Slave !"<br />
End If<br />
Else<br />
Print "Fehler bei Start"<br />
End If<br />
<br />
{{vbcomment|Immer Stop, damit die Buspegel wieder stimmen}}<br />
I2cstop<br />
<br />
Print "E " ; Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 1500<br />
<br />
I2cstart<br />
<br />
If TWSR = &H08 Then {{vbcomment|Start wurde abgesetzt}}<br />
I2cwbyte Pcf_write {{vbcomment|Slaveadresse ausgeben}}<br />
<br />
If TWSR = &H18 Then {{vbcomment|Slave hat sich gemeldet}}<br />
I2cwbyte &H55 {{vbcomment|Datenbyte ausgeben}}<br />
<br />
If TWSR <> &H28 Then {{vbcomment|Byte erfolgreich übertragen}}<br />
Print "Byte mit NACK quittiert !"<br />
End If<br />
Else<br />
Print "kein Slave !"<br />
End If<br />
Else<br />
Print "Fehler bei Start"<br />
End If<br />
<br />
{{vbcomment|Immer Stop, damit die Buspegel wieder stimmen}}<br />
I2cstop<br />
<br />
Print "E " ; Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 1500<br />
<br />
Loop<br />
<br />
End<br />
<br />
Die Printausgaben im Else-Teil sind natürlich nur in der Demo nützlich, in der Praxis entweder den Else-Teil ganz weglassen, oder entsprechende Variablen setzen um den Fehler später zu bearbeiten.<br />
<br />
Eine einfachere Version einen Fehler frühzeitig zu erkennen, ist statt TWSR nur ERR auf 0 zu prüfen.<br />
<br />
<br />
== Hardware USI ==<br />
<br />
Kleinere AVR Controller, die zwar kein TWI-Modul haben, aber [[I2C]] hardwaremäßig Unterstützen, haben das [[USI (Avr)|USI]]-Modul, die Ports für Data und Clock sind dabei vorgegeben. USI ist bei den meisten ATTinys und einigen ATMegas vorhanden, z.B. dem [[ATtiny2313|ATTiny2313]].<br />
<br />
Das [[USI (Avr)|USI]]-Modul kann evtl. als eine Art von TWI-Light angesehen werden, denn es ist nicht so komfortabel wie TWI, es muss intern noch viel in Software erledigt werden, weshalb es Performancemäßig auch keinen großen unterschied macht, ob man Software-I2C oder USI beim Master verwendet.<br />
<br />
Am einfachsten benutzt man die Lib, die unter [[#Weblinks|Weblinks]] aufgeführt ist, denn dann kann man die von Bascom vorgegebenen Befehle benutzen.<br />
<br />
$regfile = "attiny2313.dat" {{vbcomment|the used chip}}<br />
$crystal = 16000000 {{vbcomment|frequency used}}<br />
$baud = 9600<br />
<font color="#a01010"><br />
$lib "i2c_usi.lbx" {{vbcomment|Für Hardware USI-I2C}}<br />
<br />
Config Scl = Portb.7 {{vbcomment|Ports fuer IIC-Bus}}<br />
Config Sda = Portb.5<br />
{{vbcomment|Config I2cdelay &#061; 5 ' je höher der Wert umso langsamer der Bus}}<br />
<br />
I2cinit<br />
</font><br />
Const Pcf_write = &H40 {{vbcomment|Slaveadresse}}<br />
Const Pcf_read = &H41<br />
<br />
{{vbcomment|Startausgabe}}<br />
Print<br />
Print "I2C-USI Demo mit PCF 8574"<br />
Print<br />
<br />
Do<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &HAA<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
I2cstart<br />
I2cwbyte Pcf_write<br />
I2cwbyte &H55<br />
I2cstop<br />
<br />
Print Err {{vbcomment|Err &#061; 0 -> kein Fehler !}}<br />
<br />
Waitms 500<br />
<br />
Loop<br />
<br />
End<br />
<br />
Mit ERR kann nach jedem gesendeten Byte abgefragt werden, ob es mit ACK quittiert wurde (=0), oder nicht (=1).<br />
<br />
Nach I2Cstart (auch I2CStop) kann ERR kontrolliert werden, ob das Start (bzw. Stop) auch auf den Bus abgesetzt werden konnte.<br />
<br />
<br />
== Siehe auch ==<br />
<br />
* [[Avr]] - Infos zu AVR allgemein<br />
* [[I2C|I<sup>2</sup>C]] - Details zu I2C<br />
* [[TWI]] - Two-wire Serial Interface<br />
* [[SPI]] - Serial Peripheral Interface<br />
* [[TWI Praxis]] - Bascom-Beispiele für Hardware TWI<br />
* [[TWI Praxis Multimaster]] - Bascom-Beispiele für Hardware TWI<br />
* [[Bascom und USI-Kommunikation]] - Bascom-Beispiele für Hardware USI<br />
* [[Bascom Soft-I2c Library]] - weitere Tipps zu I2C mit Bascom<br />
<br />
<br />
==WebLinks==<br />
<br />
* [http://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26774] - Forum-Artikel, in dem eine [[Bascom]]-Lib vorgestellt wird, um die Bascom-I2C-Befehle mit dem USI-Modul als Master zu verwenden.<br />
<br />
<br />
--[[Benutzer:Linux 80|Linux 80]] 02:08, 28. Okt 2007 (CEST)<br />
<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Kommunikation]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Quellcode Bascom]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Bascom_und_1-Wire&diff=15017Bascom und 1-Wire2009-06-21T06:18:04Z<p>Holzi: </p>
<hr />
<div>In diesem Artikel folgen einige Programmbeispiele, in denen gezeigt wird, wie Bascom über den 1-Wire-Bus kommuniziert.<br />
<br />
1-Wire (Eindraht) ist eine serielle Schnittstelle, die mit nur einer Datenleitung auskommt, die gleichzeitig auch noch als Stromversorgung genutzt werden kann.<br />
Aufgrund der Einfachheit kann diese Schnittstelle leicht in Software auf einem Mikrocontroller nachgebildet werden.<br />
<br />
In Bascom sind [[Bascom#1WIRE_Bus|Befehle]] für die 1-Wire-Kommunikation enthalten, sodass der Programmierer sich nicht um das Protokoll und das Timing der Übertragung kümmern muss.<br />
<br />
Es gibt 1-Wire-Geräte mit verschiedenen Funktionen, in der Roboterwelt dürfte einer der bekanntesten der Temperatursensor DS18S20 (bzw. DS18B20) sein, deswegen wird dieser in den Beispielen verwendet.<br />
<br />
<br />
== Beschaltung ==<br />
<br />
Die Beschaltung rund um den DS18B20 sieht so aus:<br />
<br />
[[Bild:1Wire-DS1820.png]]<br />
<br />
<br />
== Ablauf der Kommunikation ==<br />
<br />
Die Kommunikation mit dem 1-Wire-Gerät muss immer diesen Ablauf haben:<br />
<br />
* Initialisierung<br />
* "ROM Function" Befehl<br />
* "Memory Function" Befehl<br />
* Übertragung/Daten<br />
<br />
Aus diesem Ablauf ergeben sich die beiden folgenden Programmabläufe.<br />
<br />
<br />
== Kommunikation mit nur einem Gerät ==<br />
<br />
Wenn sich nur ein einziges Gerät am Bus befindet kann man diese kurze Version der Kommunikation verwenden. Ein ROM-Befehl ist dabei nicht notwendig und kann übersprungen werden, dies muss aber dem Gerät mitgeteilt werden.<br />
<br />
Beispiel:<br />
{{vbcomment|Minimalprogramm für Temperaturmessung}}<br />
Config 1wire = Portc.7 <br />
<br />
Dim Sp(9) As Byte<br />
<br />
1wreset {{vbcomment|Initialisierung}}<br />
1wwrite &HCC {{vbcomment|überspringe ROM-Befehl}}<br />
1wwrite &H44 {{vbcomment|Temperaturmessung anstoßen}}<br />
<br />
Waitms 500 {{vbcomment|warten bis Messung fertig}}<br />
<br />
1wreset {{vbcomment|Initialisierung}}<br />
1wwrite &HCC {{vbcomment|überspringe ROM-Befehl}}<br />
1wwrite &HBE {{vbcomment|Temperatur auslesen}}<br />
Sp(1) = 1wread(9) {{vbcomment|Daten in ein Array lesen}}<br />
<br />
Wait 1<br />
<br />
Im Array Sp() stehen die Daten des Gerätes die dann Anhand des Datenblattes ausgewertet werden.<br />
<br />
<br />
== Kommunikation mit mehreren Geräten ==<br />
<br />
Wenn sich mehrere Geräte am 1-Wire-Bus befinden, müssen diese jeweils Adressiert werden um mit dem gewünschten Gerät in Kontakt zu treten. Zum Adressieren wird die Seriennummer verwendet, die in jedem 1-Wire-Gerät eindeutig vorhanden ist. Um an diese Seriennummer zu kommen gibt es zwei Strategien.<br />
<br />
Entweder man liest bei allen Geräten vorher einzeln diese Nr. aus, um diese in das eigentliche Programm einzutragen (kürzer), oder man sucht beim Programmstart jedesmal nach vorhandenen Ger&auml;ten (flexibler).<br />
<br />
<br />
=== SerienNr einzeln auslesen ===<br />
<br />
Config 1wire = Portc.7<br />
<br />
Dim Ar(8) As Byte<br />
<br />
1wreset<br />
1wwrite &H33 {{vbcomment|ROM-Befehl zum lesen der SerienNr}}<br />
Ar(1) = 1wread(8) {{vbcomment|8 Bytes lesen}}<br />
<br />
For I = 1 To 8<br />
Print Hex(ar(i)); {{vbcomment|Ausgeben}}<br />
Print " ";<br />
Next<br />
<br />
Print<br />
<br />
Wait 1<br />
<br />
Im Array Ar() befindet sich somit die SerienNr des Gerätes.<br />
<br />
<br />
=== SerienNr aller Geräte ===<br />
<br />
$regfile = "M32def.dat"<br />
$crystal = 16000000<br />
$baud = 38400<br />
<br />
Config 1wire = Portc.7<br />
<br />
Dim Ar(8) As Byte {{vbcomment|Array für SerienNr.}}<br />
Dim I As Byte<br />
Dim W As Word<br />
<br />
Sound Portd.7 , 400 , 450 {{vbcomment|BEEP bei RN-Control}}<br />
<br />
Print<br />
Print "1-Wire"<br />
<br />
Wait 1<br />
<br />
Ar(1) = 1wsearchfirst()<br />
<br />
{{vbcomment|gibts überhaupt ein Ger&auml;t}}<br />
If Err = 0 Then<br />
<br />
Do<br />
{{vbcomment|Ausgabe der SerienNr.}}<br />
For I = 1 To 8<br />
Print Hex(ar(i));<br />
Print " ";<br />
Next<br />
Print<br />
<br />
{{vbcomment|Nach weiterem Ger&auml;t suchen}}<br />
Ar(1) = 1wsearchnext()<br />
<br />
Loop Until Err = 1 {{vbcomment|solange bis sich kein weiteres Ger&auml;t mehr meldet.}}<br />
<br />
End If<br />
<br />
Print "Fertig"<br />
<br />
W = 1wirecount() {{vbcomment|Anzahl der gefundenen Ger&auml;te z&auml;hlen}}<br />
<br />
Print "Anzahl ";<br />
Print W<br />
<br />
Do<br />
Loop<br />
<br />
End<br />
<br />
Am ersten Byte der SerienNr (Family-Code) ist zu erkennen um welches Ger&auml;t es sich handelt, beim DS18B20 ist es die &amp;H28, beim DS18S20 die &amp;H10. Da beide unterschiedliche Formate beim Temperaturwert haben, kann die Berechnung anhand des Family-Code angepasst werden.<br />
<br />
<br />
=== Bestimmtes Gerät ansprechen ===<br />
<br />
Um bei mehreren vorhandenen Ger&auml;ten ein bestimmtes anzusprechen muss es mit der SerienNr adressiert werden.<br />
<br />
Do<br />
1wverify Ar(1) {{vbcomment|Ger&auml;t mit der SerienNr. aus Ar() auswählen}}<br />
{{vbcomment|Gerät vorhanden}}<br />
If Err = 0 Then<br />
<br />
1wwrite &H44 {{vbcomment|Temperaturmessung anstoßen}}<br />
<br />
Waitms 500 {{vbcomment|warten bis Messung fertig}}<br />
<br />
1wverify Ar(1) {{vbcomment|Ger&auml;t mit der SerienNr. aus Ar() auswählen}}<br />
1wwrite &HBE {{vbcomment|Temperatur auslesen}}<br />
Sp(1) = 1wread(9) {{vbcomment|Daten in ein Array lesen}}<br />
<br />
For I = 1 To 9<br />
Print Hex(sp(i));<br />
Next<br />
Print<br />
<br />
{{vbcomment|Nur für die Temperatur wichtige Daten ausgeben}}<br />
Print Hex(sp(2));<br />
Print Hex(sp(1))<br />
<br />
Else<br />
Print "Fehler"<br />
End If<br />
<br />
Wait 1<br />
<br />
Loop<br />
<br />
Die SerienNr. des gew&uuml;nschten Ger&auml;tes muss im Array Ar() stehen, bevor es mit <tt>1wverify</tt> gesucht wird, dies ist auch gleichzeitig der ROM-Befehl, diesem kann der Memory-Befehl folgen, und anschlie&szlig;end die Daten übertragen werden.<br />
<br />
<br />
== Prüfsumme ==<br />
<br />
Da wegen der einen Datenleitung durchaus mit St&ouml;rungen zu rechnen ist, wird jeder &Uuml;bertragung ein Pr&uuml;fbyte angehängt, mit dem sich die Korrektheit der Daten überpr&uuml;fen lässt.<br />
<br />
Config 1wire = Portc.7<br />
<br />
Dim Ar(8) As Byte {{vbcomment|Array für SerienNr}}<br />
Dim I As Byte<br />
<br />
1wreset<br />
If Err = 0 Then<br />
1wwrite &H33 {{vbcomment|ROM-Befehl zum lesen der SerienNr.}}<br />
Ar(1) = 1wread(8) {{vbcomment|8 Bytes lesen}}<br />
<br />
For I = 1 To 8<br />
Print Hex(ar(i)); {{vbcomment|Ausgabe der SerienNr.}}<br />
Print " ";<br />
Next<br />
Print<br />
<br />
Print Hex(crc8(ar(1) , 7) ) {{vbcomment|Pr&uuml;fsumme ausgeben}}<br />
<br />
If Ar(8) = Crc8(ar(1) , 7) Then {{vbcomment|Pr&uuml;fsumme vergleichen}}<br />
Print "Daten OK"<br />
Else<br />
Print "Fehler"<br />
End If<br />
<br />
End If<br />
<br />
Wenn das letzte Byte der Übertragung und die berechnete Pr&uuml;fsumme aus den Bytes 1-7 übereinstimmt, war die &Uuml;bertragung erfolgreich, und die Daten k&ouml;nnen weiterverarbeitet werden.<br />
Beim auslesen der Temperatur werden 9 Bytes &uuml;bertragen, deshalb m&uuml;ssen zum berechnen der Pr&uuml;fsumme Byte 1-8 einbezogen werden.<br />
<br />
<br />
== Parasitäre Stromversorgung ==<br />
<br />
Da bei der Schaltung von oben eigentlich drei Leitungen ben&ouml;tigt werden, statt der einen wie man vermuten k&ouml;nnte, ist es mit der folgenden Schaltung immerhin m&ouml;glich die Anzahl auf zwei Leitungen zu reduzieren.<br />
<br />
[[Bild:1Wire-DS1820_parasit.png]]<br />
<br />
Es ist aber Abh&auml;ngig vom Ger&auml;t und den Umgebungsbedingungen ob es sich immer so l&ouml;sen l&auml;sst. Ein Blick ins Datenblatt hilft da weiter.<br />
<br />
<br />
== Siehe auch ==<br />
<br />
* [[Bascom]]<br />
* [[Bascom#1WIRE_Bus|1-Wire Bascom-Befehle]]<br />
* [[Avr]]<br />
<br />
<br />
== Weblinks ==<br />
<br />
* [http://www.maxim-ic.com/quick_view2.cfm?qv_pk=2812] - Datenblatt zu DS18B20<br />
* [http://www.maxim-ic.com/quick_view2.cfm/qv_pk/2815] - Datenblatt zu DS18S20<br />
<br />
<br />
--[[Benutzer:Linux 80|Linux 80]] 03:16, 23. Aug 2008 (CEST)<br />
<br />
[[Kategorie:Abkürzung]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Kommunikation]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Quellcode Bascom]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Bascom_und_USI-Kommunikation&diff=15016Bascom und USI-Kommunikation2009-06-21T06:16:07Z<p>Holzi: </p>
<hr />
<div>In diesem Artikel folgen einige Programmbeispiele, um das [[USI (Avr)|USI]]-Hardwaremodul der [[AVR]]s zu verwenden. Mit dem [[USI (Avr)|USI]]-Modul können die Schnittstellen [[I2C]] ([[TWI]]) und [[SPI]] nachgebildet werden. Näheres zu [[USI (Avr)|USI]], [[I2C]] und [[SPI]] finden sich in den entsprechenden Artikeln. Die Beispiele sind zwar in [[Bascom]] Basic verfasst, aber so ausgeführt, dass es möglich sein sollte das Prinzip mit jeder anderen Sprache nachvollziehen zu können.<br />
<br />
<br />
== USI-I2C-Master ==<br />
[[Bild:USI-I2C_PCF8574_RN-Control_Tiny2313.JPG|thumb|Beispielumgebung mit PCF8574]]<br />
Ist der AVR Master, bestimmt er was und wie schnell es auf dem [[I2C|I<sup>2</sup>C]]-Bus zugeht. (Ausnahme: [[Clock_Stretching]] )<br />
<br />
Zur Generierung der gewünschten Busgeschwindigkeit ist die Software zuständig. Die Länge der Pausen zwischen den Takten muss errechnet werden. Im Beispielprogramm für ca. 100 kHz bei 16 MHz CPU-Frequenz.<br />
Der Takt kann auch mithilfe eines [[Timer/Counter (Avr)|Timer]]s erzeugt werden, dies wird erst zu einem späteren Zeitpunkt mit einem Beispiel gezeigt.<br />
<br />
In den Beispielen wird als Master das Board [[RN-Control]] mit einem [[ATtiny2313|Tiny2313]], und als Slave ein [[I2C_Chip-Übersicht#I.2FO_expanders:|PCF8574]] verwendet, da sich dieser leicht ansteuern lässt. <!-- und jeden Scheiss mitmacht ;-)) --><br />
<br />
----<br />
<br />
<br />
=== Transmitter ===<br />
<br />
;Nur Senden<br />
<br />
Der Master sendet einem Slave ein (oder mehrere) Byte, und schließt die Übertragung anschließend ab.<br />
<br />
Das Gegenstück wäre ''Slave Receiver''.<br />
<br />
<br />
Beispielprogramm sendet ein Byte zum Slave mit Adresse 64 (0x40 bzw. &H40):<br />
<br />
{{vbcomment|USI-I2C Testprogramm}}<br />
{{vbcomment|mit PCF8574 @ &H40}}<br />
{{vbcomment|}}<br />
{{vbcomment|ohne Interrupt und ohne Timer}}<br />
{{vbcomment|ein Byte senden}}<br />
$regfile = "attiny2313.dat"<br />
$crystal = 16000000<br />
$baud = 9600<br />
<br />
{{vbcomment|Unterprogramme für die USI-Kommunikation}}<br />
Declare Sub Usi_twi_master_initialise()<br />
Declare Sub Usi_twi_start_transceiver()<br />
Declare Sub Usi_twi_master_stop()<br />
Declare Sub Usi_twi_master_transfer()<br />
<br />
{{vbcomment|einige Aliases anlegen}}<br />
Pout_usi_scl Alias Portb.7<br />
Pin_usi_scl Alias Pinb.7<br />
Ddr_usi_scl Alias Ddrb.7<br />
Pout_usi_sda Alias Portb.5<br />
Pin_usi_sda Alias Pinb.5<br />
Ddr_usi_sda Alias Ddrb.5<br />
<br />
Dim Usi_twi_errorstate As Byte {{vbcomment|eigener Fehlerstatus}}<br />
{{vbcomment|Array der Daten die übertragen werden}}<br />
Dim Messagebuf(4) As Byte<br />
Dim Temp_usisr As Byte {{vbcomment|Tempvariable für Unterprogramm}}<br />
Dim Anzahlbuf As Byte {{vbcomment|Anzahl Zeichen die gesendet werden sollen }}<br />
Dim Cnt As Byte {{vbcomment|Zähler}}<br />
Dim B As Byte {{vbcomment|Zeichen von UART oder Testzeichen zum senden über USI}}<br />
<br />
{{vbcomment|Prepare register value to: Clear flags, and set USI to shift 8 bits i.e. count 16 clock edges.}}<br />
Const Temp_usisr_8bit = &HF0<br />
{{vbcomment|Prepare register value to: Clear flags, and set USI to shift 1 bit i.e. count 2 clock edges.}}<br />
Const Temp_usisr_1bit = &HFE<br />
<br />
B = 0<br />
Anzahlbuf = 2 {{vbcomment|in diesem Beispiel immer nur 2 Zeichen}}<br />
<br />
Waitms 300 {{vbcomment|Sicherheitspause nach Reset}}<br />
<br />
Call Usi_twi_master_initialise<br />
<br />
Print<br />
Print "Tiny2313 USI-TWI-Test"<br />
<br />
Messagebuf(1) = &H40 {{vbcomment|Adresse von 8574}}<br />
<br />
Do<br />
{{vbcomment|warten bis etwas über UART kommt}}<br />
Input B<br />
{{vbcomment|oder automatisch zählen lassen}}<br />
{{vbcomment|Incr B}}<br />
<br />
{{vbcomment|Den Wert zum Slave senden}}<br />
Messagebuf(2) = Not B {{vbcomment|Not, weil LEDs gegen GND schalten}}<br />
Call Usi_twi_start_transceiver<br />
Call Usi_twi_master_stop<br />
<br />
{{vbcomment|Ausgabe, damit wir sehen was geschehen ist}}<br />
Print B ;<br />
Print " "<br />
Print Hex(usi_twi_errorstate);<br />
Print " " ;<br />
Print Hex(temp_usisr)<br />
<br />
Call Usi_twi_master_initialise {{vbcomment|nochmal initialisieren falls ein Fehler aufgetreten ist}}<br />
<br />
{{vbcomment|Waitms 700 ' Wenn automatisch gezählt werden soll, eine kleine Pause, damit man auch was sehen kann}}<br />
Loop<br />
<br />
End<br />
<br />
==== Unterprogramm nur Senden ====<br />
<br />
Die restlichen Subroutinen sind im nächsten Abschnitt zu finden.<br />
<br />
Diese Funktion ist nur zum Versenden geeignet !<br />
<br />
Statt dieser kann auch die Routine von unten genommen werden, die aber etwas mehr Speicherplatz benötigt.<br />
<br />
{{vbcomment|USI Transmit Funktion.}}<br />
Sub Usi_twi_start_transceiver()<br />
<br />
Usi_twi_errorstate = 0<br />
<br />
{{vbcomment|Test if any unexpected conditions have arrived prior to this execution.}}<br />
{{vbcomment|Ist eine Startbedingung aufgetreten ?}}<br />
If Usisr.7 = 1 Then {{vbcomment|USISIF}}<br />
Usi_twi_errorstate = &H02 {{vbcomment|Usi_twi_ue_start_con}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Ist eine Stopbedingung aufgetreten ?}}<br />
If Usisr.5 = 1 Then {{vbcomment|USIPF}}<br />
Usi_twi_errorstate = &H03 {{vbcomment|Usi_twi_ue_stop_con}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Ist eine Datenkollision aufgetreten ?}}<br />
If Usisr.4 = 1 Then {{vbcomment|USIDC}}<br />
Usi_twi_errorstate = &H04 {{vbcomment|Usi_twi_ue_data_col}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Release SCL to ensure that (repeated) Start can be performed}}<br />
Pout_usi_scl = 1<br />
Waitus 5<br />
<br />
{{vbcomment|Startbedingung ausgeben}}<br />
Pout_usi_sda = 0 {{vbcomment|Force SDA LOW.}}<br />
Waitus 4<br />
Pout_usi_scl = 0 {{vbcomment|Pull SCL LOW.}}<br />
Pout_usi_sda = 1 {{vbcomment|Release SDA.}}<br />
<br />
{{vbcomment|prüfen ob die Startbedingung vom eigenen USI erkannt wurde}}<br />
If Usisr.7 = 0 Then {{vbcomment|USISIF}}<br />
Usi_twi_errorstate = &H07<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Slaveadresse und Daten ausgeben}}<br />
For Cnt = 1 To Anzahlbuf<br />
{{vbcomment|Ein Byte ausgeben}}<br />
Pout_usi_scl = 0 {{vbcomment|Pull SCL LOW.}}<br />
Usidr = Messagebuf(cnt)<br />
Temp_usisr = Temp_usisr_8bit {{vbcomment|8Bit ausgeben}}<br />
Call Usi_twi_master_transfer<br />
<br />
{{vbcomment|(N)ACK vom Slave lesen}}<br />
Ddr_usi_sda = 0 {{vbcomment|Enable SDA as input.}}<br />
Temp_usisr = Temp_usisr_1bit {{vbcomment|1Bit einlesen}}<br />
Call Usi_twi_master_transfer<br />
<br />
{{vbcomment|kein ACK gekommen, Slave meldet sich nicht}}<br />
If Temp_usisr.0 = 1 Then<br />
Usi_twi_errorstate = &H05 {{vbcomment|Slave hat mit NACK quittiert}}<br />
If Cnt = 1 Then<br />
Usi_twi_errorstate = &H06 {{vbcomment|Es hat sich kein Slave gemeldet}}<br />
End If<br />
Exit For {{vbcomment|hier wird die Schleife bei einem NACK verlasssen}}<br />
End If<br />
<br />
Next Cnt<br />
<br />
End Sub<br />
<br />
----<br />
<br />
=== Transmitter und Receiver mit DS1621 als Slave ===<br />
[[Bild:USI-I2C_DS1621_RN-Control_Tiny2313.JPG|thumb|Beispielumgebung mit DS1621]]<br />
<br />
;Senden und Empfangen (Repeated Start)<br />
Im Beispiel wird ein DS1621 Temperatursensor mit I2C-Schnittstelle verwendet.<br><br />
Der Master sendet dem Slave ein Kommando, stellt um auf Empfang und holt den Temperaturwert, schließt die Übertragung anschließend ab.<br />
<br />
Der Temperaturwert wird über [[UART]] ([[RS232]]) im Klartext ausgegeben.<br />
<br />
Die Subroutinen sind die gleichen wie für ''Master Transmitter''. Da der DS1621 aber mit 400 kHz kommunizieren kann, wurden die ''Waitus'' zwischen den Pegelwechseln weggelassen, da die Befehle hier sowieso nicht schnell genug sind und ein Wait unnötig machen. Sie sind aber als Kommentar eingefügt, damit zu sehen ist an welchen Stellen ansonsten gewartet werden sollte (zB bei 100kHz).<br />
<br />
Beispielprogramm holt Temperaturwert vom Slave mit Adresse 144 (0x90 bzw. &H90):<br><br />
(Das Beispiel belegt 1418 Byte im Flash, das sind ca. 69% eines Tiny2313 !)<br />
<br />
{{vbcomment|USI-I2C Testprogramm}}<br />
{{vbcomment|mit DS1621 @ &H90}}<br />
{{vbcomment|}}<br />
{{vbcomment|ohne Interrupt und ohne Timer}}<br />
{{vbcomment|Temperatur von DS1621 lesen, und über UART ausgeben}}<br />
$regfile = "attiny2313.dat"<br />
$crystal = 16000000<br />
$baud = 9600<br />
<br />
{{vbcomment|Unterprogramme für die USI-Kommunikation}}<br />
Declare Sub Usi_twi_master_initialise()<br />
Declare Sub Usi_twi_start_transceiver()<br />
Declare Sub Usi_twi_master_stop()<br />
Declare Sub Usi_twi_master_transfer()<br />
<br />
{{vbcomment|einige Aliases anlegen}}<br />
Pout_usi_scl Alias Portb.7<br />
Pin_usi_scl Alias Pinb.7<br />
Ddr_usi_scl Alias Ddrb.7<br />
Pout_usi_sda Alias Portb.5<br />
Pin_usi_sda Alias Pinb.5<br />
Ddr_usi_sda Alias Ddrb.5<br />
<br />
Dim Usi_twi_errorstate As Byte {{vbcomment|eigener Fehlerstatus}}<br />
{{vbcomment|Array der Daten die übertragen werden}}<br />
Dim Messagebuf(4) As Byte<br />
Dim Temp_usisr As Byte {{vbcomment|Tempvariable für Unterprogramm}}<br />
Dim Anzahlbuf As Byte {{vbcomment|Anzahl Zeichen die gesendet werden sollen}}<br />
Dim Cnt As Byte {{vbcomment|Zähler}}<br />
Dim Rw As Bit {{vbcomment|Read/Write Flag}}<br />
<br />
{{vbcomment|Prepare register value to: Clear flags, and set USI to shift 8 bits i.e. count 16 clock edges.}}<br />
Const Temp_usisr_8bit = &HF0<br />
{{vbcomment|Prepare register value to: Clear flags, and set USI to shift 1 bit i.e. count 2 clock edges.}}<br />
Const Temp_usisr_1bit = &HFE<br />
<br />
Waitms 500 {{vbcomment|Sicherheitspause nach Reset}}<br />
<br />
Call Usi_twi_master_initialise<br />
<br />
Dim Device As Byte<br />
Dim Deviceread As Byte<br />
Dim Lowtemp As Byte<br />
Dim Hightemp As Byte<br />
<br />
Device = &H90<br />
Deviceread = &H91<br />
<br />
Sound Portd.5 , 300 , 450 {{vbcomment|BEEP}}<br />
<br />
Print<br />
Print "DS1621-USI Temperatur"<br />
<br />
<br />
{{vbcomment|Hauptprogramm}}<br />
Do<br />
<br />
Messagebuf(1) = Device {{vbcomment|Adresse von DS1621}}<br />
Messagebuf(2) = &HEE {{vbcomment|Temperaturmessung anstoßen}}<br />
Anzahlbuf = 2 {{vbcomment|2 Byte ausgeben}}<br />
Call Usi_twi_start_transceiver<br />
{{vbcomment|Print Hex(usi_twi_errorstate)}}<br />
<br />
If Usi_twi_errorstate = 0 Then {{vbcomment|kein Fehler aufgetreten}}<br />
<br />
Call Usi_twi_master_stop<br />
{{vbcomment|Print Hex(usi_twi_errorstate)}}<br />
<br />
{{vbcomment|Waitms 1}}<br />
Messagebuf(1) = Device {{vbcomment|Adresse von DS1621}}<br />
Messagebuf(2) = &HAA {{vbcomment|Temperaturmessung Lesekommando}}<br />
Anzahlbuf = 2 {{vbcomment|2 Byte ausgeben}}<br />
Call Usi_twi_start_transceiver<br />
{{vbcomment|Print Hex(usi_twi_errorstate)}}<br />
{{vbcomment|kein STOP an dieser Stelle !}}<br />
{{vbcomment|es folgt ein Repeated START !}}<br />
<br />
If Usi_twi_errorstate = 0 Then {{vbcomment|kein Fehler aufgetreten}}<br />
{{vbcomment|Temperatur lesen}}<br />
Messagebuf(1) = Deviceread {{vbcomment|Adresse von DS1621}}<br />
Messagebuf(2) = 0<br />
Messagebuf(3) = 0<br />
Anzahlbuf = 3 {{vbcomment|3 Byte ausgeben, bzw. einlesen}}<br />
Call Usi_twi_start_transceiver<br />
{{vbcomment|Print Hex(usi_twi_errorstate)}}<br />
<br />
If Usi_twi_errorstate = 0 Then {{vbcomment|kein Fehler aufgetreten}}<br />
<br />
Call Usi_twi_master_stop<br />
{{vbcomment|Print Hex(usi_twi_errorstate)}}<br />
<br />
{{vbcomment|Gelesenen Bytes stehen ab Position 2 im Array}}<br />
Lowtemp = Messagebuf(2)<br />
Hightemp = Messagebuf(3)<br />
<br />
{{vbcomment|Negativer Wert ?}}<br />
If Lowtemp.7 = 1 Then<br />
Lowtemp = Not Lowtemp<br />
{{vbcomment|.5 ?}}<br />
If &H80 > Hightemp Then<br />
Incr Lowtemp<br />
End If<br />
Print "-" ;<br />
Else<br />
Print " " ;<br />
End If<br />
<br />
Print Lowtemp ; "," ;<br />
<br />
If Hightemp = &H80 Then<br />
Print "5"<br />
Else<br />
Print "0"<br />
End If<br />
<br />
End If<br />
End If<br />
End If<br />
<br />
If Usi_twi_errorstate <> 0 Then {{vbcomment|bei einem Fehler den Fehlercode ausgeben}}<br />
Print "Error " ; Hex(usi_twi_errorstate)<br />
End If<br />
<br />
{{vbcomment|nochmal initialisieren falls ein Fehler aufgetreten ist}}<br />
Call Usi_twi_master_initialise<br />
<br />
Waitms 2000<br />
Loop<br />
<br />
End<br />
<br />
<br />
=== Unterprogramme für USI-Kommunikation ===<br />
<br />
Hier folgen die Unterprogramme für die USI-I2C-Master Kommunikation<br />
<br />
==== Initialisierung ====<br />
<br />
USI-I2C Pins Initialisieren, und USI-Register setzen für I2C-Master.<br />
<br />
{{vbcomment|USI TWI single master initialization function}}<br />
Sub Usi_twi_master_initialise()<br />
{{vbcomment|Direction Out}}<br />
Ddr_usi_scl = 1<br />
Ddr_usi_sda = 1<br />
{{vbcomment|Release SCL & SDA}}<br />
Pout_usi_scl = 1<br />
Pout_usi_sda = 1<br />
<br />
{{vbcomment|Preload dataregister with "released level" data.}}<br />
Usidr = &HFF<br />
<br />
{{vbcomment|Disable USI Interrupts.}}<br />
{{vbcomment|Set USI in Two-wire mode.}}<br />
{{vbcomment|Software stobe as counter clock source}}<br />
Usicr = &B00101010<br />
<br />
{{vbcomment|Statusflags löschen, und Counter auf 0 zurücksetzen.}}<br />
Usisr = &B11110000<br />
<br />
End Sub<br />
<br />
==== Senden/Empfangen ====<br />
<br />
Startbedingung ausgeben,<br><br />
versenden der Anzahl der angegebenen Bytes,<br><br />
und einen Status zurückgeben, ob die Daten angenommen (ACK) wurden.<br />
<br />
{{vbcomment|USI Transmit und Receive Funktion.}}<br />
Sub Usi_twi_start_transceiver()<br />
<br />
Usi_twi_errorstate = 0<br />
<br />
{{vbcomment|Test if any unexpected conditions have arrived prior to this execution.}}<br />
{{vbcomment|Ist eine Startbedingung aufgetreten ?}}<br />
If Usisr.7 = 1 Then {{vbcomment|USISIF}}<br />
Usi_twi_errorstate = &H02 {{vbcomment|Usi_twi_ue_start_con}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Ist eine Stopbedingung aufgetreten ?}}<br />
If Usisr.5 = 1 Then {{vbcomment|USIPF}}<br />
Usi_twi_errorstate = &H03 {{vbcomment|Usi_twi_ue_stop_con}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Ist eine Datenkollision aufgetreten ?}}<br />
If Usisr.4 = 1 Then {{vbcomment|USIDC}}<br />
Usi_twi_errorstate = &H04 {{vbcomment|Usi_twi_ue_data_col}}<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|Release SCL to ensure that (repeated) Start can be performed}}<br />
Pout_usi_scl = 1<br />
Waitus 1 {{vbcomment|5}}<br />
<br />
{{vbcomment|Generate Start Condition}}<br />
Pout_usi_sda = 0 {{vbcomment|Force SDA LOW.}}<br />
{{vbcomment|Waitus 4}}<br />
Pout_usi_scl = 0 {{vbcomment|Pull SCL LOW.}}<br />
Pout_usi_sda = 1 {{vbcomment|Release SDA.}}<br />
<br />
{{vbcomment|prüfen ob die Startsequenz vom eigenen USI erkannt wurde}}<br />
If Usisr.7 = 0 Then {{vbcomment|USISIF}}<br />
Usi_twi_errorstate = &H07<br />
Exit Sub<br />
End If<br />
<br />
{{vbcomment|RW-Bit : Messagebuf(1).0}}<br />
Rw = Messagebuf(1).0<br />
<br />
{{vbcomment|Write address and Read/Write data}}<br />
For Cnt = 1 To Anzahlbuf<br />
{{vbcomment|SlaveAdresse immer Write, sonst auf R/W prüfen}}<br />
If Cnt = 1 Or Rw = 0 Then<br />
{{vbcomment|Write a byte}}<br />
Pout_usi_scl = 0 {{vbcomment|Pull SCL LOW.}}<br />
Usidr = Messagebuf(cnt)<br />
Temp_usisr = Temp_usisr_8bit<br />
Call Usi_twi_master_transfer<br />
<br />
{{vbcomment|Clock and verify (N)ACK from slave}}<br />
Ddr_usi_sda = 0 {{vbcomment|Enable SDA as input.}}<br />
Temp_usisr = Temp_usisr_1bit<br />
Call Usi_twi_master_transfer<br />
<br />
{{vbcomment|kein ACK gekommen}}<br />
If Temp_usisr.0 = 1 Then<br />
Usi_twi_errorstate = &H05 {{vbcomment|Der Slave hat die Daten mit NACK quittiert}}<br />
If Cnt = 1 Then<br />
Usi_twi_errorstate = &H06 {{vbcomment|Es hat sich kein Slave gemeldet}}<br />
End If<br />
Exit For {{vbcomment|die Schleife bei einem Fehler verlasssen}}<br />
End If<br />
Else<br />
{{vbcomment|Read a Byte}}<br />
Ddr_usi_sda = 0 {{vbcomment|Enable SDA as input.}}<br />
Temp_usisr = Temp_usisr_8bit<br />
Call Usi_twi_master_transfer<br />
<br />
Messagebuf(cnt) = Temp_usisr {{vbcomment|Empfangenes Byte ins Array}}<br />
<br />
{{vbcomment|Prepare to generate ACK (or NACK in case of End Of Transmission)}}<br />
If Cnt = Anzahlbuf Then<br />
Usidr = &HFF {{vbcomment|Load NACK to confirm End Of Transmission.}}<br />
Else<br />
Usidr = &H00 {{vbcomment|Load ACK. Set data register bit 7 (output for SDA) low.}}<br />
End If<br />
<br />
Temp_usisr = Temp_usisr_1bit<br />
Call Usi_twi_master_transfer {{vbcomment|ACK oder NACK senden}}<br />
<br />
End If<br />
Next Cnt<br />
<br />
End Sub<br />
<br />
==== Ein Byte ausgeben/einlesen ====<br />
<br />
Diese Routine gibt die Anzahl Bit aus, wie anhand der Variablen ''Temp_usisr'' eingestellt wurde, bzw. es wird damit die Anzahl Takte angegeben, die der Counter des USI-Moduls zählt bevor er überläuft, und das Flag ''USIOIF'' im Status-Register ''USISR'' gesetzt wird.<br />
<br />
Getaktet wird hier per Software, pro Bit zwei Takte. Bei jedem Takt ändert sich der Zustand (High/Low) von SCL.<br />
<br />
Die Daten, die ausgegeben werden sollen, müssen vor dem Aufruf dieser Routine in das Datenregister ''USIDR'' geschrieben werden.<br />
<br />
Ob ein Bit ausgegeben oder gelesen wird, wird vor dem Aufruf im Datenrichtungsregister der Datenleitung SDA eingestellt. Im Beispiel mit dem Alias ''Ddr_usi_sda''.<br />
<br />
Das gelesene Byte von ''USIDR'' wird in die Variable ''Temp_usisr'' geschrieben, und kann vom Hauptprogramm weiterverarbeitet werden.<br />
<br />
Sub Usi_twi_master_transfer()<br />
Usisr = Temp_usisr<br />
<br />
Temp_usisr = &B00101011 {{vbcomment|for Toggle Clock Port.}}<br />
<br />
Do<br />
{{vbcomment|Waitus 5}}<br />
Usicr = Temp_usisr {{vbcomment|SCL takten}}<br />
{{vbcomment|Wait for SCL to go high.}}<br />
While Pin_usi_scl = 0<br />
Wend<br />
<br />
{{vbcomment|Waitus 4}}<br />
Usicr = Temp_usisr {{vbcomment|SCL takten}}<br />
<br />
Loop Until Usisr.6 = 1 {{vbcomment|USIOIF, Wenn der Zähler überläuft, sind alle Bits versendet.}}<br />
<br />
{{vbcomment|Waitus 5}}<br />
Temp_usisr = Usidr {{vbcomment|Daten aus USI-Datenregister lesen.}}<br />
Usidr = &HFF {{vbcomment|Release SDA.}}<br />
<br />
Ddr_usi_sda = 1 {{vbcomment|Enable SDA as output.}}<br />
<br />
End Sub<br />
<br />
==== STOP-Bedingung ausgeben ====<br />
<br />
STOP-Bedingung ausgeben, und prüfen ob dies vom eigenen Modul erkannt wurde.<br><br />
Status zurückgeben, ob die STOP-Bedingung erfolgreich ausgegeben wurde.<br />
<br />
{{vbcomment|Function for generating a TWI Stop Condition. Used to release the TWI bus.}}<br />
Sub Usi_twi_master_stop()<br />
<br />
Pout_usi_sda = 0 {{vbcomment|Pull SDA LOW.}}<br />
Pout_usi_scl = 1 {{vbcomment|Release SCL.}}<br />
<br />
{{vbcomment|Wait for SCL to go high.}}<br />
While Pin_usi_scl = 0<br />
Wend<br />
{{vbcomment|Waitus 4}}<br />
Pout_usi_sda = 1 {{vbcomment|Release SDA.}}<br />
Waitus 1 {{vbcomment|5}}<br />
<br />
{{vbcomment|prüfen ob die Stopsequenz vom eigenen USI erkannt wurde}}<br />
If Usisr.5 = 0 Then {{vbcomment|USIPF}}<br />
Usi_twi_errorstate = &H08<br />
{{vbcomment| Exit Sub ' Exit nicht nötig, da schon das Ende erreicht}}<br />
End If<br />
<br />
Usisr.5 = 1 {{vbcomment|USIPF zurücksetzen}}<br />
End Sub<br />
<br />
----<br />
<br />
=== Fehlercodes aus den Beispielen ===<br />
<br />
Wenn ein unerwartetes Ereignis auftreten sollte, wird eine Zahl ausgegeben, hier ist deren Bedeutung dazu.<br />
Die Fehlercodes wurden aus den Beispielen von Atmel übernommen. (siehe Weblinks)<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- {{Hintergrund1}}<br />
!| Code || Kurzbezeichnung || Fehlerbeschreibung<br />
|-<br />
|align="center"|02<br />
| USI_TWI_UE_START_CON || Unerwartete Start Bedingung aufgetreten<br />
|-<br />
|align="center"|03<br />
| USI_TWI_UE_STOP_CON || Unerwartete Stop Bedingung aufgetreten<br />
|-<br />
|align="center"|04<br />
| USI_TWI_UE_DATA_COL || Unerwartete Data Collision (arbitration)<br />
|-<br />
|align="center"|05<br />
| USI_TWI_NO_ACK_ON_DATA || Der Slave hat die Daten nicht per ACK quittiert<br />
|-<br />
|align="center"|06<br />
| USI_TWI_NO_ACK_ON_ADDRESS || Es hat sich kein Slave per ACK gemeldet<br />
|-<br />
|align="center"|07<br />
| USI_TWI_MISSING_START_CON || Erzeugte Start Bedingung nicht erkannt<br />
|-<br />
|align="center"|08<br />
| USI_TWI_MISSING_STOP_CON || Erzeugte Stop Bedingung nicht erkannt<br />
|}<br />
</div><br />
<br />
<br />
== USI-I2C-Slave ==<br />
<br />
Da der I2C-Master den Takt vorgibt, sind die [[TWI#Anmerkung_zur_CPU-Frequenz|Anmerkungen zur CPU-Frequenz]] zu beachten.<br />
<br />
In den Beispielen wird als Master das Board [[RN-Mega8]] mit einem [[ATMega8|Mega8]], und als Slave das [[RN-Control]] Board, mit dem Adapter auf dem der [[ATtiny2313|Tiny2313]] sitzt, verwendet. Da nur diese beiden Boards am Bus hängen, wurde ebenfalls als Slaveadresse 64 (0x40 bzw. &H40) verwendet, damit man die vorhergehenden Beispiele gleich weiterverwenden kann.<br />
<br />
<br />
Im unten angegebenen WebLink (Nr.1) zum Forum ist ein Beispielprogramm um einen USI-I2C-Slave zu programmieren, es ist noch nicht ganz ausgereift, funktioniert aber ausreichend.<br />
<br />
Im gleichen angegebenen WebLink (Nr.1) ist ein Beispiel für Portierung der '''Atmel Application Note AVR312''' "Using the USI module as a I2C slave" (siehe Link) auf Bascom. Das vollständig interruptgesteuerte Programm belegt 476Byte im Speicher eines ATtiny25.<br />
<br />
== Siehe auch ==<br />
<br />
* [[Avr]] - Infos zu AVR allgemein<br />
* [[I2C|I<sup>2</sup>C]] - Details zu I2C<br />
* [[TWI]] - Two-wire Serial Interface<br />
* [[SPI]] - Serial Peripheral Interface<br />
* [[TWI Praxis]] - Bascom-Beispiele für Hardware TWI<br />
* [[TWI Praxis Multimaster]] - Bascom-Beispiele für Hardware TWI<br />
<br />
<br />
==WebLinks==<br />
* [http://www.roboternetz.de/phpBB2/viewtopic.php?t=25058] - Thread im Forum der zu diesem hier geführt hat<br />
* [http://www.shop.robotikhardware.de/shop/catalog/product_info.php?cPath=71&products_id=107] - DS1621 bei Robotikhardware<br />
* [http://www.atmel.com/dyn/resources/prod_documents/doc2561.pdf Atmel_AVR310] - Using the USI module as a I2C master<br />
* [http://www.atmel.com/dyn/resources/prod_documents/doc2560.pdf Atmel_AVR312] - Using the USI module as a I2C slave<br />
* [http://www.roboternetz.de/phpBB2/zeigebeitrag.php?t=26774] - Forum-Artikel, in dem eine [[Bascom]]-Lib vorgestellt wird, um die Bascom-I2C-Befehle mit dem USI-Modul als Master zu verwenden.<br />
<br />
<br />
<br />
--[[Benutzer:Linux 80|Linux 80]] 02:11, 26. Nov 2006 (CET)<br />
<br />
[[Kategorie:Abkürzung]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Kommunikation]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Quellcode Bascom]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=ADC_(Avr)&diff=15015ADC (Avr)2009-06-21T06:13:21Z<p>Holzi: </p>
<hr />
<div>''Für allgemeine Informationen zum Analog-Digital-Wandler siehe Artikel [[ADC]].''<br />
<br />
Mit einem Analog-Digital-Wandler ([[ADC]], für Analog Digital Converter) ist es mit den AVRs möglich, auf einfache Art und Weise analoge Größen in digitale Werte umzuwandeln. Dies bietet sich z.B. an, wenn die Batteriespannung eines Roboters bestimmt werden soll.<br />
<br />
= Kanäle =<br />
Ein AVR hat normalerweise nur einen [[ADC]] integriert. Des öfteren müssen aber mehrere analoge Größen von verschiedenen Quellen umgewandelt werden. Deswegen besitzen die AVRs Kanäle (ein ATmega32 z.B. besitzt acht Kanäle auf Port A). Diese Kanäle werden dann mit Hilfe eines Multiplexer auf den [[ADC]] geschaltet, der dann die anliegende analoge Spannung in einen digitalten Wert wandelt.<br />
<br />
= Betriebsmodi =<br />
Der [[ADC]] bietet verschiedene Betriebsmodi. Diese wären:<br />
* Single Conversion: Der [[ADC]] wandelt eine analoge Größe um und gibt diese zurück.<br />
* Free Running: Der [[ADC]] wandelt wie in einer Endlosschleife ständig die anliegende analoge Größe in digitale Werte um und gibt diese zurück.<br />
* Autotrigger: Bei neueren AVRs (z.B. Mega48,Mega88,Mega32,..) kann der ADC auch direkt vom [[Timer/Counter_(Avr)|Timer]] oder über den analogen Komperator gestartet werden.<br />
<br />
= Teilungsfaktor =<br />
Zum Wandeln benötigt der [[ADC]] einen eigenen Takt, der auf der Taktfrequenz des Mikrocontrollers basiert. Eine Wandlung braucht normalerweise 13 Zyklen des ADC-Taktes. Allerdings ist die Taktfrequenz des Mikrocontrollers zu schnell und deswegen wird diese durch den Vorteiler verkleinert. Der resultierende Takt sollte beim AVR zwischen 50kHz und 200kHz liegen. Mit reduzierter Genauigkeit ist bis 1000 kHz möglich. Folgende Teilungsfaktoren sind verfügbar:<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- align="center"<br />
|'''Teilungsfaktoren'''<br />
| &nbsp;2 || &nbsp;4 || &nbsp;8 || 16 || 32 || 64 || 128<br />
|}</div><br />
<br />
Um zu bestimmen, welcher Teilungsfaktor geeignet ist, kann folgende Formel verwenden werden.<br><br />
<math>Taktfrequenz = 8 MHz</math><br />
<br />
<math>Teilungsfaktor_{min} = {Taktfrequenz \over {200 kHz}} = {{8000000 Hz} \over {200000 Hz}} = 40</math><br />
<br />
<math>Teilungsfaktor_{max} = {Taktfrequenz \over {50 kHz}} = {{8000000 Hz} \over {50000 Hz}} = 160</math><br />
<br />
Deswegen kann nun zwischen einem der folgenden Teilungsfaktor gewählt werden: 64 und 128. Im Interesse der Geschwindigkeit sollte 64 gewählt werden. <br />
<br />
Siehe bitte die Registerübersicht weiter unten. Dort wird gezeigt, welches Register entsprechend eingestellt werden muss, damit einer der oben aufgelisteten Teilungsfaktoren gewählt werden kann.<br />
<br />
= Referenzspannung =<br />
Das Ergebnis der Wandlung des [[ADC]] bezieht sich auf eine bestimmte Referenzspannung. Diese Referenzspannung ist gleich der maximal zu messenden Spannung. Wenn die Spannung höher ist (kleiner als Vcc+0.3V, um den Port nicht zu beschädigen) gibt der AD Wandler das maximale Ergebnis. Um einzustellen, welche Referenzspannung verwendet werden soll, gibt es das Register ''ADMUX''.<br />
Je nach verwendetem AVR sind verschiedene Möglichkeiten als Referenzspannung vorhanden:<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- {{Hintergrund1}}<br />
!| Referenz- spannungsquelle|| Bedeutung<br />
|-<br />
|AREF || es wird die externe Spannung als Referenz verwendet, die an Pin AREF anliegt<br />
|-<br />
|AVCC || besitzt der AVR eine eigene Spannungsversorgung für den ADC<br />, wird der Pin AVCC als Referenz gewählt,<br />ansonsten wird Vcc verwendet,<br />mit externen Kondensator am AREF Pin<br />
|-<br />
|Intern || Spannung 1,1V und/oder 2,56V, je nach AVR einer der beiden Spannungen, oder beide zur Auswahl, wie zB. beim [[ATmega644]], mit oder ohne (zB. beim Tiny15L) externem Kondensator am AREF Pin<br />
|}</div><br />
<br />
Verwendet man [[Bascom]] als Programmiersprache, gibt es, je nach verwendetem AVR, folgende Möglichkeiten zur Angabe als Referenz :<br />
Config Adc = Single , Prescaler = Auto , Reference = <br />
OFF {{vbcomment|AREF}}<br />
AVCC {{vbcomment|AVCC oder VCC (intern geschaltet)}}<br />
INTERNAL {{vbcomment|Wenn nur eine interne Spannung möglich ist}}<br />
INTERNAL_1.1 {{vbcomment|Wenn mehr interne Spannungen auswählbar sind}}<br />
INTERNAL_2.56 {{vbcomment|Wenn mehr interne Spannungen auswählbar sind}}<br />
INTERNALEXTCAP {{vbcomment|Wenn, zB. beim Tiny15L, ein Kondensator an AREF angeschlossen ist}}<br />
<br />
Siehe bitte die Registerübersicht. Dort steht genauer wie man das Register einzustellen hat.<br />
<br />
Die Referenzspannung wird auch (oder besser deren analoge Größe) benötigt, um den Wert, den der ADC zurückgibt, in V umzurechnen. Um den zurückgegebenen Wert des ADC umzuwandel, wird wie folgt vorgegangen:<br />
<br />
# Bestimmen der Auflösung des ADC. Bei den ATMegas normalerweise 10 Bit. 10 Bit entsprechen einer Stufung von 1024.<br />
# Ermitteln des digitalen Wertes der analogen Größe. In der Beispielrechnung verwende ich den Wert 592.<br />
# Größe der Referenzspannung. In der Beispielrechnung wird 5V verwendet.<br />
Mit diesen Werten kann folgende Berechnung ausführen.<br />
<br />
<math>V = 592 * 5V</math><br />
<br />
<math>V = 2960 / 2 ^{Bit} = 2960 / 2 ^{10} = \underline {\underline { 2{,}9V }}</math><br />
<br />
= Programmbeispiele =<br />
<br />
=== C/C++ ===<br />
<br />
Dieses Beispiel ist für die [[Atmel Controller Mega16 und Mega32]] gedacht, die mit einer Taktfrequenz von 8 MHz laufen. Je nach Einsatzart muss das Beispielprogramm entsprechend abgeändert werden (also diese Zeile mit ADMUX |= (1<<REFS1) | (1<<REFS0);).<br />
<pre><br />
#include <avr/io.h><br />
#include <inttypes.h><br />
<br />
uint16_t readADC(uint8_t channel) {<br />
uint8_t i;<br />
uint16_t result = 0;<br />
<br />
// Den ADC aktivieren und Teilungsfaktor auf 64 stellen<br />
ADCSRA = (1<<ADEN) | (1<<ADPS2) | (1<<ADPS1);<br />
<br />
// Kanal des Multiplexers waehlen<br />
ADMUX = channel;<br />
// Interne Referenzspannung verwenden (also 2,56 V)<br />
ADMUX |= (1<<REFS1) | (1<<REFS0);<br />
<br />
// Den ADC initialisieren und einen sog. Dummyreadout machen<br />
ADCSRA |= (1<<ADSC);<br />
while(ADCSRA & (1<<ADSC));<br />
<br />
// Jetzt 3x die analoge Spannung and Kanal channel auslesen<br />
// und dann Durchschnittswert ausrechnen.<br />
for(i=0; i<3; i++) {<br />
// Eine Wandlung<br />
ADCSRA |= (1<<ADSC);<br />
// Auf Ergebnis warten...<br />
while(ADCSRA & (1<<ADSC));<br />
<br />
result += ADCW;<br />
}<br />
<br />
// ADC wieder deaktivieren<br />
ADCSRA &= ~(1<<ADEN);<br />
<br />
result /= 3;<br />
<br />
return result;<br />
}<br />
<br />
int main(void) {<br />
uint16_t result = readADC(0); //Auslesen der analogen Spannungen an Pin 0,<br />
// also ADC0. In result steht das Ergebnis.<br />
return 0;<br />
}<br />
</pre><br />
<br />
=== Bascom ===<br />
<br />
Dieses Programmbeispiel ist für den Atmel Controller Mega32 gedacht. Es gibt nacheinander die Spannungen der einzelnen Kanäle (ADC0..7) aus. Dazwischen macht es immer 800 ms pause.<br />
<pre><br />
' Die gemessene Spannung wird in der Variablen W gespeichert.<br />
' Channel ist der Pin, an dem die Spannung gemessen werden soll.<br />
<br />
$baud = 9600<br />
$crystal = 1000000<br />
$regfile "m32def.dat"<br />
Config Adc = Single , Prescaler = Auto<br />
Start Adc<br />
Dim W As Word , Channel As Byte<br />
Channel = 0<br />
Do<br />
W = Getadc(channel)<br />
Print "ADC-Pin " ; Channel ; ": Wert " ; W<br />
Incr Channel<br />
If Channel > 7 Then Channel = 0<br />
Waitms 800<br />
Loop<br />
End<br />
</pre><br />
<br />
= Registerübersicht =<br />
<br />
{| {{GrauRotDesignSchmal}}<br />
|-<br />
|Hinweis: Diese Registertabellen wurden für den aktuellen [[Atmel Controller Mega16 und Mega32]] erstellt. Wenn Sie ein anderes Modell verwenden, kann es sein, dass ein oder mehrere Register nicht existieren oder sie eine andere Bezeichnung haben.<br />
|}<br />
<br />
<br />
=== ADCSRA ===<br />
<br />
ADC Control and Status Register A<br />
<br />
Dieser Register dient dazu den ADC zu kontrollieren.<br />
<br />
{{Registertabelle8BitFix|ADEN|ADSC|ADATE|ADIF|ADIE|ADPS2|ADPS1|ADPS0}}<br />
<br />
*'''ADEN (ADC Enable)'''<br/>Wird dieses Bit gesetzt (also 1), dann wird der ADC aktiviert. Wird eine 0 geschrieben, wird der ADC deaktiviert. Wird der ADC während einer Wandlung deaktiviert, wird die Wandlung abgebrochen.<br />
*'''ADSC (ADC Start Conversion)'''<br/>Dieses Bit startet den Messvorgang, je nachdem in welchem Betriebsmodi der ADC läuft. Wird dieses Bit nach der Aktivierung des ADC über '''ADEN''' zum ersten Mal gesetzt, wird der ADC erst eine Initialisierungswandlung durchführen und danach erst die eigentliche Wandlung. Das Schreiben einer 0 auf das Bit hat keinen Effekt.<br />
*'''ADATE (ADC Auto Trigger Enable)'''<br/>Wird dieses Bit gesetzt, wird das Auto Triggering des ADC aktiviert. Die genaue Triggerquelle wir im Register '''SFIOR''' eingestellt. Default ist das der Free-runnng mode.<br />
*'''ADIF (ADC Interrupt Flag)'''<br/>Dieses Bit wird auf 1 gesetzt, wenn eine Wandlung erfolgte und das Ergebnis nun verfügbar ist. Der ADC Complete Interrupt wird ausgelöst, wenn das '''ADIE'''-Bit gesetzt ist und die Interrupts global aktiviert sind. Das Bit wird gelöscht, wenn die entsprechende [[ISR]] abgearbeitet wird. Alternativ kann es gelöscht werden, indem eine 1 auf das Bit geschrieben wird.<br />
*'''ADIE (ADC Interrupt Enable)'''<br/>Wird dieses Bit gesetzt und die globalen Interrupts sind aktiviert, wird der ADC Complete Interrupt aktiviert, auf den dann in der entsprechenden [[ISR]] reagiert werden kann.<br />
*'''ADPS2 (ADC Prescaler Select Bit 2)'''<br/>Diese Bits bestimmen den Teilungsfaktor zwischen der CPU-Frequenz und dem Eingangstakt des [[ADC]]. Zum Wandeln benötigt der [[ADC]] einen eigenen Takt, der auf der Taktfrequenz des Mikrocontrollers basiert. Allerdings ist die Taktfrequenz zu schnell und deswegen wird diese durch den Vorteiler verkleinert. Der resultierende Takt sollte zwischen 50kHz und 200kHz liegen. Siehe [[#Teilungsfaktor|Teilungsfaktor]]. Folgende Teilungsfaktoren sind verfügbar:<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- {{Hintergrund1}}<br />
!|ADPS2 || ADPS1 || ADPS0 || Teilungsfaktor<br />
|- align="center"<br />
|0 || 0 || 0 || 2<br />
|- align="center"<br />
|0 || 0 || 1 || 2<br />
|- align="center"<br />
|0 || 1 || 0 || 4<br />
|- align="center"<br />
|0 || 1 || 1 || 8<br />
|- align="center"<br />
|1 || 0 || 0 || 16<br />
|- align="center"<br />
|1 || 0 || 1 || 32<br />
|- align="center"<br />
|1 || 1 || 0 || 64<br />
|- align="center"<br />
|1 || 1 || 1 || 128<br />
|}</div><br />
<br />
*'''ADPS1 (ADC Prescaler Select Bit 1)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.<br />
*'''ADPS0 (ADC Prescaler Select Bit 0)'''<br/>Siehe '''ADPS2''' für eine Beschreibung.<br />
<br />
=== ADMUX ===<br />
<br />
ADC Multiplexer Selection Register<br />
<br />
Mit diesem Register wird u.a. der Multiplexer gesteuert.<br />
<br />
<div align="center">{{Registertabelle8BitFix|REFS1|REFS0|ADLAR|MUX4|MUX3|MUX2|MUX1|MUX0}}</div><br />
<br />
*'''REFS0, REFS1 (Reference Selection Bits 0,1)'''<br />
Mit diesem Bit kann steuern werden, welche Referenzspannung der ADC verwenden soll. Die möglichen Quellen sind unten aufgelistet. Wird während einer Wandlung die Quelle für die Referenzspannung geändert, wird die aktuelle Wandlung mit der "alten" Quellen zuerste beendet, bevor die neue Einstellung übernommen wird.<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- {{Hintergrund1}}<br />
!|REFS1 || REFS0 || Referenzspannungsquelle<br />
|-<br />
|0 || 0<br />
|AREF, internes Vref deaktiviert<br />
|-<br />
|0 || 1<br />
|AVCC mit externen Kondensator am AREF Pin<br />
|-<br />
|1 || 0<br />
|Keine Funktion, reserviert<br />
|-<br />
|1 || 1<br />
|Interne 2,56V Spannungsreferenz mit externen Kondensator am AREF Pin<br />
|}</div><br />
<br />
<br />
*'''ADLAR (ADC Left Adjust Result)'''<br/>Dieses Bit beeinflusst, wie der ermittelte Messwert im ADC Data Register abgelegt wird. Bei '''ADLAR'''=1 liegen die oberen 8 Bits im Register ADCH.<br />
<br />
*'''MUX3,MUX4 (Analog Channel and Gain Selection Bits 3,4)'''<br/>Mit diesen Bits können Gain und Differenz-Kanäle gewählt werden. Speziell steht 00 für keine Verstärkung und einfache Eingänge. Weitere Möglichkeiten stehen im Datenblatt.<br />
<br />
<div align="center"><br />
{| {{Blauetabelle}}<br />
|- {{Hintergrund1}}<br />
!|MUX4..0 || Eingang<br />
|-<br />
|00000 || ADC0<br />
|-<br />
|00001 || ADC1<br />
|-<br />
|00010 || ADC2<br />
|-<br />
|00011 || ADC3<br />
|-<br />
|00100 || ADC4<br />
|-<br />
|00101 || ADC5<br />
|-<br />
|00110 || ADC6<br />
|-<br />
|00111 || ADC7<br />
|-<br />
|10000 || ADC0-ADC1<br />
|-<br />
|11110 || Ref. 1.22 V<br />
|}</div><br />
<br />
*'''MUX0...MUX2 (Analog Channel and Gain Selection Bits 0..2)'''<br/>Auswahl des Eingangskanals. Siehe Tabelle. Für die einfachen Kanäle reicht es also einfach die Pinnummer in die unteren Bits von ADMUX zu schreiben.<br />
<br />
=== ADCL / ADCH ===<br />
<br />
Desweiteren gibt es noch die Register '''ADCL/ADCH''' hier steht das Ergebnis einer Wandlung. Wie bei den meisten auf 2 Register verteilten Werten, bewirkt das lesen des Low-Bytes ein puffern des High-bytes. Der Wert wird folgendermaßen ausgelesen:<br />
<br />
<br />
uint16_t x = ADCL;<br />
x += (ADCH<<8);<br />
// oder besser<br />
x = ADCW;<br />
<br />
= Siehe auch =<br />
<br />
* [[Atmel]]<br />
* [[HEX Beispiel-Dateien für AVR]]<br />
<br />
<br />
= Weblinks =<br />
<br />
* [http://www.atmel.com/dyn/products/param_table.asp?family_id=607&OrderBy=part_no&Direction=ASC Aktuelle AVR Vergleichstabelle]<br />
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]<br />
<br />
<br />
[[Kategorie:Abkürzung]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Praxis]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Getriebemotoren_Ansteuerung&diff=14867Getriebemotoren Ansteuerung2009-04-26T05:47:24Z<p>Holzi: </p>
<hr />
<div>Ist der Entschluss gefasst, für seinen Roboter oder andere Konstruktion einen Getriebemotor zu verwenden, so müssen sich Gedanken gemacht werden, wie er ansteuert werden kann. Gewöhnlich sollen die Motoren ja sowohl in Bezug auf Drehrichtung und Geschwindigkeit über eine Programmiersprache angesteuert werden. Daher wird in der Regel erst mal ein Controllerboard benötigt. Leider kann man an die wenigsten Controllerboards einen Getriebemotor direkt anschließen, eine der wenigen Ausnahmen ist das [[RN-Control]]-Board und das RNBFRA-Board. Bei beiden Boards ist es einfach, dort müssen die Getriebemotoren einfach nur an die Schraubklemmen angeschlossen werden, danach kann man sofort mit der Programmierung loslegen.<br />
<br />
Ich möchte hier aber aufzeigen, wie man Motoren auch bei anderen Boards anschließen kann. Die gleiche Technik läßt sich natürlich auch nutzen, um z.B. mehr als zwei Motoren an [[RN-Control]] anzuschließen.<br />
<br />
==Ansteuerung mit Relais==<br />
<br />
Die einfachste Methode, um Motoren per [[Microcontroller|Controller]] anzusteuern, erreicht man durch die Verwendung von Relais. Mit einem Relais, das zwei Umschaltkontakte besitzt, lässt sich über einen einzelnen Controllerport bequem die Drehrichtung wechseln.<br />
<br />
[[Bild:hbrueckerelais.gif|center]]<br />
<br />
Da auch Relais wegen des Strombedarfes nicht direkt vom Controller geschaltet werden können, wurde in dem oberen Beispiel ein Transistor vorangestellt. Die Diode dient dazu, die Spannungen abzuleiten, die beim Ausschalten des Relais induziert werden. Ohne Diode könnte der Transistor oder sogar der Controller durch die induzierte Spannung beschädigt werden. <br />
Die Schaltung ist also in der Lage, die Drehrichtung umzuschalten, jedoch nicht in der Lage, den Motor zu stoppen. Um den Motor ganz auszuschalten, könnte man man 2 getrennte Relais für die beiden Umschaltkontakte nutzen. Ein Schaltbild können wir uns ersparen, da das Ganze recht ähnlich aussieht. <br />
Der große Nachteil von Relaisschaltungen ist, dass die Geschwindigkeit des Motors nicht geregelt werden kann, zudem haben Relais bei sehr vielen Schaltvorgängen einen gewissen Verschleiß. <br />
Vorteil der Schaltung ist jedoch, das man auch sehr große Lasten/Motoren schalten kann.<br />
<br />
==Ansteuerung mit Relais und MOS-FET==<br />
Die Schaltung ist sehr ähnlich wie die normale Relaisschaltung. Es wird aber in die Masseleitung hinter dem Relais ein [[Feldeffekttransistor#MOSFETS|MOSFET]] und eine Freilaufdiode eingesetzt. Dadurch werden die Nachteile der einfach Relaisschaltung behoben. Durch den MOSFET läßt sich der Motor in der Geschwindigkeit regeln und ggf. abschalten.<br />
<br />
[[Bild:RelaisundFet.png|center]]<br />
<br />
Es sind prinzipiell alle N-Kanal MOS-FETs geeignet. Für die hier gezeigte direkte Steuerung vom µC sollte es ein Logik-Level-Typen sein. Der FET IRLZ34 sollte ohne Kühlung bis etwa 5 A genügen. Die Freilaufdiode D1 muß für den Motorstrom ausgelegt sein, und bei PWM Steuerung genügend schnell sein(z.B. Shottky). Die Induktivität L1 (ca. 10...100 µH) und der Kondensator C1 dienen zur Funkentstörung und können bei kurzem Kabel zum Motor auch weggelassen werden. Um die Umschaltverluste und Funkstörungen gering zu halten, sollte die [[PWM]]-Frequenz (< 1 kHz) nicht unnötig hoch liegen.<br />
Da das Relais nur Strom verbraucht, wenn es angezogen wird, sollte man den Motor so anschließen, dass in der bevorzugten Drehrichtung (beim Roboter Vorwärtsfahren) das Relais nicht angezogen ist. <br />
Die Schaltung ist sicher gegen Querströme und es können durch Fehler im Programm des µC keine Schäden entstehen. Das Relais sollte erst umgeschaltet werden, wenn der Motor steht, dann gibt es keine Funken an den Relaiskontakten.<br />
<br />
Der Verdrahtungsaufwand insgesamt ist minimal und sogar kleiner als bei Motortreiber-ICs, wie dem [[Getriebemotoren_Ansteuerung#Ansteuerung_mit_dem_Schaltkreis_L298|L298]], da keine zusätzlichen Bauteile benötigt werden. Daher ist die Schaltung insbesondere für Anfänger geeignet.<br />
<br />
Vorteile sind:<br />
*tollerant gehen Fehler im µC Programm<br />
*hohe Strombelastbarkeit<br />
*sehr geringer Spannungsabfall (< 1 V)<br />
*niedrige Kosten, auch bei hoher Leistung<br />
*das Relais kann stromlos geschaltet werden (wenig Verschleiß an Kontakten)<br />
<br />
Nachteile sind:<br />
*hörbares "Klacken" beim Laufrichtungswechsel<br />
*zusätzlicher Stromverbrauch, wenn das Relais geschaltet ist<br />
*keine einfache Motorbremse<br />
*(Verschleiß der Relais, tritt aber erst bei sehr sehr vielen Schaltvorgängen auf)<br />
<br />
==Ansteuerung mit MOS-FET==<br />
===Neufassung===<br />
{{Ausbauwunsch|Die Neufassung kann im momentanen Stand nur als Anregung verstanden werden.<br />
<br />
Insbesondere fehlen noch angepasste Schaltpläne.<br />
<br />
Einige der Anmerkungen aus dem Abschnitt "Kritik an der Schaltung" sind in der Neufassung noch nicht enthalten, die Beschreibung von Verzögerungsgliedern müsste auch eine Erklärung enthalten, welche Verzögerung mit welchen Werten erreicht wird.<br />
<br />
Wenn die Neufassung komplett fertig ist, sollten die alten Texte weg.<br />
}}<br />
====Grundprinzip====<br />
Wesentlich günstiger und auch beliebter ist die Ansteuerung von Motoren mit [[Feldeffekttransistor#MOSFETS|MOS-FET]]s. Also (unipolaren) Transistoren, die quasi leistungslos nur durch Spannungen geschaltet werden und extrem hohe Ströme verkraften. Zu diesem Thema findet man unzählige Beiträge im Roboternetz.<br />
<br />
Die Grundschaltung besteht aus 2 N-Kanal-MOS-FET (hier BUZ11) und zwei P-Kanal-MOS-FET(hier [[Im RN-Wiki verwendete Transistoren|IRF5305]]), mit denen die Motoranschlüsse nach GND bzw. UB geschaltet werden. Zusätzlich sind 4 [[Im RN-Wiki verwendete Elektronikbauteile|Schottky-Dioden]] (z.B. [[Im RN-Wiki verwendete Elektronikbauteile|SB530]]) erforderlich, um Induktionsströme des Motors abzuleiten. Die Dioden werden in Sperrichtung von den beiden Motoranschlüssen nach GND bzw. UB geschaltet.<br />
Auf die extra Dioden kann bei einer Vollbrücke mit modernen MOSFETs meistens verzichtet werden, da die MOSFETs bereits hinreichend gute Dioden enthalten.<br />
<br />
Grundsätzlich muss die Beschaltung der Gate-Eingänge so erfolgen, dass zum Starten des Motors die Transistoren einer Diagonale auf "leitend" und die der anderen auf "sperrend" geschaltet werden. Zum Anhalten des Motors werden z.B. die unteren auf leitend und die oberen auf sperrend geschaltet (Der Motor wird aufgrund des nicht unerheblichen Bremsstroms von Transistor und Freilaufdiode stark gebremst).<br />
Alternativ kann man auch alle Transistoren auf sperrend schalten, der Motor läuft dann im Leerlauf aus.<br />
<br />
Die Transistoren einer Seite dürfen nicht gleichzeitig auf "leitend" geschaltet werden, da dies einen Kurzschluss verursacht.<br />
<br />
Hinweis: Zumindest bei dem Transistor [[Im RN-Wiki verwendete Transistoren|BUZ11]] handelt es sich um ein veraltetes Modell. Wenn es auf hohe Leistung ankommt, sollte da ein anderer Transistor gewählt werden (z.B. [[Im RN-Wiki verwendete Transistoren|IRF 530]]).<br />
<br />
====Elektrische Ansteuerung der Gates====<br />
Beim Umschalten der Transistoren entsteht eine erhöhte Verlustleistung - der Widerstand wechselt von sperrend (sehr großer Widerstand) nach leitend (sehr kleiner Widerstand) und umgekehrt.<br />
<br />
Zwischen beiden Enden des Schaltvorgangs befindet sich der Transistor in der "Widerstandsphase" (weder ganz leitend, noch ganz sperrend), die eine erhebliche Verlustleistung und damit Erwärmung mit sich bringt.<br />
<br />
Deshalb sollte der Schaltvorgang möglichst schnell erfolgen, insbesondere wenn für eine [[PWM]]-Regelung sehr oft geschaltet werden soll. Da zum Umschalten die durch den Aufbau des MOSFETs bedingte Gatekapazität umgeladen werden muss, ist hierzu (sehr kurzzeitig) ein hoher Stromfluss nötig. Zu schnell sollte man wegen der Funkstörungen aber auch nicht schalten.<br />
<br />
=====Schaltung direkt am Port=====<br />
Eine Ansteuerung unmittelbar über den Ausgang eines Mikrocontrollers (oder eines TTL-IC) ist schon wegen der benötigten Spannungen nicht möglich. <br />
<br />
Bei den N-FET kann man sog. "Logik-MOSFET" nehmen, die bereits bei 5 V ausreichend leitet. <br />
<br />
Bei den P-[[MOSFET]] bemisst sich die Schaltspannung gegen UB, mit einem 5 V Port und U<sub>B</sub>=12 V würde also zwischen -12 V und -7 V umgeschaltet, was einen P-[[MOSFET]] erfordern würde, der bereits bei -7 V sperrt.<br />
<br />
Dass ein Portpin nur einen geringen Stromfluss (ca. 20 mA) zulässt, ist ein weiteres Problem und verhindert einen Schaltvorgang mit idealer steiler Flanke. Allerdings ist die Schaltungsvariante mit einem Transistor in diesem Punkt keinesfalls besser, wenn die Gatekapazität durch den PullUp-Widerstand umgeladen werden muss.<br />
Diese Schaltungsversion ist für nicht zu große FETs (bis etwa 2 nF Gate Kapazität), bevorzugt ohne PWM, möglich.<br />
<br />
=====Schaltung mit einem Transistor=====<br />
Eine einfache Steuerschaltung besteht aus einem Transistor-Schalter und einem Pull-Up-Widerstand. Als Schalter hab ich 1/7 eines [[Im RN-Wiki verwendete ICs|ULN2003]] IC verwendet, als PullUp 2200 Ohm. Ein diskreter Aufbau mit 1 Transistor und 2 Widerständen ist aber auch nicht komplizierter.<br />
<br />
Der Vorteil liegt in der Einfachheit, der Nachteil liegt darin, dass die Schaltung nicht sonderlich schnell vonstatten geht: Für die Schaltung des FET muss die Gate-Kapazität transferiert werden, was insbesondere beim Wechsel von 0 V nach U<sub>B</sub> einen Moment dauert, da die Ladung durch den Widerstand hindurch muss.<br />
<br />
Ein kleinerer Widerstand könnte hier helfen, verursacht allerdings einen nicht unerheblichen Stromfluss im geschalteten Zustand (zulässige Verlustleistung beachten).<br />
<br />
=====Schaltung mit zwei Transistoren=====<br />
Eine bessere Ansteuerung sollte sich ergeben, wenn man zwei Transistoren zur Gate-Ansteuerung verwendet: Einer schaltet gegen 0 V, der andere gegen UC. So kann man erreichen, dass in beide Richtungen rasch umgeschaltet werden kann.<br />
<br />
=====Integrierte Gate-Treiber=====<br />
Statt der Beschaltung mit zwei Transistoren kann man auch einen integrierten [[MOSFET]]-Treiber verwenden. Derartige ICs sind darauf ausgelegt, kurzfristig den für eine Umschaltung benötigten hohen Stromfluss zu ermöglichen.<br />
<br />
Es gibt auch Treiber-ICs, die zur Ansteuerung der oberen Transistoren eine Spannung oberhalb von UB erzeugen. Mit solchen Highside-Treibern kann die H-Brücke auch aus 4 N-Kanal-Transistoren gebaut werden, was den Vorteil hat, dass N-Kanal-FETs mit geringerem Schaltwiderstand zu bekommen sind.<br />
<br />
====Logische Ansteuerung der Gates====<br />
Nach der elektrischen Ansteuerung ist die logische Ansteuerung durch den Mikrocontroller zu überlegen.<br />
<br />
=====Mögliche Querströme=====<br />
In der H-Brücke sind zwei problematische Zustände zu berücksichtigen:<br />
<br />
1. Das offensichtliche Problem ist ein Kurzschluss: Wenn beide Transistoren einer Seite auf leitend geschaltet werden, dann wird dadurch ein Kurzschluss erzeugt. Falls vorhanden brennt die Sicherung durch oder es wird sogar etwas beschädigt.<br />
<br />
2. Ein nicht so offensichtliches Problem rührt daher, dass der Schaltvorgang nur mit endlicher Geschwindigkeit abläuft und der Transistor auch schon vor Erreichen des Zielwertes der Gate-Spannung erheblichen Strom leitet. Hierdurch kommt es zu einem Kurzschluss durch den nicht mehr richtig gesperrten und den noch nicht richtig gesperrten Transistor.<br />
<br />
Die Stromspitze selbst liegt noch im Rahmen der Spezifikationen der Transistoren. Sofern ein Messwiderstand von z.B. 0,1 Ohm da ist oder die Spannungsquelle einen vergleichbaren Innenwiderstand hat fließt ein Strom von weniger als 70 A, die Transistoren sind jeweils für Spitzen von über 100 A spezifiziert.<br />
<br />
Allerdings hat die Stromspitze drei Auswirkungen: <br />
<br />
# Die Transistoren erwärmen sich<br />
# Es kann an einem Messwiderstand zu einer Spannungsspitze kommen<br />
# Die Versorgungsspannung bricht kurzzeitig zusammen<br />
<br />
----<br />
<br />
Die Erwärmung des Transistors ist solange kein Problem, wie nur selten umgeschaltet wird. Bei einer Regelung per [[PWM]] könnten sich die kleinen Energiemengen zu einem relevanten Problem addieren. <br />
<br />
Da die Erwärmung - sofern sie relevant wird - leicht ohne Messinstrumente feststellbar ist, dürfte dieser Teil des Problems insofern handhabbar sein, als man leicht feststellen kann, ob das Problem relevant ist und das Problem auf die Transistoren beschränkt sind.<br />
<br />
Bei Leerlauf-Schaltvorgängen im Abstand von 1/15 Sekunden habe ich keine Erwärmung der Transistoren feststellen können, es wurden auch keine zusätzlichen Kühlkörper verwendet.<br />
<br />
----<br />
Die Spannungsspitze am Messwiderstand kann abgeleitet werden:<br />
Als weitere Vorsichtsmaßnahme habe ich den Messport des Controllers mit einem Widerstand und einer Z5.1 Diode abgesichert.<br />
<br />
----<br />
<br />
Die Störung der Versorgungsspannung lässt sich ohne Oszilloskop nicht messen. Insbesondere in umfangreicheren Schaltungen können Störungen an ganz anderen Stellen (z.B. bei Sensoren) auftreten, die man dann nicht gleich mit der Motorsteuerung in Verbindung bringt.<br />
<br />
Um die Störung vom Controller fernzuhalten habe ich dem Spannungswandler vorsichtshalber eine kleine Schottky-Diode ([[Im RN-Wiki verwendete Elektronikbauteile|SB140]]) vorgeschaltet, um ein Entladen des Stützkondensators zu verhindern.<br />
<br />
=====softwaremäßige Ansteuerung=====<br />
Die einfachste Art der Ansteuerung besteht darin, die Schalter der 4 Gates mit 4 Ausgängen des Controllers zu verbinden.<br />
<br />
Die korrekte Ansteuerung muss dann durch die Software garantiert werden. <br />
<br />
Eine Fehlschaltung der Software z.B. bei einem Absturz kann allerdings zur Zerstörung der Schaltung führen, die Schaltung sollte also in jedem Fall eine Sicherung haben.<br />
<br />
=====Einfache Ansteuerung=====<br />
Etwas sicherer ist es, die Schaltung so aufzubauen, dass ein Kurzschluss nicht dauerhaft geschaltet werden kann.<br />
<br />
Hierzu habe ich die Schaltung so aufgebaut, dass die Gates einer Seite jeweils gemeinsam geschaltet werden. <br />
<br />
Bei einer Gate-Spannung von 0V sperrt der N-[[MOSFET]] (U<sub>GS</sub>=0V), der P-[[MOSFET]] leitet bei dieser Gate-Spannung, da hier U<sub>GS</sub>=-UB ist. <br />
<br />
Bei einer Gate-Spannung von UB verhält es sich genau umgekehrt: Der N-[[MOSFET]] leitet (U<sub>GS</sub>=UB) und der P-[[MOSFET]] sperrt (U<sub>GS</sub>=0V)<br />
<br />
Diese einfache Ansteuerung benötigt lediglich zwei Transistorschalter und auch nur 2 Port-Pins, hat jedoch den Nachteil, dass während des Umschaltens die oben beschriebenen Querströme auftreten können. Außerdem ist die gemeinsame Ansteuerung der Gates nur für Spannungen von etwa 6V bis 12 V möglich.<br />
<br />
=====Verbesserungsmöglichkeiten=====<br />
Zur Lösung des Querstrom-Problems gibt es mehrere Ansatzmöglichkeiten, die ebenfalls mit zwei Controller-Ausgängen auskommen.<br />
----<br />
Mittels Logik-Bausteinen werden zwei Ausgänge des Controllers so umgesetzt, dass die folgenden Zustände geschaltet werden können:<br />
<br />
# Motor-Stop: untere Transistoren leitend, obere sperrend (oder umgekehrt)<br />
# Motor-Vorlauf: 1. Diagonale leitend<br />
# Motor-Rücklauf: 2. Diagonale leitend<br />
# Motor-Leerlauf: Alle Transistoren sperrend<br />
<br />
Die Querstrom-Problematik kann hierbei softwaremäßig gelöst werden, indem beim Umschalten jeweils kurz der Leerlauf geschaltet wird, damit alle Transistoren sperren.<br />
----<br />
Eine andere Möglichkeit besteht darin, das Umladen der Gate-Kapazität asymmetrisch zu gestalten, so dass die Transistoren schneller auf sperrend als auf leitend geschaltet werden. Eine einfache Möglichkeit ist die Parallelschaltung einer Diode und eines Widerstandes: In Sperr-Richtung fließt die Ladung langsamer als in die Durchlass-Richtung.<br />
<br />
===Heidingscher Encoder===<br />
Aufgrund der Kritik an der alten Schaltung(siehe '''Alte Schaltungsbeschreibung''') entschied ich mich einen neuen, einfachen sowie preisgünstigen Encoder zu entwickeln, den man mit der 74series aufbauen kann. Als Treiber können sowohl Transistoren verwendet werden, dabei aber Vorwiderstände nicht vergessen! Die [[Im RN-Wiki verwendete ICs|74series]] sind mit 20 mA Treiberstrom also natürlich nicht zum direkten Treiben geeignet.<br />
Die Logikanzeigen in den Grafiken sollen je einen Transistor bzw. Mosfet darstellen. Eventuelle Freilaufdioden müssen natürlich noch hinzugefügt werden.<br />
<br />
====PR Encoder====<br />
[[Bild:Prtreiber.png]]<br />
<br />
Der PR Encoder(PWM-Richtung Encoder) ist mit zwei NOR Gates sowie eines Inverters aufgebaut, d.h. man kann ihn mit nur einem [[Im RN-Wiki verwendete ICs|IC(74HC(T)02)]] aufbauen. Will mein 2 Encoder verwenden, empfiehlt sich den Inverter auszulagern [[Im RN-Wiki verwendete ICs|(74HC(T)04]] oder [[Im RN-Wiki verwendete ICs|74HC(T)14]]. Sollte man keinen Schmitt-Trigger benötigen empfiehlt sich aus Schnelligkeitsgründen die [[Im RN-Wiki verwendete ICs|74HC(T)04]] Variante). <br />
Alternativ ist es noch möglich sich den Inverter zu sparen, und die Ansteuerung für den P(WM) Kanal invertiert laufen zu lassen.<br />
<br />
====PRK Encoder====<br />
[[Bild:Prktreiber.png]]<br />
<br />
Der Prk-Encoder([[PWM]]-Richtung-Kurzschluss-Encoder) ist eine Erweiterung des PR-Encoders. Er erlaubt es zusätzlich, die Motoren durch einen Kurzschluss zu stoppen.<br />
Aufgebaut werden kann dieser aus 1 NOR und 1 NAND Gate. Dabei werden 3 NAND-Gates als Inverter beschaltet (d.h. eine Leitung, die übrigen bleiben auf VCC).<br />
<br />
====Support====<br />
Fragen einfach in das Forum posten, oder mich anschreiben (User s.o.)<br />
<br />
===Alte Schaltungsbeschreibung===<br />
{{FarbigerRahmen|<br />
Achtung! Die Schaltung ist so nicht zu verwenden! Siehe unter '''Kritik an der Schaltung'''<br />
}}<br />
Wesentlich günstiger und auch beliebter ist die Ansteuerung von Motoren mit MOS-FETs. Also Transistoren, die quasi leistungslos nur durch Spannungen geschaltet werden und extrem hohe Ströme verkraften. Zu diesem Thema findet man unzählige Beiträge im Roboternetz. Eine der interessantesten Schaltungen, die im Roboternetz vorgestellt wurde, dürfte diese sein:<br />
<br />
<br />
[[Bild:hbrueckemosfet.gif|center]]<br />
<br />
<br />
Anmerkung: Den 74HC26N gibts wohl nicht , nur die TTL-Version [[Im RN-Wiki verwendete ICs|74LS26]], die HC-Mos-Version lautet [[Im RN-Wiki verwendete ICs|74HC03]].<br />
<br />
Eine sogenannte H-Brücke, die nur aus zwei MOSFETSs und einem Logik-IC besteht. Mit zwei Controllerports kann diese Schaltung sowohl Geschwindigkeit als auch Drehrichtung regeln. Für die Geschwindigkeit ist ein sogenannter [[PWM]]-Port notwendig. Also ein Port, der durch ein gepulstes Signal den Motor etlichemal innerhalb einer Sekunde ein- und ausschaltet und somit quasi die Leistung regelt (siehe [[PWM]]).<br />
Die Schaltung ist so konstruiert, dass immer nur zwei Transistoren durchschalten. Auf diese Weise fließt einmal der Strom von links oben nach rechts unten und einmal von rechts oben nach links unten, der Motor wird also ähnlich wie bei der Relaisschaltung umgepolt. <br />
Bei niedriger [[PWM]]_Frequenz sollte die Schaltung durchaus für einige Ampere geeignet sein, wobei ca. 8 bis 13 V ideal sein sollten.<br />
<br />
Das Logic-IC wurde durch 3x [[Im RN-Wiki verwendete Transistoren|BC547]] Transitoren ersetzt.<br />
<br />
<br />
[[Bild:Hbrückenmosfet BD547.PNG|center|900px]]<br />
<br />
====Kritik an der Schaltung====<br />
<br />
Diese Schaltung wird [http://www.roboternetz.de/phpBB2/viewtopic.php?t=33067&sid=892e80c6cd2d003292e607bcd7a7123aim hier Forum von mehreren Leuten, u.A. Ratber, shaun, massiv kritisiert].<br />
<br />
Ich habe leider nicht das Wissen eine bessere Lösung zu liefern. Das Problem sind die Querströme: Im Umschaltmoment sind highside und lowside switch für kurze Zeit beide leitend. Das entspricht einem Kurzschluss der Versorgungsleitung bei jedem Umschalten mit allen damit verbundenen Problemen (Erwärmung, Schwingung, Sicherungen, Reset). Aus diesem Grund sind NAND-Gatter nicht geeignet!<br />
<br />
Zum Umschalten muss man<br />
*den bisher leitenden [[MOSFET]] ausschalten,<br />
*dann etwas warten,<br />
*und dann den nächsten [[MOSFET]] schließen.<br />
<br />
Dies kann man erreichen, indem man den Einschaltmoment <br />
*durch RC-Glieder verzögert und <br />
*den Ausschaltmoment durch Dioden beschleunigt.<br />
Die entstehenden Schaltungen sind komplex, benötigen viele Bauteile und sind fehleranfällig.<br />
<br />
<br />
Am sinnvollsten sind integrierte [[MOSFET]]-Treiber. Diese haben oft eine einstellbare Tot-Zeit (''Dead-Time''), können hohe Leistungen zum Umladen der Gatekapazität liefern und beachten andere Effekte wie ''Propagation-Time'', Veränderung des Source Potentials beim Highside-switch, etc.<br />
<br />
'''Erklärung von shaun:'''<br />
<br />
Die gezeigte Schaltung taugt auch nur als Prinzipschaltung bedingt, da man einen variierenden Aufwand in eine sichere Verriegelung investieren müsste. Bei fixer und nicht zu hoher Betriebsspannung könnte man mit RD-Kombinationen in den Gateleitungen das Ausschalten beschleunigen und das Einschalten verzögern, so dass die Querleitung wegfällt. Allerdings bewirkt diese simple R-Cg-Verzögerung größere Schaltverluste. <br />
<br />
Setzt man die Verzögerung vor dedizierte Treiber, müssen diese wiederum leistungsfähig genug zum Umladen der Gates sein und bis an die Versorgung heranreichen, weshalb man an diesem Punkt überlegen sollte, ob 95% duty cycle nicht auch reichen würden ''(Anmerkung: Bezug auf bootstrapping?)'' und man integrierte Treiber für reine N-Kanal-Bestückung einsetzen sollte - spart dann wieder etwas Verluste am Highside-Switch, weil N-Kanäler gleicher Generation und Leistungsklasse einen niedrigeren Rds(on) als ihre P-Pendants haben.<br />
<br />
{{Ausbauwunsch|Eine vernünftige diskrete Ansteuerung für eine H-Brücke.<br />
Korrektur auf Rechtschreibfehler, Zeichensetzung, Schreibstil, Fachausdrücke. Gibt's denn keinen, der etwas verbessern möchte?}}<br />
==Ansteuerung mit einem LeistungsOPV==<br />
Die wohl preislich und platztechnisch günstigste Alternative zur Ansteuerung von Motoren in H-Brücken ist die Verwendung von (Leistungs-)Operationsverstärkern.<br />
<br />
===Heidingscher Motortreiber=== <br />
Bei dem Heidingschen Motortreiber wird jeder Anschluss des Motors mit einem Ausgang des Operationsverstärker verbunden, die Eingänge des OPVs selbst als Komparator. Diese Methode ist für kleine und mittlere Motoren(=< 1A) und mäßige PWM-Frequenzen(<10kHz) gut geeignet. Ein RB35 von Conrad kann damit problemlos angesteuert werden. Bei zu hohen [[PWM]]-Frequenzen ist die SlewRate von vielen OPVs zu gering und die entsprechenden OPVs sind dann viel zu teuer und man sollte eine Ansteuerung per [[MOSFET]] (s.o.) bevorzugen. Momentan hat sich der [[Im RN-Wiki verwendete ICs|TCA 0372 DP1]] (0,57€ bei Reichelt) Verwendung gefunden. <br />
Weitere Informationen sind in [http://www.roboternetz.de/phpBB2/viewtopic.php?t=38412 diesem Forumsbeitrag] zu finden.<br />
<br />
===Gleichstromansteuerung===<br />
Eine weitere Möglichkeit ist es, dem Operationsverstärker eine Gleichspannung vorzugeben, mit denen der OPV die Motoren ansteuert. Diese Methode eignet sich sehr gut für analoge Schaltkreise. Der Wirkungsgrad ist allerdings nicht der beste, da die restliche Spannung in Wärme umgesetzt wird. Zudem werden viele weitere Komponenten benötigt, was den Aufbau teurer und fehleranfälliger macht.<br />
Der entsprechende Schaltkreis ist im Datenblatt des TCA 0372 DP1 zu finden.<br />
<br />
==Ansteuerung mit Treiber IC L293 D==<br />
<br />
Dies ist ohne Zweifel die am häufigsten genutzte Ansteuerung bei Roboter-Bastlern: Man nimmt einfach das IC L293D, denn darin sind sogar zwei H-Brücken enthalten. Also mit einem IC lassen sich ohne weitere externe Bauteile gleich zwei Motoren ansteuern. Zwar nur bis ca. 600mA, aber das reicht oft schon für kleinere bis mittlere Roboteranwendungen aus.<br />
<br />
[[Bild:L293Pinout.JPG|center]]<br />
<br />
<br />
[[Bild:hbrueckel293d.gif|center]]<br />
<br />
Wie aus dem Schaltbild zu ersehen ist, werden für die Ansteuerung jedes Motors 3 Ports benötigt. Die Enable-Leitung führt man oft auf einen [[PWM]]-Port welcher wie bei der [[MOS-FET]] Schaltung oben die Geschwindigkeit regelt. Die beiden anderen Ports geben die Drehrichtung an. Immer wenn die Ports unterschiedliche Polarität haben dreht der Motor in eine bestimmte Richtung, je nachdem wo Low und High anliegt. Das Besondere ist, dass wenn an beiden Ports der gleiche Pegel anliegt, also zweimal Low oder High, dann wird nämlich der Motor kurzgeschlossen, das dann als Bremse fungiert. Das Bremsen kann bei Robotern durchaus nützlich sein. Zudem ist bei schnellen Richtungswechseln immer zu empfehlen zuerst kurz zu bremsen, um nicht den Motor oder Motortreiber zu stark zu belasten.<br />
<br />
==Ansteuerung mit dem Schaltkreis L298==<br />
<br />
Der Schaltkreis [[Im RN-Wiki verwendete ICs|L298]] ist quasi der große Bruder des [[Im RN-Wiki verwendete ICs|L293D]]. Er beinhaltet auch zwei komplette H-Brücken, kann also auch zwei Motoren ansteuern. Die Pinbelegung ist ebenfalls dem [[Im RN-Wiki verwendete ICs|L293D]] sehr ähnlich, jedoch verfügt er über eine andere Bauform:<br />
<br />
<br />
[[Bild:L298Pinout.JPG|center]]<br />
<br />
<br />
Der wichtigste Unterschied besteht jedoch darin, dass jede H-Brücke bei [[Im RN-Wiki verwendete ICs|L298]] bis zu 2 A belastet werden kann. Damit lassen sich also schon wesentlich größere Motoren ansteuern. Ein weiterer Vorzug sind die sogenannten SENSE-Ausgänge, über die der komplette Strom fließt. Oft wird hier ein Hochlastwiderstand angeschlossen, um aus der abfallenden Spannung den Strom berechnen zu können. Dies machen sich Steuerungen wie [http://www.roboternetz.de/phpBB2/viewtopic.php?t=2741 RN-Motor] oder aber andere Schrittmotoransteuerungen zunutze, um den Strom zu regeln. Benötigt man keine Strommessung, so müssen die Sense-Ausgänge direkt mit GND verbunden werden. Anders als beim [[Im RN-Wiki verwendete ICs|L293D]] werden hier externe Freilaufdioden gebraucht.<br />
<br />
<br />
[[Bild:hbrueckel298.gif|center]]<br />
<br />
<br />
Ein weiteres Schaltbild gibt es hier [http://www.roboternetz.de/bilder/schaltung298getriebe.gif]<br />
<br />
==Ansteuerung mit L6205==<br />
Der Schaltkreis [[Im RN-Wiki verwendete ICs|L6205]] stellt eine etwas modernere Alternative zur L298-Ansteuerung dar. Die Ansteuerung ist praktisch identisch, der Schaltungsaufbau in etwa gleich. Beim L6205 sind keine externen Freilaufdioden mehr notwendig, dafür ist ein Kondensator und zwei Dioden für die interne Spannungserzeugung notwendig.<br />
Ein großer Vorteil ist auch, dass kein extra Kühlkörper mehr notwendig ist. Viele integrierte Schutzfunktionen im L6205 sorgen dafür, dass der Chip nicht so einfach zerstört werden kann. In der Praxis sind die angegeben 2,8 A jedoch mit Vorsicht zu genießen. Bei Testlayouts erwärmten sich die ICs bereits bei 2 A Dauerstrom (PWM) oft so stark, dass die automatische Temperaturabschaltung reagierte, somit wird man vermutlich ohne Kühlung oder großes Kühllayout auf der Platine auch nicht mehr als beim [[Im RN-Wiki verwendete ICs|L298]] erreichen. <br />
<br />
[[Bild:l6205ic.gif]] [[Bild:l6205pinbelegung.gif]]<br />
<br />
<br />
[[Bild:l6205.gif|center]]<br />
<br />
==Noch mehr Power gewünscht?==<br />
<br />
Obwohl der L298 schon einiges abdeckt, so kommt er spätestens bei den Scheibenwischermotoren langsam an seine Grenzen. Bei starker Belastung können solche Motoren kurzzeitig bis ca. 10 A und mehr ziehen. Für solch starke Motoren gibt es jetzt einen ganz interessanten Motorchip aus dem Kfz-Bereich: vnh3sp (Datenblatt im Roboternetz Download-Bereich). <br />
Mit ihm lassen sich sogar recht große Motoren ansteuern; vorausgesetzt, man kühlt ihn entsprechend, so verträgt der Chip bis zu 30 A. Aber selbst ohne Kühlung bietet er bedeutet mehr Leistung als der L298. Das Schöne, die Ansteuerung ist kaum anders als beim L298 und L293D.<br />
<br />
Kleiner Nachteil: Da es ein SMD-Chip mit 1mm Kontaktabstand ist, muss man schon eine geeignete Platine (spezielles Layout mit Kühlflächen) und etwas Löterfahrung besitzen. Inzwischen gibt es aber schon verschiedene RN-Projekte mit dem Chip (RN-Power, RN-Mini H-Bridge), Platinen und Chip können über den [http://www.shop.robotikhardware.de/shop/catalog/index.php Robotikhardware.de-Platinenservice] bezogen werden. <br />
<br />
<br />
[[Bild:minihbridge_ansteuerung.gif|center]]<br />
<br />
<br />
Alternativ zum [[SMD]]-Chip VNH3SP30 gibt es noch die Alternative VNH2SP30. Dieser Chip erlaubt zwar nur Motorspannungen zwischen 6 und 16 Volt, jedoch hat er einen wesentlich geringeren Innenwiderstand und wird deshalb nur etwa halb so warm wie der VNH3SP30. <br />
Aus diesem Grund eignet er sich auch ideal für kleine Doppelmotorsteuerungen.<br />
Natürlich gibt's auch hierfür ein Projekt und eine Bauanleitung, siehe [[RN-VNH2Dualmotor]]<br />
<br />
Das Schöne ist, dass es dieses RN-Projekt jetzt auch als Fertigmodul gibt!<br />
<br />
<br />
[[Bild:rndualmotoransteuerung.jpeg|center]]<br />
<br />
==Endstufen mit I2C-Bus / RS232==<br />
[[Bild:motctrl.png|thumb|Motoransteuerung über RS232, I2C, RC]]Verwendet man eine der oben vorgestellten H-Bridges, so wird immer vorausgesetzt, dass ein PWM-Signal und mehrere Ports zur Ansteuerung bereitstehen. Ist dies nicht der Fall, weil diese vielleicht schon belegt sind, so lassen sich Endstufen durch einen zusätzlichen Microcontroller auch um beliebige Schnittstellen erweitern. Insbesondere über I2C lassen sich dadurch mehrere Motorboards über einen einzigen Bus ansteuern. Ein Beispiel ist der programmierte Controller MOTCTRL, der speziell für diese Aufgabe gedacht ist. Die Grundschaltung sieht man in der rechten Skizze.<br />
<br />
==Und nie vergessen Motoren zu entstören==<br />
<br />
Das Entstören dient dazu, eine Ausbreitung von Funkstörungen durch das sogenannte "Bürstenfeuer" zu verhindern. Und so wird's gemacht:<br />
<br />
<br />
[[Bild:entstoerung.gif|center]]<br />
<br />
Bei Steuerung des Motors per PWM sind die Induktivitäten hilfreich. Sie verhindern das bei den steilen Flanken des PWM Signals große Ströme duch die Kondensatoren fließen. Alternativ zu den 2 Kondensatoren (C2,C3) gegen das Gehäuse kann das Gehäuse auch direkt an Masse angeschlosssen werden. Bei einer PWM Steuerung ist das die bessere Lösung.<br />
<br />
==Siehe auch==<br />
* [[Getriebemotoren]]<br />
* [[RN-VNH2Dualmotor]]<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/motordrehmoment.php Drehmoment Berechnung]<br />
* [http://www.roboternetz.de/motoruebersicht.html Motoren Übersicht]<br />
* [http://www.shop.robotikhardware.de/shop/catalog/index.php?cPath=65 Bauteilesets]<br />
* [http://www.roboternetz.de/robotertutorial.html Roboter-Tutorial]<br />
* [http://www.roboternetz.de Roboternetz Forum]<br />
<br />
[[Category:Robotikeinstieg]]<br />
[[Category:Praxis]]<br />
[[Category:Grundlagen]]<br />
[[Category:Motoren]]<br />
[[Category:Elektronik]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=RC-Empf%C3%A4nger_auswerten&diff=14866RC-Empfänger auswerten2009-04-26T05:46:04Z<p>Holzi: </p>
<hr />
<div>{{Ausbauwunsch|Mehr Grundlagen/ Erklärungen, und Code Beispiele in C}}<br />
<br />
==Vorwort==<br />
Um einen RC-Empfänger mit einem ATmega auszuwerten, bedient man sich am besten des Summensignals. Im [http://www.mikrokopter.de/ucwiki/RC-Empf%C3%A4nger Wiki von Mikrokopter.de] findet sich eine Liste mit getesteten Empfängern und kurzen Anleitungen, wie man an das Signal kommt.<br />
Die Quellcode Beispiele in diesem Artikel funktionieren mit einen Atmel ATmega32 der mit einem 16Mhz Quarz betrieben wird. Werden andere µC's oder andere Quarze verwendet ändern sich natürlich einige Zeilen. Besonders bei Verwendung eines anderen Quarzes müssen die Zeilen "preload für 4ms" auf den entsprechend richtigen Preload geändert werden! Evtl. muss auch der Prescaler angepasst werden.<br />
<br />
Für BASCOM kann man mit folgendem Code die Kanäle 1-6 auslesen (atmega32, 16Mhz Quarz - bei Bedarf anpassen):<br />
==Auslesen mit Timer0==<br />
<pre><br />
$baud = 9600<br />
$crystal = 16000000<br />
$regfile "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 64<br />
Config Timer0 = Timer , Prescale = 256 , Capture Edge = Falling , Noise Cancel = 1<br />
Enable Timer0<br />
On Timer0 Pausedetected<br />
Config Int1 = Falling 'Summensignal an int1 (am Mega32: Port D3), Reaktion auf fallende Flanke<br />
Enable Interrupts<br />
Enable Int1 'einschalten Int1<br />
On Int1 Measure 'springe zum Interrupt von Timer0<br />
Dim Empf(6) As Word<br />
Dim Channel As Byte<br />
<br />
Do 'Main Loop gibt Signale per UART aus<br />
Print Empf(1) ; " CH1"<br />
Print Empf(2) ; " CH2"<br />
Print Empf(3) ; " CH3"<br />
Print Empf(4) ; " CH4"<br />
Print Empf(5) ; " CH5"<br />
Print Empf(6) ; " CH6"<br />
Print " "<br />
Waitms 500<br />
Loop<br />
<br />
Measure: 'Reaktion auf fallende Flanke<br />
Select Case Channel<br />
Case 1 :<br />
Empf(1) = Timer0<br />
Case 2 :<br />
Empf(2) = Timer0<br />
Case 3 :<br />
Empf(3) = Timer0<br />
Case 4:<br />
Empf(4) = Timer0<br />
Case 5:<br />
Empf(5) = Timer0<br />
Case 6:<br />
Empf(6) = Timer0<br />
End Select<br />
Timer0 = 6 'preload für 4ms<br />
Incr Channel<br />
Return<br />
<br />
Pausedetected:<br />
Channel = 0<br />
Return<br />
<br />
End<br />
</pre><br />
<br />
==Auslesen mit Timer1==<br />
Alternativ kann man den Empfänger natürlich auch mit Timer1 auslesen. Hier ist die Auflösung höher:<br />
<pre><br />
$baud = 9600<br />
$crystal = 16000000<br />
$regfile "m32def.dat"<br />
$framesize = 32<br />
$swstack = 32<br />
$hwstack = 64<br />
Config Timer1 = Timer , Prescale = 8 , Capture Edge = Falling , Noise Cancel = 1<br />
Enable Timer1<br />
On Timer1 PauseDetect<br />
Config Int1 = Falling<br />
Enable Interrupts<br />
Enable Int1 <br />
On Int1 Measure<br />
Dim Empf(6) As Word<br />
Dim Channel As Byte<br />
Do<br />
Print Empf(1) ; " CH1"<br />
Print Empf(2) ; " CH2"<br />
Print Empf(3) ; " CH3"<br />
Print Empf(4) ; " CH4"<br />
Print Empf(5) ; " CH5"<br />
Print Empf(6) ; " CH6"<br />
Print " "<br />
Waitms 500<br />
Loop<br />
<br />
Measure:<br />
Select Case Channel<br />
Case 1 :<br />
Empf(1) = Timer1<br />
Case 2 :<br />
Empf(2) = Timer1<br />
Case 3 :<br />
Empf(3) = Timer1<br />
Case 4:<br />
Empf(4) = Timer1<br />
Case 5:<br />
Empf(5) = Timer1<br />
Case 6:<br />
Empf(6) = Timer1<br />
End Select<br />
Timer1 = 57536 'preload für 4ms<br />
Incr Channel<br />
Return<br />
<br />
PauseDetect:<br />
Channel = 0<br />
Return<br />
End<br />
<br />
</pre><br />
<br />
== C-Programmbeispiel (Auslesen mit Timer0) ==<br />
Dieses Beispiel ist für einen ATMega128 mit 14,745600MHz und funktioniert für alle 8 möglichen Kanäle.<br />
<br />
Wichtig ist es den Overflow des Counters zwischen 2ms und 4ms zu setzen, damit der Controller den Anfang des Signals erkennen kann.<br />
Die einzelnen Servosignale sind dann in cSumSig[] zu finden.<br />
<br />
<pre><br />
#ifndef RC_SUM_H<br />
#define RC_SUM_H<br />
<br />
#include <inttypes.h><br />
#include <avr/interrupt.h><br />
<br />
volatile unsigned char cSumSig[8];<br />
volatile uint8_t iCounter=0,iValid=0;<br />
<br />
ISR(TIMER0_OVF_vect) {<br />
iCounter=0; // Bei Overflow den Channel Counter zurücksetzen<br />
iValid=0; // Messung bis zum ersten Puls blockieren<br />
}<br />
<br />
ISR(INT0_vect) {<br />
if(iValid==1) { // Nicht vor dem ersten Puls das zählen beginnen<br />
cSumSig[iCounter] = TCNT0; // Pulslänge im Array speichern<br />
iCounter++; // Counter für nächsten Puls erhöhen<br />
} else {<br />
iValid = 1; // Messung bei erstem Puls freigeben<br />
}<br />
TCNT0 = 0; // Counter zurücksetzen<br />
}<br />
<br />
void RC_SUM_init(void) { <br />
TIMSK |= (1<<TOIE0); // Overflow Interrupt einschalten<br />
TCCR0 |= ((1<<CS00) | (1<<CS02)); // Prescaler 128<br />
TCNT0 = 0; // Overflow zwischen 2,2ms & 3,8ms<br />
EIMSK |= (1<<INT0); // INT0 enable<br />
EICRA |= ((1<<ISC01) | (1<<ISC00)); // Externer Interrupt bei steigender Flanke an Pin INT0<br />
sei(); // Globale Interrupts erlauben<br />
}<br />
#endif<br />
</pre><br />
<br />
== Autoren ==<br />
* [[Benutzer:Willa|Willa]]<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Robotikeinstieg]] <br />
[[Kategorie:Praxis]] <br />
[[Kategorie:Quellcode Bascom]]<br />
<br />
==Siehe auch==<br />
*[[Servos]]<br />
*[[Servoansteuerung]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Transistor&diff=14853Transistor2009-04-21T10:13:08Z<p>Holzi: </p>
<hr />
<div>Ein Transistor ist ein elektronisches Halbleiterbauelement. Dieser wird zum Schalten und Verstärken benutzt. Die Bezeichnung ''Transistor'' ist ein Kurzwort, das sich vom englischen ''Transfer Varistor'' ableitet und den Transistor als bei bipolaren durch Strom bzw. bei FETs durch Spannung steuerbaren Widerstand umschreibt. <br />
<br />
Transistoren werden in zwei Gruppen unterteilt:<br />
* Bipolare Transitoren<br />
* [[Feldeffekttransistor]]en (FETs)<br />
<br />
Bipolare Transistoren werden durch Stromfluss angesteuert. Die Anschlüsse des bipolaren Transistors sind ''Kollektor'', ''Basis'' und ''Emitter''. Ein kleiner Strom auf der Basis-Emitter-Strecke kann dabei einen großen Strom auf der Kollektor-Emitter-Strecke steuern. Es wird unter anderem auch zwischen NPN- und PNP-Transistoren unterschieden.<br />
<br />
Bei FETs werden die Anschlüsse als Gate (engl. Tor, Gatter), Drain (engl. Abfluss), Source (engl. Quelle) bezeichnet. Der Strom auf der Drain-Source-Strecke wird hier durch die Spannung zwischen Gate und Source gesteuert. Die Steuerung mit Gleichspannung erfolgt stromlos. Bei Steuerung mit Wechselspannung wird ein Strom fürs Umladen der Gate-Kapazität benötigt.<br />
<br />
{{Ausbauwunsch|<br />
}}<br />
<br />
== Funktionsprinzip ==<br />
<br />
[[Bild:Ib-Kennlinie, BC547.gif|thumb|Spannungs-Strom-Kennlinie der Basis-Emitter-Strecke]]<br />
Gehen wir zunächst von einem NPN-Transistor aus, dessen Emitter auf Masse liegt. Durch ihn können zwei Ströme fließen: Der Basis-Emitter-Strom (Kurz: I<sub>b</sub>) und der Collector-Emitter-Strom (Kurz: I<sub>c</sub>). Der Basisstrom I<sub>b</sub> ist der Steuerstrom. Die Spannungs-Strom-Kennlinie der Basis-Emitter-Strecke ähnelt einer Diodenkennlinie: Bis ca. 0,6V fließt kaum Strom, danach steigt die Stromstärke schnell an (siehe Grafik). Diese Kennlinie ist auch noch temperaturabhängig, bei höheren Temperaturen kann ein höherer Strom fließen. Wenn nun eine Schwellenspannung (= ab dieser Spannung lässt die Basis Strom fließen, hier gehen wir von Silizium aus; bei Germanium würde die Schwellenspannung schon bei 0,35V sein) von 0,7V an die Basis anlegt wird, würde zuerst nur ein kleiner Strom fließen. Mit der Zeit würde sich der Transistor erwärmen, wodurch ein höherer Strom fließen kann. Dadurch wird jedoch auch wieder die Wärmeabgabe größer, ein Teufelskreis entsteht und irgendwann brennt der Transistor durch. Um das zu verhindern, benutzt man, je nachdem wie groß die Last ist, die am Transistor angeschlossen ist, Basis-Vorwiderstände in der Größenordnung von 220 Ohm bis 100 kOhm. Diese werden zwischen die Ansteuerung und die Basis des Transistors geschaltet und begrenzen den Strom, der durch die Basis fließen kann.<br />
[[Bild:Ic-Kennlinie, BC547.gif|thumb|Spannungs-Strom-Kennlinine der Collector-Emitter-Strecke]]<br />
Die Collector-Emitter-Strecke des Transistors hat eine Kennlinie, die zuerst in etwa linear ansteigt und dann bei einer bestimmten Stromstärke in eine fast waagrechte Gerade übergeht (siehe Grafik).<br />
Bei welcher Stromstärke die Gerade abknickt, hängt von dem Strom ab, der durch die Basis-Emitter-Strecke fließt. Je höher dieser ist, desto später knickt die Gerade ab, und desto größere Lasten kann man schalten. In einem begrenzten Bereich ändert sich der Basisstrom linear zum Collectorstrom. Die Basis-Emitter-Stromstärken betragen in der Grafik von unten nach oben 0mA, 5mA, 10mA, 15mA und 20mA.<br />
Das Verhältnis aus dem Strom, der auf der Collector-Emitter-Strecke fließen kann, und dem Strom, der dazu als Steuerstrom benötigt wird, nennt man Verstärkungsfaktor. Der Verstärkungsfaktor, der bei einem Transistor angegeben ist, ist jedoch eine rein theoretische Größe. Die Werte, die im Datenblatt angegeben sind, beziehen sich meistens auf eine Collector-Emitter-Spannung von 5V, bei höheren Lastströmen sinkt der Verstärkungsfaktor weiter. Für Schaltanwendungen sollte man daher von etwa der halben Stromverstärkung ausgehen, damit die Emitter-Collector-Spannung sicher klein bleibt. <br />
Wie groß man I<sub>b</sub> wählen muss, probiert man in einer Schaltungssimulation aus, oder berechnet es näherungsweise.<br><br><br />
Bei einem PNP-Transistor sind im Grunde alle Spannungen umgedreht. Der Emitter zeigt nicht zur Masse, sondern zur positiven Versorgung (Vcc, z.B. 5 V). Die Basis muss auf einer niedrigeren Spannung liegen, beispielsweise 4,3V, damit der Transistor durchschaltet. Der Strom fließt aber weiterhin von + nach - (technische Stromrichtung angenommen)<br />
<br />
== Schaltsymbol und Anschlussbelegung ==<br />
[[Bild:Transistor.JPG|thumb|300px|{{FarbigerRahmen|<br />
'''Warnung:'''<br />
Es gibt ebenso Transistoren im TO-92 Gehäuse, deren Basis an der Seite liegt. <br />
Bevor du einen Transistor verwendest, solltest du auf jeden Falls sein Datenblatt gelesen haben<br />
bzw. dir sicher sein, wo sich welcher Anschluss befindet!<br />
}}]]<br />
<br />
[[Bild:Schaltsymbol NPN.png|thumb|250px|left|Schaltsymbol npn-Transistor. Der Pfeil zeigt von der Basis (p) zum Emitter (n)]] <br />
<br style="clear:left"/><br />
[[Bild:Schaltsymbol PNP.png|thumb|250px|left|Schaltsymbol pnp-Transistor. Der Pfeil zeigt vom Emitter (p) zur Basis (n)]] <br />
<br />
<br />
<br style="clear:both"/><br />
<br />
== Grundschaltungen ( NPN-Transitor) ==<br />
=== Emitterschaltung ===<br />
[[Bild:Emitterschaltung.gif|thumb|Grundschaltung der Emitterschaltung]]<br />
(1) Die Emitterschaltung besteht hauptsächlich aus dem Transistor, dem Kollektorwiderstand und dem Basis-Vorwiderstand. Ist an der Basis eine Spannung von unter 0,6V anlegt, ist der Transistor nicht leitend, also hochomig. Weil der hochomige Transistor einen höheren Widerstand als der Kollektorwiderstand aufweist fällt bei ihm die größte Spannung ab. Der Ausgang der Schaltung wird durch den Widerstand auf die positive Versorgungsspannung (Vcc) "gezogen". <br><br />
<br><br />
(2) Wenn man nun eine Spannung am Eingang anlegt, die größer als ca. 0,6V ist, fließt ein Strom durch die Basis des Transistors. Der Transistor wird leitend und zieht den Ausgang der Schaltung auf 0V (GND).<br><br />
Durch die Offsetspannung von 0,6V ist diese Schaltung nicht zum linearen Verstärken von Signalen geeignet. Die Schaltung kann nur als Schalter genutzt werden, sei es um die Flanken auf einem Signal zu verbessern (steiler zu machen) oder um Lasten zu schalten.<br><br />
<br><br />
In ersterem Fall muss man beachten, dass die Emitterschaltung das Signal invertiert, d.h. bei 0V am Eingang liegen 5V am Ausgang an und umgekehrt.<br />
In letzterem Fall wird die Last (beispielsweise eine Glühbirne) statt Rc angeschlossen. Sobald man nun eine Spannung an die Basis anlegt, wird der Transistor leitend und es kann ein Strom durch die Last fließen, die Lampe leuchtet.<br />
Bei großen Lasten benötigt der Transistor einen entsprechend hohen Basisstrom, der durch den Basis-Vorwiderstand eingestellt wird.<br />
<br />
==== Erweiterte Emitterschaltung ====<br />
[[Bild:Emitterschaltung, erweitert.gif|thumb|Emitterschaltung zum linearen Verstärken von Wechselspannungen]]<br />
Wenn man die Emitterschaltung zum linearen Verstärken eines Signals nutzen will, muss man sie noch ein wenig erweitern. An die Basis wird zusätzlich ein Pullup-Widerstand angeschlossen. Dieser sorgt dafür, dass der Transistor "vorgespannt" wird. Der Widerstand wird dabei gerade so groß gewählt, dass der Ausgang möglichst genau zwischen GND und der Versorgungsspannung liegt.<br><br />
Hinter den Ausgang und vor den Eingang müssen zusätzlich so genannte Koppelkondensatoren geschaltet werden. Diese sorgen am Eingang dafür, dass die angelegte Eingangsspannung die Vorspannung nicht zerstört und am Ausgang dafür, dass kein Gleichstrom durch die Last fließen kann. Dies ist vor allem bei Lautsprechern wichtig.<br><br />
Die Emitterschaltung kann in dieser Form sowohl negative als auch positive Wechselspannungen verstärken. Für Gleichspannungen ist sie nicht mehr geeignet, da die Koppelkondensatoren diesen sperren.<br><br />
Wenn man eine Wechselspannung anlegt, fließt zusätzlich zu dem Vorspannstrom ein Eingangsstrom, der den Transistor entweder leitender (positive Halbwelle) oder weniger leitend (negative Halbwelle) macht.<br><br />
In ersterem Fall wird der Kollektor des Transistors durch selbigen auf eine negativere Spannung gezogen. Durch den Koppelkondensator am Ausgang fließt dann ein Strom in Richtung des Kollektors, bis der Kondensator durch diesen weit genug aufgeladen ist.<br><br />
im anderen Fall wird der Transistor weniger leitend, der Kollektor des Transistors wird dann durch den Widerstand Rc auf eine positivere Spannung gezogen. Folglich fließt durch den Koppelkondensator am Ausgang ein Strom in Richtung der Last, allerdings auch hier nur solange der Kondensator nicht vollständig geladen ist.<br />
<br />
=== Kollektorschaltung ===<br />
[[Bild:Kollektorschaltung.gif|thumb|Kollektorschaltung mit NPN-Transistor]]<br />
Für eine Kollektorschaltung werden zunächst nur ein Transistor und ein Widerstand benötigt.<br><br />
Ohne Eingangsspannung leitet der Transistor nicht, der Ausgang liegt also auf 0V.<br><br />
Sobald man am Eingang eine Spannung anlegt, wird der Transistor jedoch leitend, die Ausgangsspannung wird größer. Gleichzeitig wird dadurch die Basis-Emitterspannung kleiner. Der Ausgang erreicht also maximal etwa die Eingangsspannung abzüglich der 0,7 Volt, die benötigt werden, damit auf der Basis-Emitterstrecke ein Strom fließen kann. Die Spannungsverstärkung ist folglich etwas kleiner als 1. Im Gegenzug besitzt die Kollektorschaltung eine sehr hohe Stromverstärkung und dadurch auch einen sehr hohen Eingangswiderstand. Die Kollektorschaltung wird auch als Emitterfolger bezeichnet.<br><br />
Bei dieser Schaltung kann auf den Basis-Vorwiderstand verzichtet werden, solange man am Eingang keine Spannung anlegt, die größer ist als die Versorgungsspannung. Der Strom durch die Basis reguliert sich durch die variable Emitterspannung selbst. Allerdings kann ein Basis-Vorwiderstand auch als Kurzschlussschutz dienen, da bei einem begrenzten Basisstrom auch der Kollektor-Emitterstrom begrenzt ist.<br />
<br />
=== Basisschaltung ===<br />
[[Bild:Pegelwandler.png|thumb|Pegelwandler für 3 V auf 5 V Logicpegel, mit NPN Transistor in Basisschaltung.]]<br />
In der Basisschaltung wird die Basis fest auf eine mittlere Spannung gelegt. Der Strom am Emitter dient als Eingang, der Strom am Kollektor als Ausgang. Wenn man den kleinen Basisstrom vernachlässigt, sind der Emitter- und Kollektorstrom gleich groß. Wenn der Widerstand (bzw. die Impedanz) an der Emitterseite niedriger als an der Kollektorseite ist, ergibt sich eine Spannungsverstärkung. Die Basisschaltung wird hauptsächlich in HF-Schaltungen benutzt. <br />
<br />
Eine weitere Anwedung sind Pegelwandler. Die Schaltung im Bild rechts dient dazu, ein Digitalsignal von einem IC mit 2-3 V Versorgung auf 5 V zu Verstärken. Wenn am Eingang mehr als etwa 1 V anliegen, sperrt der Transistor, und am Ausgang liegt die Spannung über den 1 K Widerstand. Wenn der Eingang auf GND Potential ist, ist der Transistor durchgeschaltet und der Ausgang liegt fast auf GND Potential. Der Basisstrom wird durch den 22 K Widerstand auf rund 0,2 mA begrenzt. Die Schaltung ist keine reine Basisschaltung, denn die Spannung an der Baisis ändert sich hier ein wenig.<br />
<br />
=== Darlingtonschaltung ===<br />
[[Bild:Darlington.png|thumb|Darlingtonschaltung (NPN)]]<br />
Wenn die Stromverstärkung eines einzelnen Transistors nicht ausreicht, können zwei Transistoren so zusammengeschaltet werden, dass der Emitter des ersten Transistors an die Basis des zweiten Transistors geht. Die Collectoren sind miteinander verbunden. Diese Schaltung verhält sich dann ganz ähnlich wie ein Transistor mit einer Stromverstärkung, die dem Produkt der beiden Stromverstärkungen entspricht. In einem Gehäuse zusammengefasst bezeichnet man diese Schaltung als Darlingtontransistor. Der im Bild gezeigte Widerstand kann auch weggelassen werden. Er macht die Schaltung schneller und reduziert den Leckstrom.<br />
<br />
=== Verstärkung mit Gegenkopplung ===<br />
==== Spannungsgegenkopplung ====<br />
<br />
[[Bild:Spannungsgegenkopplung.png|thumb|Verstärker mit Spannungsgegenkopplung]]<br />
<br />
Die Verstärkung mit der Emitterschaltung ist von den Eigenschaften (besonders Verstärkungsfaktor) des verwendeten Transistors abhängig und damit auch temperaturabhängig. Außerdem ist die Verstärkung nicht besonders linear.<br />
Die Schaltung im Bild zeigt einen Weg eine stabilere Verstärkung zu erzeugen. Über den Widerstand R2 wirkt die Ausgangsspannung der Eingangsspannung entgegen. <br />
Diese Schaltungprinzip wird daher Spannungsgegenkopplung genannt.<br />
Die Verstärkung ist in diesem Fall auf -R2/R3 = -5 fach festgelegt. Damit die Gegenkopplung wirken kann, muss die Verstärkung ohne die Gegenkopplung wesentlich höher sein, als sie durch die Widerstände eingestellt wird. Durch die Gegenkopplung reduziert sich die Verstärkung zugunsten einer besseren Linearität und Stabilität. <br />
<br />
<br />
==== Stromgegenkopplung ====<br />
<br />
[[Bild:Stromgegenkopplung.png|thumb|Verstärker mit Stromgegenkopplung]]<br />
<br />
Eine andere Form der Gegenkopplung zeigt das Bild rechts. Hier ist die Rückkopplung nicht so klar zu sehen, denn die Rückkopplung wirkt nicht auf die Basis, sondern auf den Emitter. Der Kollektorstrom hängt vom Basistrom ab und damit von der Spannung zwischen Basis und Emitter. Eine höhere Spannung am Emitter ist daher gleichbedeutend mit einer niedrigeren Spannung an der Basis und weniger Strom. Durch Strom durch dem Kollektor fleißt auch durch den Widerstand am Emitter, erhöht dort die Spannung und wirkt so einem höheren Strom entgegen. Man nennt diese Schaltung daher auch Stromgegenkopplung. Auch hier reduziert sich die Verstärkung auf etwa -R2/R3.<br />
<br />
=== Logische Interpretation der Schaltungen ===<br />
====Die NOT-Verknüpfung====<br />
<br />
[[Bild:NOT Gatter.JPG]]<br />
<br />
Diese einfache Schaltung, bestehend aus einem NPN-Transistor und zwei Widerständen, invertiert das Eingangssignal, sodass aus beispielsweise +5V (oder logisch 1) 0V (oder logisch 0) erzeugt werden.<br />
Die daraus resultierende Wertetabelle sieht folgendermaßen aus:<br />
<br />
<div align = "center"><br />
{| {{Blauetabelle}}<br />
| '''Eingang'''<br />
| '''Ausgang'''<br />
|-<br />
| 0V<br />
| +5V<br />
|-<br />
| +5V<br />
| 0V<br />
|}<br />
</div><br />
Wenn also an der Transistorbasis +5V angelegt werden (+0,7V reichen meistens auch schon), dann schaltet der Transistor durch und am Ausgang liegen 0V an. Der Strom, der nun durch den Transistor fließt, wird durch den Widerstand R<sub>2</sub> begrenzt. Wird dieser Widerstand weggelassen, dann wird durch den entstehenden Kurzschluss der Transistor unweigerlich zerstört.<br />
Legt man nun am Eingang 0V an, so sperrt der Transistor und am Ausgang liegen +5V an. <br />
<br />
<br />
Der Basisstrom wird durch den Widerstand R<sub>1</sub> bestimmt. Ein kleiner Widerstand beschleunigt die Schaltgeschwindigkeit des Transistors, ein großer ermöglicht die Ansteuerung auch mit kleinen Strömen.<br />
<br />
====Die NAND Verknüpfung====<br />
<br />
[[Bild:NAND_Gatter.jpg]]<br />
<br />
Die NAND ('''N'''ot'''AND''', d.h. die invertierte Form einer AND Verknüpfung) Verknüpfung besteht aus zwei Transistoren und damit auch zwei Eingängen. Es gibt auch NAND Verknüpfungen mit mehr Transistoren und folglich auch mehr Eingängen, diese sind im Aufbau aber sehr ähnlich zu der vorgestellten Grund-NAND Verknüpfung.<br />
Schauen wir uns zunächst die Wertetabelle an:<br />
<div align = "center"><br />
{| {{Blauetabelle}}<br />
| '''Eingang 1 (E1)'''<br />
| '''Eingang 2 (E2)'''<br />
| '''Ausgang (A1)'''<br />
|-<br />
| 0V<br />
| 0V<br />
| +5V<br />
|-<br />
| +5V<br />
| 0V<br />
| +5V<br />
|-<br />
| 0V<br />
| +5V<br />
| +5V<br />
|-<br />
| +5V<br />
| +5V<br />
| 0V<br />
|}<br />
</div><br />
<br />
Wie kommt es nun zu dieser Werte- oder auch Wahrheitstabelle?<br />
<br />
Wenn an den beiden Eingängen 0V anliegen, dann schaltet keiner der beiden Transistoren durch und der Ausgang ist über den Widerstand R<sub>3</sub> mit +5V verbunden.<br />
Wechselt nun einer der beiden Eingänge auf 1, dann schaltet auch nur einer der beiden Transistoren durch und am Ausgang liegen immer noch +5V an. Werden nun aber beide Eingänge mit +5V verbunden, dann schalten beide Transistoren durch und der Ausgang ist leitend mit Masse verbunden.<br />
<br />
Die Widerstände (R<sub>1</sub>, R<sub>2</sub>, R<sub>3</sub>) haben die gleiche Funktion wie auch in der NOT Verknüpfung.<br />
<br />
== Transistor-Kennwerte ==<br />
Die Transistorkennwerte sind grundsätzlich in Grenzdaten und Kenndaten unterteilt. Grenzwerte dürfen auf keinen Fall überschritten werden, da eine Zerstörung des Transistors möglich ist. Eigenschaften eines Transistors werden als Kenndaten angegeben, die das Verhalten in bestimmten Arbeitspunkten kennzeichnen.<br />
<br />
==Grenzwerte für Sperrschichttemperatur==<br />
Durch die Verlustleistung bei Dauerbetrieb entsteht in der Sperrschicht Wärme, durch die sich die Sperrschichttemperatur erhöht. Die Sperrschichttemperatur '''T<sub>J</sub> ''' , darf bestimmte Werte nicht überschreiten, da sich sonst die Eigenschaften des Transistors stark verändern würden (z.B. sehr hoher Leckstrom), was oft eine Zerstörung zur Folge hat. Die maximale Temperatur hängt vom Halbleitermaterial ab.<br />
<br />
'''T<sub>J</sub> ''' : 90°C Germaniumtransistoren<br />
<br />
'''T<sub>J</sub> ''' : 150 - 200°C Siliziumtransistoren<br />
<br />
==Zulässiger Arbeitsbereich==<br />
In Transistorschaltungen dürfen bestimmte Grenzwerte nicht überschritten werden. Der zulässige Arbeitsbereich einer Transistorschaltung wird somit durch den Kollektorstrom '''I<sub>c</sub> ''', durch die Kollektor - Emitterspannung '''U<sub>CE</sub> ''' und durch die Verlustleistung '''P<sub>tot</sub> ''' begrenzt. Wird der Transistor außerhalb des erlaubten Arbeitsbereiches betrieben wird der Transistor zerstört. <br />
Die zulässige Verlustleistung wird bei kleinen Transistoren oft für 25°C Umgebungstemperatur angegeben. Bei Leistungstransistoren wird oft 25°C Gehäusetemperatur vorausgesetzt. Bei höheren Temperaturen oder schlechterer Kühlung, was fast immer der Fall ist, reduziert sich die zulässige Verlustleistung. In den Datenblättern findet man dazu Zahlenwerte und teilweise Diagramme zur zulässigen Verlustleistung als Funktion der Umgebungstemperatur. Je nach Wärmewiderstand '''R<sub>Th</sub> ''' eines ggf. vorhandenen Kühlkörpers ergeben sich unterschiedliche Kurven.<br />
<br />
<br />
==Kenndaten==<br />
Von den Kenndaten ist im wesentlichen der Stromverstärkungsfaktor ('''h<sub>FE</sub> ''') wichtig. Für Schaltanwendungen interessiert noch die Kollektor-Emitter-Sättigungsspannung. Die anderen Kenndaten sind im wesentlichen für fortgeschrittene Schaltungen wichtig.<br />
<br />
<br />
''Autor: ZwieBack - Wiki Konvertierung Frank''<br />
<br />
==Siehe auch==<br />
* [[Feldeffekttransistor|FET]]<br />
<br />
==Weblinks==<br />
* [http://www.nano.physik.uni-muenchen.de/elektronik/nav/k5t2.html Grundlagen Transistorschaltungen] <br />
* [http://www.mikrocontroller.net/articles/Transistor Mikrocontroller.net/Transistor]<br />
* [http://de.wikipedia.org/wiki/Transistor Wikipedia/Transistor]<br />
<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Fotodiode&diff=14852Fotodiode2009-04-21T10:09:41Z<p>Holzi: </p>
<hr />
<div>[[Bild:Fotodiode-Schaltbild.jpg|thumb|Schaltzeichen einer Fotodiode]]<br />
Fotodioden sind eine Art von Dioden, die auf einfallendes Licht reagieren. Der pn-Übergang ist bei Fotodioden optisch zugänglich. <br />
<br />
== Aufbau und Funktion ==<br />
[[Bild:Fotodiode-Struktur.jpg|thumb|Innerer Aufbau einer Fotodiode]]<br />
Meist befindet sich zwischen den beiden dotierten Halbleiterschichten (p und n) ein undotierter Bereich (PIN-Dioden). Im Bereich des Überganges werden bei einfallendem Licht durch den inneren lichtelektrischen Effekt freie Elektronen aus der atomaren Struktur gelöst, die einen Fotostrom erzeugen.<br />
<br />
Bei kleinen Spannungen oder mit Spannung in Sperrichtung ist der Strom über einen sehr großen Bereich proprotional zur Intensität und relativ unabhängig von der Spannung.<br />
<br />
Bei Betrieb mit nur einem Lastwiderstand erzeugt die Fotodiode, wie eine Solarzelle, elektrische Energie. Die Leerlaufspannung ist dabei annähernd proportional zum Logaritmus der Intensität.<br />
<br />
Die langwellige Grenze der spektralen Empfindlichkeit von Fotodioden hängt vom verwendeten Halbleitermaterial ab. Bei Silizium liegt die Grenze bei ca. 1050 nm, die höchste spektrale Empfindlichkeit je nach Qualität bei ca. 800-900 nm. Bei Germanium liegt die Grenze ca. bei 1.900 nm, also im Infrarot-Bereich. Die kurzwellige Grenze hängt vom Fenstermaterial und der Oberfläche des Halbleiters ab, typisch bei etwa 400 nm. Für Infrarot Anwendungen gibt es Fotodioden mit integrietem Filter, die dann nur auf Infrarotlicht zwischen ca. 800 nm und ca. 1000 nm reagieren.<br />
Daneben gibt es auch Fotodioden speziell für den sichtbaren Bereich die das IR Licht unterdrücken (z.B. BPW21).<br />
<br />
Die typische Empfindlichkeit liegt bei ca. 0,5 A/W bei 800 nm. In der Regel hat man also kleine Ströme im µA Bereich und darunter.<br />
<br />
== Anwendungsbeispiele ==<br />
Im Gegensatz zum Fotowiderstand haben Fotodioden eine geringe Trägheit und können auf Signale im Nano- und Mikrosekunden-Bereich reagieren. Die Schaltgeschwindigkeit hängt dabei von der Sperrspannung ab, je höher diese ist, desto kürzer werden die Schaltzeiten (bei Erhöhung der Sperrspannung wird die Kapazität der Sperrschicht geringer).<br />
<br />
<br />
[[Bild:FotodiodenVerst.png|thumb|Einfacher Verstärker für Fotodiode]]<br />
Das Bild zeigt eine einfache Verstärkerschaltung, um eine Fotodiode an einen µC anzuschließen. Schaltzeiten bis etwa 20 µs sind so möglich.<br />
<br />
Wegen der sehr guten Linearität werden für genaue Messungen der Lichtintensität in der Regel Fotodioden benutzt. Der Strom wird dabei oft mit einem als Transimpedanzverstärker geschaltetem Operationsverstärker in eine Spannung umgewandelt.<br />
<br />
Um sich das relativ starke IR Signal z.B. einer Fernbedienung anzusehen, genügt es parallel zu einer Fotodiode (bevorzugt mit IR Filter) eine Widerstand von etwa 1 KOhm zu schalten, und die Spannung auf dem Oszilloskop darzustellen.<br />
<br />
''t.b.c.''<br />
<br />
== Anmerkungen ==<br />
{{Ausbauwunsch|Ein erster Anfang: Ausbau - Gliederung in Kapitel - Bilder einfügen!}}<br />
<br />
== Weblinks ==<br />
<br />
<br />
== Autor ==<br />
--[[Benutzer:Williwilli|Williwilli]] 17:26, 17. Okt 2008 (CEST)<br\><br />
--[[Benutzer:Besserwessi|Besserwessi]]<br />
<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Sensoren]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Fototransistor&diff=14851Fototransistor2009-04-21T10:07:56Z<p>Holzi: </p>
<hr />
<div>[[Bild:Fototransistor-Schaltbild.jpg|thumb|Schaltzeichen eines Fototransistors]]<br />
Fototransistoren sind eine Art von Transistoren, die auf einfallendes Licht reagieren. Der Basis-Anschluß ist bei Fototransistoren optisch zugänglich. <br />
<br />
<br />
== Aufbau und Funktion ==<br />
[[Bild:Fototransistor-Struktur.jpg|thumb|Innerer Aufbau eines Fototransistors]]<br />
Wie die [[Fotodiode]], arbeitet auch der Fototransistor mit einer Halbleiterstrecke, die bei Lichteinfall ihre Eigenschaften ändert. Es handelt sich dabei um die Basis-Kollektor-Strecke, die als Fotodiode fungiert und den Basisstrom für den Fototransistor erzeugt. Der Fototransistor wird somit nur über das einfallende Licht gesteuert. Fällt Licht auf einen Fototransistor, dann erhöht sich der Strom, der zwischen Kollektor und Emitter fließt.<br />
<br />
Die spektrale Empfindlichkeit von Fototransistoren ist mit der von Fotodioden vergleichbar, d.h. Fototransistoren aus Silizium haben ihr Maximum bei etwa 800 nm, solche aus Germanium bei etwa 1.500 nm. Beide Wellenlängen liegen somit im Infrarotbereich.<br />
<br />
Fototransistoren haben ein lichtdurchlässiges Gehäuse, bei dem das Licht auf die Basis-Kollektor-Sperrschicht fallen kann. Die Empfindlichkeit ist jedoch auch vom verwendeten Material das Transistorgehäuse abhängig, ein transparentes Gehäuse hat eine breitere Empfindlichkeitskurve als ein schwarzes Epoxy-Gehäuse (IR Filter). <br />
<br />
Der Vorteil des Fototransistors gegenüber der Fotodiode ist die wesentlich höhere Empfindlichkeit, denn der Fotostrom wird wie bei einem normaler bipolarer Transistor um etwa den Faktor 200 verstärkt. <br />
Allerdings ist die Trägheit von Fototransistoren höher als die von Fotodioden: Die Grenzfrequenz eines Fototransistors liegt mit etwa 250 kHz wesentlich niedriger, bei Foto-Darlington-Transistoren liegt diese sogar nur bei ca. 30 kHz. Bei der typischen eher hochohmigen Beschaltung liegt die Grenzfrequenz sogar noch deulich niedriger.<br />
<br />
== Anwendungsbeispiele ==<br />
<br />
Bei manchen Fototransistoren ist der Basisanschluss trotzdem herausgeführt. Dadurch ist eine Arbeitspunktstabilisierung oder schnellers Schaltverhalten möglich.<br />
<br />
Die Empfängerseite der meisten [[Optokoppler]] ist ein Fototransistor.<br />
<br />
Für die Auswertung als analoges Signal wird der Fototransistor gegen VCC geschaltet und ein Arbeitswiderstand (z.B. 10 KOhm) nach GND. Die Spannung am Widerstand ist dann näherungsweise proportional zur Helligkeit. Die Linearität ist besser als bei einem [[LDR]], aber schlechter als bei einer [[Fotodiode]].<br />
<br />
''t.b.c.''<br />
<br />
== Anmerkungen ==<br />
{{Ausbauwunsch|Ausbau - Bilder einfügen!}}<br />
<br />
<br />
== Weblinks ==<br />
<br />
<br />
== Autor ==<br />
--[[Benutzer:Williwilli|Williwilli]] 20:26, 17. Okt 2008 (CEST)<br />
<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Sensoren]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Portexpander_am_AVR&diff=14787Portexpander am AVR2009-04-06T16:33:59Z<p>Holzi: </p>
<hr />
<div>Bietet ein Controller nicht genügend I/O-Leitungen, dann kann ein Portexpander verwendet werden. Dadurch stehen zusätzliche Ports zur Verfügung. Neben [[I2C Chip-Übersicht|Portexpandern der I&sup2;C-Klasse]] oder [[SPI]]-Klasse bietet sich an, 8-Bit-Schieberegister zu kaskadieren und als Expander zu verwenden. Das ist oft ausreichend, weil mehr Ausgänge gebraucht werden als Eingänge. Dabei werden Schieberegister mit Ausgangs-Latch verwendet, d.h. die Daten werden erst dann an die Ausgänge geschaltet, wenn sie an Ort und Stelle sind. <br />
<br />
Falls Eingänge benötigt werden, können auch Schieberegister mit Input-Latches ankaskadiert werden, welche die Eingänge von parallel nach seriell umsetzen (in diesem Artikel nicht näher beschrieben).<br />
<br />
= Pro & Contra =<br />
<br />
;Vorteile:<br />
* schnell<br />
* preiswert<br />
* einfach anzusteuern (auch ohne Hardware-Unterstützung, deutlich einfacher als I&sup2;C)<br />
* Ansteuerung ohne Interrupt-Programmierung<br />
* modular aufgebaut und erweiterbar<br />
* '''alle''' Ports können '''gleichzeitig''' geschaltet werden, auch 100 Stück<br />
* SPI-Interface und [[In System Programming|ISP-Pins]] (die oft ungenutzt bleiben) können verwendet werden<br />
* Bus hat nur 3 Leitungen, dadurch kein kompliziertes Layout mit vielen Leitungen<br />
* Hardware bzw. Code der Version ohne Hardware-Unterstützung ist auch auf anderen Controllertypen als AVR verwendbar (sofern die Ausgangspegel passen).<br />
* Test der Schaltung direkt am PC möglich, falls man Zugriff auf den Parallelport oder [[RS232]] ('''Pegelanpassung erforderlich!''' z.B MAX232, Widerstände & [[Diode#Zenerdiode|Zenerdiode]]) hat. In diesem Fall verwendet man die Software PC-seitig und setzt/resettet die 3 Portleitungen, an die man die Expander angeschlossen hat.<br />
* Indem die Enable-Leitung des Latches per PWM angesteuert wird, können die Ausgänge einfach und effizient gedimmt werden. Das ist interessant, wenn die Portexpander [[LED]]s treiben.<br />
<br />
;Nachteile<br />
* bei dieser Version nur Ausgabe möglich<br />
* soll ein Ausgangs-Port geändert werden, müssen ''alle'' Daten neu gesendet werden <br />
* bei der Variante mit SPI-Hardware liegt MISO brach bzw ist nicht so einfach nutzbar zu machen<br />
* Lange Leitungen sind problematisch, weil die CLK Leitung empfindlich auf Überschwinger reagiert.<br />
<br />
=Resourcen=<br />
<br />
<center><br />
{| {{Blauetabelle}}<br />
|+ '''Tabelle: Resourcen-Verbrauch mit'''&nbsp;''N''&nbsp;'''ICs'''<br />
|- {{Hintergrund1}}<br />
!| Resource || ohne SPI || mit SPI<br />
|-<br />
| AVR-Peripherie || 3 I/O-Ports || SPI + 1 I/O-Port<br />
|- <br />
| Expander 74*595, CD4094, ... || colspan="2" align="center"| ''N''<br />
|- <br />
| maximaler Datendurchsatz<br/> in kByte pro Sekunde und MHz <br />
| 10 || 37<br />
|}<br />
</center><br />
<br />
Mit einer CPU-Frequenz von 16MHz hat man also mit der Hardware-Variante einen maximalen Durchsatz von ca. 590 kByte/Sekunde, und 160kByte/Sekunde mit der reinen Software-Variante.<br />
<br />
'''Kleinkram:'''<br />
* evtl. Pullup/Pulldown-Widerstand: 20k&Omega;<br />
* Widerstände zum Entkoppeln vom ISP: einige k&Omega;<br />
* evtl. Kondensatoren von 100pF zum Entstören der Dateinleitungen<br />
* Strom für die Versorgung im Bereich von µA bis wenige mA (je nach Expander-Typ, Anzahl und Frequenz)<br />
<br />
=Schaltplan=<br />
<br />
<center><br />
{| {{Blauetabelle}}<br />
|+ '''Anschlussplan'''<br />
| [[Bild:Portexpander_74595_an_AVR.png]]<br />
|}<br />
</center><br />
;Das umstrichelte Modul: kann einfach so oft nach rechts wiederholt werden, bis es soviele Ausgänge hat, wie gewünscht. Die Bits wandern über Pin&nbsp;14 (SER) in den Expander. Acht Takte später erscheint das Bit wieder an Pin&nbsp;9 (QH*) und damit am SER-Eingang des folgenden Expanders.<br />
;R1: ist ein Pullup-Widerstand, der während des ISP-Programmierens dafür sorgt, daß RCK nicht floatet, denn während der Programmierung sind die AVR I/O-Leitungen hochohmig. Dadurch bleiben die Ausgänge der Expander stabil (MOSI und SCK wackeln natürlich beim Programmierern).<br />
;R2, R3: entkoppeln den ISP-Adapter. Ansonsten stören sie nicht weiter, denn beim Proggen muss praktisch kein Strom fliessen &ndash; abgesehen vom minimalen Leckstrom der Ports und Füllen der Portkapazität von ein paar pF.<br />
; Eingang G (Pin13): ist hier auf LOW verdrahtet. Falls gewünscht, kann er verwendet werden, um die Ausgänge der Expander hochohmig zu schalten (high-Z). Dann wird natürlich einen weiteren µC-Port benötigt, um das zu tun. Falls an den Expandern [[LED]]s zum Einsatz kommen sollen, kann G auch mit einem [[PWM]]-Ausgang des µC verdrahtet werden, um die Anzeige dimmen zu können. Im Falle eines PWM-Betriebs ist darauf zu achten, daß durch das gleichzeitige Schalten vieler Ausgänge/Lasten die Betriebsspannung "sauber" bleibt, indem man etwa auf ausreichend große Abblock-Kondensatoren an den Expandern achtet oder andere Maßnahmen zur hinreichenden Stabilisierung der Versorgungsspannung ergreift.<br />
<br />
=Ports=<br />
Ohne Nutzung der SPI-Hardware gibt es die freie Auswahl, welche Ports verwendet werden sollen. Natürlich ist auch die Verwendung der SPI/ISP-Ports in jeder beliebigen Anordnung möglich und das Signal "SCK" muss nicht an Port "SCK" angeschlossen sein. Einzig auf das Signal '''RCK''' sollte man achten, denn falls es zugleich durch den ISP verwendet wird, flattern beim Programmieren möglicherweise die Expander-Ausgänge.<br />
<br />
Bei der Hardware-Version ist man auf die SPI-Pins <br />
'''MOSI''' (Master Out, Slave IN) und<br />
'''SCK''' (SPI Clock)<br />
festgelegt, mit Ausnahme von '''RCK'''. Das kann irgendein Port sein (ausser '''MISO''', das bei aktiviertem SPI immer Input ist). Im Beispiel ist '''RCK''' an '''SS''' (SPI Slave Select) angeschlossen. <br />
{{FarbigerRahmen |<br />
Falls '''SS''' nicht in dieser Weise verwendet wird, muss auf jeden Fall dafür gesorgt werden, daß '''SS''' ''entweder'' auf OUT steht, oder ''nie'' auf LOW geht, da sonst SPI in den Slave-Modus schaltet!<br />
}}<br />
<br />
=Signalfolge=<br />
[[Bild:Signalfolge-Portexpander.png|center]]<br />
Nachdem das auszugebende Bit an SER/MOSI ausgegeben wurde, wird es mit einem low-Strobe an SCK ins Schieberegister übernommen und alle Bits wandern um eine Position weiter. Nachdem so alle Bits ausgegeben wurden und an ihrer Position sind, werden die Bits durch ein Strobe an RCK an die Ausgänge gelegt und bleiben dort, bis sie wieder überschrieben werden.<br />
<br />
=C-Code=<br />
Der folgende C-Code ist Pseudocode, was Setzen der Ports angeht. Die entsprechenden Befehle sind durch die richtigen C-Befehle für diese Ports zu ersetzen.<br />
;MAKE_OUT (X): Schaltet X als Ausgang (DDR-Register)<br />
;SET (X): Setzt Ausgang X auf HIGH (PORT-Register)<br />
;CLR (X): Setzt Ausgang X auf LOW (PORT-Register)<br />
<br />
<center><br />
{| {{Blauetabelle}}<br />
|+ '''Tabelle: Resourcen-Verbrauch mit'''&nbsp;''N''&nbsp;'''ICs'''<br />
|- {{Hintergrund1}}<br />
!| Resource || ohne SPI || mit SPI<br />
|-<br />
| Interrupts || colspan="2" align="center"| keine<br />
|- <br />
| Flash (Bytes mit <tt>-Os</tt>) || 52 || 44<br />
|- <br />
| SRAM (statisch) || colspan="2" align="center"| ''N''<br />
|- <br />
| SRAM (Stack) || colspan="2" align="center"| 2<br />
|-<br />
| Laufzeit <tt>serpa_out()</tt> || 19 + 101*''N'' || 16 + 27*''N''<br />
|-<br />
| SCK-Frequenz || ~''f''<sub>cpu</sub>/9 || ''f''<sub>cpu</sub>/2<br />
|}<br />
</center><br />
<br />
==Makros, Datenstrukturen, Funktionen==<br />
;<tt>#define SERPA_SIZE</tt>: Define für Anzahl der auszugebenden Bytes<br />
;<tt>extern unsigned char serpa[SERPA_SIZE]</tt>: Das Array, dessen Bytes ausgegeben werden. <tt>serpa[0]</tt> landet in dem Portexpander-IC, das direkt am Controller sitzt. Bit0 erscheint jeweils an Ausgang QA, Bit7 erscheint am Ausgang QH, etc.<br />
;<tt>void serpa_init(void)</tt>: Initialisiert die Schnittstelle bzw. die verwendeten Ports<br />
;<tt>void serpa_out(void)</tt>: Gibt die <tt>SERPA_SIZE</tt> Bytes aus dem Array <tt>serpa</tt> aus.<br />
<br />
'''serpa.h'''<br />
<br />
{{comment|SERiell nach PArallel (serpa) im SPI-Protokoll}}<br />
#ifndef _SERPA_H_<br />
#define _SERPA_H_<br />
<br />
{{comment|4 Bytes (32 Ports)}}<br />
#define SERPA_SIZE 4<br />
<br />
extern unsigned char serpa[];<br />
extern void serpa_out (void);<br />
extern void serpa_init (void);<br />
<br />
#endif {{comment|_SERPA_H_}}<br />
<br />
== Mit SPI-Hardware == <br />
<br />
Das Senden erfolgt, ohne den SPI-Interrupt zu nutzen. Allein der ISR-Prolog/Epilog dauert schon so lange, wie ein Schleifendurchlauf.<br />
<br />
'''serpa.c'''<br />
<br />
{{lcomment|SERiell nach PArallel (serpa) mit Hardware-Unterstuetzung}}<br />
#include <avr/io.h><br />
#include "serpa.h"<br />
<br />
{{lcomment|Array fuer die Daten}}<br />
unsigned char serpa[SERPA_SIZE];<br />
<br />
void serpa_init (void)<br />
{<br />
MAKE_OUT (PORT_MOSI); <br />
MAKE_OUT (PORT_SCK);<br />
MAKE_OUT (PORT_RCK); SET (PORT_RCK);<br />
<br />
{{lcomment|!!! SS muss OUT sein, damit SPI nicht in Slave-Mode wechselt !!!}}<br />
{{lcomment|entfaellt, falls PORT_RCK &#61; PORT_SS}}<br />
MAKE_OUT (PORT_SS);<br />
<br />
{{lcomment|SPI als Master}}<br />
{{lcomment|High-Bits zuerst}}<br />
{{lcomment|SCK ist HIGH wenn inaktiv}}<br />
SPCR = (1 << SPE) | (1 << MSTR) | (1 << CPOL);<br />
<br />
{{lcomment|pullup an MISO vermeidet Floaten}}<br />
SET (PORT_MISO);<br />
<br />
{{lcomment|maximale Geschwindigkeit: F_CPU / 2}}<br />
SPSR |= (1 << SPI2X);<br />
}<br />
<br />
void serpa_out (void)<br />
{<br />
unsigned char anz = SERPA_SIZE;<br />
unsigned char* serp = serpa+SERPA_SIZE;<br />
<br />
do<br />
{<br />
unsigned char data = *--serp;<br />
<br />
{{lcomment|SPDR schreiben startet Uebertragung}}<br />
SPDR = data;<br />
<br />
{{lcomment|warten auf Ende der Uebertragung für dieses Byte}}<br />
while (!(SPSR & (1 << SPIF)));<br />
<br />
{{lcomment|clear SPIF durch Lesen von SPDR}}<br />
SPDR;<br />
}<br />
while (--anz > 0);<br />
<br />
{{lcomment|Strobe an RCK bringt die Daten von den Schieberegistern in die Latches}}<br />
CLR (PORT_RCK);<br />
SET (PORT_RCK);<br />
}<br />
<br />
== Ohne SPI-Hardware == <br />
<br />
Dieser Code funktioniert auch für jeden anderen µC-Typ, der mindestend 3 digitale I/O-Ausgangsports hat, und mit einem Compiler für Standard-C übersetzt wird. Die Pseudocodes <tt>MAKE_OUT</tt>, <tt>SET</tt> und <tt>CLR</tt> sind auch hier an die jeweilige Schaltung/Architektur/Compiler/Controller anzupassen.<br />
<br />
'''serpa.c'''<br />
{{comment|SERiell nach PArallel (serpa) via Software}}<br />
#include "serpa.h"<br />
<br />
{{comment|Array fuer die Daten}}<br />
unsigned char serpa[SERPA_SIZE];<br />
<br />
void serpa_init (void)<br />
{<br />
{{comment|Verwendete Ports auf OUT}}<br />
MAKE_OUT (PORT_SER);<br />
MAKE_OUT (PORT_SCK);<br />
MAKE_OUT (PORT_RCK);<br />
<br />
{{comment|SCR und RCK auf definierten Level HIGH}}<br />
SET (PORT_SCK);<br />
SET (PORT_RCK);<br />
}<br />
<br />
void serpa_out (void)<br />
{<br />
unsigned char anz = SERPA_SIZE;<br />
unsigned char* serp = serpa+SERPA_SIZE;<br />
<br />
do<br />
{<br />
unsigned char bits;<br />
unsigned char data = *--serp;<br />
<br />
{{comment|8 Bits pro Byte rausschieben}}<br />
for (bits = 8; bits > 0; bits--)<br />
{<br />
CLR (PORT_SER);<br />
if (data & 0x80)<br />
{<br />
SET (PORT_SER);<br />
}<br />
<br />
data <<= 1;<br />
{{comment|Strobe an SCK schiebt Daten im Gaensemarsch}}<br />
{{comment|um 1 Position weiter durch alle Schieberegister}}<br />
CLR (PORT_SCK);<br />
SET (PORT_SCK);<br />
}<br />
}<br />
while (--anz > 0);<br />
<br />
{{comment|Strobe an RCK bringt die Daten von den Schieberegistern in die Latches}}<br />
CLR (PORT_RCK);<br />
SET (PORT_RCK);<br />
}<br />
<br />
= BASCOM-Code=<br />
<br />
== Mit SPI-Hardware == <br />
<br />
'''serpa.bas'''<br />
<pre><br />
' SERiell nach PArallel (serpa) mit Hardware-Unterstuetzung<br />
' Beispiel mit 2 Datenbytes<br />
<br />
' SPI Bus (Hardware) als Master konfiguiren<br />
Config SPI = Hard , Master = Yes<br />
<br />
' SPI Bus initialisieren<br />
' setzt das DDR Register entsprechend<br />
Spiinit<br />
<br />
' Bytes für die Daten<br />
Dim Serpa(2) As Byte<br />
Serpa(1) = &B10101010<br />
Serpa(2) = &B00000000<br />
<br />
' Die Bytes auf den SPI Bus schieben<br />
Spiout Serpa(1) , 2<br />
</pre><br />
<br />
=Expander=<br />
<br />
Von den meisten Expandern gibt es auch Unterversionen, wie 74HC (Highspeed CMOS), 74HTC (Highspeed CMOS, TTL-Compatible), etc. Hier tut's z.B. 74HC. Pro Expander fallen Kosten von ca 30-40 Cent an ([[Bezugsquellen#Elektronikbauteile|Reichelt]]). Ungelatchte Register wie 74*164 sind übrigens nicht zu empfehlen, weil bei deren Verwendung wäherend des Schiebens die Ausgänge flattern.<br />
<br />
Die Verwendete SPI-Frequenz ist unkritisch und kann natürlich auch langsamer eingestellt werden. Taktfrequenzen von 50MHz sind für die ICs normalerweise kein Problem. Die steilen Flanken können aber ein Problem bei längeren Kabeln werden.<br />
<br />
;8-Bit Schieberegister mit Ausgangs-Latch:<br />
:;74*594: Shift Clear, Latch Clear, Tri-State<br />
:;74*595: Shift Clear, Tri-State<br />
:;74*596: Shift Clear, [[Open Collector]]/high-Z <br />
:;CD4094, 74*4094: Tri-State<br />
<br />
;8-Bit Schieberegister mit Eingangs-Latch:<br />
:;74*589: Tri-State<br />
:;74*597: Shift Clear<br />
<br />
=Siehe auch=<br />
* [[avr-gcc]]<br />
* [[Bezugsquellen]]<br />
* [[I2C|I&sup2;C-Bus]]<br />
* [[SPI|SPI-Bus]]<br />
* [[RN-Definitionen]] - Empfohlener einheitlicher Stecker für SPI-Bus<br />
<br />
=Weblinks=<br />
* [http://www.gjlay.de/pub/ebook/index.html Dokumentiertes Projekt, das drei 74*595 als Portexpander verwendet]<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Kommunikation]]<br />
[[Kategorie:Praxis]]<br />
[[Kategorie:Software]]<br />
[[Kategorie:Quellcode C]]<br />
[[Kategorie:Projekte]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Getriebemotoren_Ansteuerung&diff=14786Getriebemotoren Ansteuerung2009-04-06T16:32:32Z<p>Holzi: </p>
<hr />
<div>Ist der Entschluss gefasst, für seinen Roboter oder andere Konstruktion einen Getriebemotor zu verwenden, so müssen sich Gedanken gemacht werden, wie er ansteuert werden kann. Gewöhnlich sollen die Motoren ja sowohl in Bezug auf Drehrichtung und Geschwindigkeit über eine Programmiersprache engesteuert werden. Daher wird in der Regel erst mal ein Controllerboard benötigt. Leider kann man an die wenigsten Controllerboards einen Getriebemotor direkt anschließen, eine der wenigen Ausnahmen ist das [[RN-Control]]-Board und das RNBFRA-Board. Bei beiden Boards ist es einfach, dort müssen die Getriebemotoren einfach nur an die Schraubklemmen angeschlossen werden, danach kann man sofort mit der Programmierung loslegen.<br />
<br />
Ich möchte hier aber aufzeigen, wie man Motoren auch bei anderen Boards anschließen kann. Die gleiche Technik läßt sich natürlich auch nutzen, um z.B. mehr als zwei Motoren an [[RN-Control]] anzuschließen.<br />
<br />
==Ansteuerung mit Relais==<br />
<br />
Die einfachste Methode, um Motoren per [[Microcontroller|Controller]] anzusteuern, erreicht man durch die Verwendung von Relais. Mit einem Relais, das zwei Umschaltkontakte besitzt, lässt sich über einen einzelnen Controllerport bequem die Drehrichtung wechseln.<br />
<br />
[[Bild:hbrueckerelais.gif|center]]<br />
<br />
Da auch Relais wegen des Strombedarfes nicht direkt vom Controller geschaltet werden können, wurde in dem oberen Beispiel ein Transistor vorangestellt. Die Diode dient nur dazu, die Spannungen abzuleiten, die beim Ausschalten des Relais induziert werden. Ohne Diode funktioniert das Ganze in der Regel auch, jedoch könnte der Transistor oder sogar der Controller durch die induzierte Spannung beschädigt werden. <br />
Die Schaltung ist also in der Lage, die Drehrichtung umzuschalten, jedoch nicht in der Lage, den Motor zu stoppen. Um den Motor ganz auszuschalten, müsste man noch ein weiteres Relais vorsehen, das die gesamte Motorspannung abschaltet. Ein Schaltbild können wir uns ersparen, da das Ganze recht ähnlich aussieht. <br />
Der große Nachteil von Relaisschaltungen ist, dass die Geschwindigkeit des Motors nicht geregelt werden kann, zudem haben Relais bei sehr vielen Schaltvorgängen einen gewissen Verschleiß. <br />
Vorteil der Schaltung ist jedoch, das man auch sehr große Lasten/Motoren schalten kann.<br />
<br />
<br />
==Ansteuerung mit Relais und MOS-FET==<br />
Die Schaltung ist sehr ähnlich wie die normale Relaisschaltung. Es wird aber in die Masseleitung hinter dem Relais ein [[Feldeffekttransistor#MOSFETS|MOSFET]] und eine Freilaufdiode eingesetzt. Dadurch werden die Nachteile der einfach Relaisschaltung behoben. Durch den MOSFET läßt sich der Motor in der Geschwindigkeit regeln und ggf. abschalten.<br />
<br />
Es sind prinzipiell alle N-Kanal MOS-FETs geeignet. Logik-Level-Typen sind aber auf Grund des geringeren Innenwiderstandes bei 5 V (vom µC) vorzuziehen. Im einstelligen Amperebereich ist der Spannungsabfall vernachlässigbar gering. Deswegen müssen auch keine Bauteile gekühlt werden. Um die Umschaltverluste und Funkstörungen gering zu halten, sollte die [[PWM]]-Frequenz (< 1 kHz) nicht unnötig hoch liegen.<br />
Da das Relais nur Strom verbraucht, wenn es angezogen wird, sollte man den Motor so anschließen, dass in der bevorzugten Drehrichtung (beim Roboter Vorwärtsfahren) das Relais nicht angezogen ist. <br />
Die Schaltung ist sicher gegen Querströme und es können durch Fehler im Programm des µC keine Schäden entstehen.<br />
<br />
Der Verdrahtungsaufwand insgesamt ist minimal und sogar kleiner als bei Motortreiber-ICs, wie dem [[Im RN-Wiki verwendete ICs|L298]], da keine zusätzlichen Bauteile benötigt werden. Daher ist die Schaltung insbesondere für Anfänger geeignet.<br />
<br />
Vorteile sind:<br />
*kurzschluss-/querstromsicher<br />
*hohe Strombelastbarkeit<br />
*sehr geringer Spannungsabfall (< 1 V)<br />
*niedrige Kosten, auch bei hoher Leistung<br />
*Relais kann stromlos geschaltet werden (wenig Verschleiß an Kontakten)<br />
<br />
Nachteile sind:<br />
*hörbares "Klacken" beim Laufrichtungswechsel<br />
*zusätzlicher Stromverbrauch, wenn die Relais geschaltet sind<br />
*keine einfache Motorbremse<br />
*(Verschleiß der Relais, tritt aber erst bei sehr sehr vielen Schaltvorgängen auf)<br />
<br />
==Ansteuerung mit MOS-FET==<br />
===Neufassung===<br />
{{Ausbauwunsch|Die Neufassung kann im momentanen Stand nur als Anregung verstanden werden.<br />
<br />
Insbesondere fehlen noch angepasste Schaltpläne.<br />
<br />
Einige der Anmerkungen aus dem Abschnitt "Kritik an der Schaltung" sind in der Neufassung noch nicht enthalten, die Beschreibung von Verzögerungsgliedern müsste auch eine Erklärung enthalten, welche Verzögerung mit welchen Werten erreicht wird.<br />
<br />
Wenn die Neufassung komplett fertig ist, sollten die alten Texte weg.<br />
}}<br />
====Grundprinzip====<br />
Wesentlich günstiger und auch beliebter ist die Ansteuerung von Motoren mit [[Feldeffekttransistor#MOSFETS|MOS-FET]]s. Also (unipolaren) Transistoren, die quasi leistungslos nur durch Spannungen geschaltet werden und extrem hohe Ströme verkraften. Zu diesem Thema findet man unzählige Beiträge im Roboternetz.<br />
<br />
Die Grundschaltung besteht aus 2 N-Kanal-MOS-FET (hier BUZ11) und zwei P-Kanal-MOS-FET(hier [[Im RN-Wiki verwendete Transistoren|IRF5305]]), mit denen die Motoranschlüsse nach GND bzw. UB geschaltet werden. Zusätzlich sind 4 [[Im RN-Wiki verwendete Elektronikbauteile|Schottky-Dioden]] (z.B. [[Im RN-Wiki verwendete Elektronikbauteile|SB530]]) erforderlich, um Induktionsströme des Motors abzuleiten. Die Dioden werden in Sperrichtung von den beiden Motoranschlüssen nach GND bzw. UB geschaltet.<br />
Auf die extra Dioden kann bei einer Vollbrücke mit modernen MOSFETs meistens verzichtet werden, da die MOSFETs bereits hinreichend gute Dioden enthalten.<br />
<br />
Grundsätzlich muss die Beschaltung der Gate-Eingänge so erfolgen, dass zum Starten des Motors die Transistoren einer Diagonale auf "leitend" und die der anderen auf "sperrend" geschaltet werden. Zum Anhalten des Motors werden z.B. die unteren auf leitend und die oberen auf sperrend geschaltet (Der Motor wird aufgrund des nicht unerheblichen Bremsstroms von Transistor und Freilaufdiode stark gebremst).<br />
Alternativ kann man auch alle Transistoren auf sperrend schalten, der Motor läuft dann im Leerlauf aus.<br />
<br />
Die Transistoren einer Seite dürfen nicht gleichzeitig auf "leitend" geschaltet werden, da dies einen Kurzschluss verursacht.<br />
<br />
Hinweis: Zumindest bei dem Transistor [[Im RN-Wiki verwendete Transistoren|BUZ11]] handelt es sich um ein veraltetes Modell. Wenn es auf hohe Leistung ankommt, sollte da ein anderer Transistor gewählt werden (z.B. [[Im RN-Wiki verwendete Transistoren|IRF 530]]).<br />
<br />
====Elektrische Ansteuerung der Gates====<br />
Beim Umschalten der Transistoren entsteht eine erhöhte Verlustleistung - der Widerstand wechselt von sperrend (sehr großer Widerstand) nach leitend (sehr kleiner Widerstand) und umgekehrt.<br />
<br />
Zwischen beiden Enden des Schaltvorgangs befindet sich der Transistor in der "Widerstandsphase" (weder ganz leitend, noch ganz sperrend), die eine erhebliche Verlustleistung und damit Erwärmung mit sich bringt.<br />
<br />
Deshalb sollte der Schaltvorgang möglichst schnell erfolgen, insbesondere wenn für eine [[PWM]]-Regelung sehr oft geschaltet werden soll. Da zum Umschalten die durch den Aufbau des MOSFETs bedingte Gatekapazität umgeladen werden muss, ist hierzu (sehr kurzzeitig) ein hoher Stromfluss nötig. Zu schnell sollte man wegen der Funkstörungen aber auch nicht schalten.<br />
<br />
=====Schaltung direkt am Port=====<br />
Eine Ansteuerung unmittelbar über den Ausgang eines Mikrocontrollers (oder eines TTL-IC) ist schon wegen der benötigten Spannungen nicht möglich. <br />
<br />
Bei den N-FET kann man sog. "Logik-MOSFET" nehmen, die bereits bei 5 V ausreichend leitet. <br />
<br />
Bei den P-[[MOSFET]] bemisst sich die Schaltspannung gegen UB, mit einem 5 V Port und U<sub>B</sub>=12 V würde also zwischen -12 V und -7 V umgeschaltet, was einen P-[[MOSFET]] erfordern würde, der bereits bei -7 V sperrt.<br />
<br />
Dass ein Portpin nur einen geringen Stromfluss (ca. 20 mA) zulässt, ist ein weiteres Problem und verhindert einen Schaltvorgang mit idealer steiler Flanke. Allerdings ist die Schaltungsvariante mit einem Transistor in diesem Punkt keinesfalls besser, wenn die Gatekapazität durch den PullUp-Widerstand umgeladen werden muss.<br />
Diese Schaltungsversion ist für nicht zu große FETs (bis etwa 2 nF Gate Kapazität), bevorzugt ohne PWM, möglich.<br />
<br />
=====Schaltung mit einem Transistor=====<br />
Eine einfache Steuerschaltung besteht aus einem Transistor-Schalter und einem Pull-Up-Widerstand. Als Schalter hab ich 1/7 eines [[Im RN-Wiki verwendete ICs|ULN2003]] IC verwendet, als PullUp 2200 Ohm. Ein diskreter Aufbau mit 1 Transistor und 2 Widerständen ist aber auch nicht komplizierter.<br />
<br />
Der Vorteil liegt in der Einfachheit, der Nachteil liegt darin, dass die Schaltung nicht sonderlich schnell vonstatten geht: Für die Schaltung des FET muss die Gate-Kapazität transferiert werden, was insbesondere beim Wechsel von 0 V nach U<sub>B</sub> einen Moment dauert, da die Ladung durch den Widerstand hindurch muss.<br />
<br />
Ein kleinerer Widerstand könnte hier helfen, verursacht allerdings einen nicht unerheblichen Stromfluss im geschalteten Zustand (zulässige Verlustleistung beachten).<br />
<br />
=====Schaltung mit zwei Transistoren=====<br />
Eine bessere Ansteuerung sollte sich ergeben, wenn man zwei Transistoren zur Gate-Ansteuerung verwendet: Einer schaltet gegen 0 V, der andere gegen UC. So kann man erreichen, dass in beide Richtungen rasch umgeschaltet werden kann.<br />
<br />
=====Integrierte Gate-Treiber=====<br />
Statt der Beschaltung mit zwei Transistoren kann man auch einen integrierten [[MOSFET]]-Treiber verwenden. Derartige ICs sind darauf ausgelegt, kurzfristig den für eine Umschaltung benötigten hohen Stromfluss zu ermöglichen.<br />
<br />
Es gibt auch Treiber-ICs, die zur Ansteuerung der oberen Transistoren eine Spannung oberhalb von UB erzeugen. Mit solchen Highside-Treibern kann die H-Brücke auch aus 4 N-Kanal-Transistoren gebaut werden, was den Vorteil hat, dass N-Kanal-FETs mit geringerem Schaltwiderstand zu bekommen sind.<br />
<br />
====Logische Ansteuerung der Gates====<br />
Nach der elektrischen Ansteuerung ist die logische Ansteuerung durch den Mikrocontroller zu überlegen.<br />
<br />
=====Mögliche Querströme=====<br />
In der H-Brücke sind zwei problematische Zustände zu berücksichtigen:<br />
<br />
1. Das offensichtliche Problem ist ein Kurzschluss: Wenn beide Transistoren einer Seite auf leitend geschaltet werden, dann wird dadurch ein Kurzschluss erzeugt. Falls vorhanden brennt die Sicherung durch oder es wird sogar etwas beschädigt.<br />
<br />
2. Ein nicht so offensichtliches Problem rührt daher, dass der Schaltvorgang nur mit endlicher Geschwindigkeit abläuft und der Transistor auch schon vor Erreichen des Zielwertes der Gate-Spannung erheblichen Strom leitet. Hierdurch kommt es zu einem Kurzschluss durch den nicht mehr richtig gesperrten und den noch nicht richtig gesperrten Transistor.<br />
<br />
Die Stromspitze selbst liegt noch im Rahmen der Spezifikationen der Transistoren. Sofern ein Messwiderstand von z.B. 0,1 Ohm da ist oder die Spannungsquelle einen vergleichbaren Innenwiderstand hat fließt ein Strom von weniger als 70 A, die Transistoren sind jeweils für Spitzen von über 100 A spezifiziert.<br />
<br />
Allerdings hat die Stromspitze drei Auswirkungen: <br />
<br />
# Die Transistoren erwärmen sich<br />
# Es kann an einem Messwiderstand zu einer Spannungsspitze kommen<br />
# Die Versorgungsspannung bricht kurzzeitig zusammen<br />
<br />
----<br />
<br />
Die Erwärmung des Transistors ist solange kein Problem, wie nur selten umgeschaltet wird. Bei einer Regelung per [[PWM]] könnten sich die kleinen Energiemengen zu einem relevanten Problem addieren. <br />
<br />
Da die Erwärmung - sofern sie relevant wird - leicht ohne Messinstrumente feststellbar ist, dürfte dieser Teil des Problems insofern handhabbar sein, als man leicht feststellen kann, ob das Problem relevant ist und das Problem auf die Transistoren beschränkt sind.<br />
<br />
Bei Leerlauf-Schaltvorgängen im Abstand von 1/15 Sekunden habe ich keine Erwärmung der Transistoren feststellen können, es wurden auch keine zusätzlichen Kühlkörper verwendet.<br />
<br />
----<br />
Die Spannungsspitze am Messwiderstand kann abgeleitet werden:<br />
Als weitere Vorsichtsmaßnahme habe ich den Messport des Controllers mit einem Widerstand und einer Z5.1 Diode abgesichert.<br />
<br />
----<br />
<br />
Die Störung der Versorgungsspannung lässt sich ohne Oszilloskop nicht messen. Insbesondere in umfangreicheren Schaltungen können Störungen an ganz anderen Stellen (z.B. bei Sensoren) auftreten, die man dann nicht gleich mit der Motorsteuerung in Verbindung bringt.<br />
<br />
Um die Störung vom Controller fernzuhalten habe ich dem Spannungswandler vorsichtshalber eine kleine Schottky-Diode ([[Im RN-Wiki verwendete Elektronikbauteile|SB140]]) vorgeschaltet, um ein Entladen des Stützkondensators zu verhindern.<br />
<br />
=====softwaremäßige Ansteuerung=====<br />
Die einfachste Art der Ansteuerung besteht darin, die Schalter der 4 Gates mit 4 Ausgängen des Controllers zu verbinden.<br />
<br />
Die korrekte Ansteuerung muss dann durch die Software garantiert werden. <br />
<br />
Eine Fehlschaltung der Software z.B. bei einem Absturz kann allerdings zur Zerstörung der Schaltung führen, die Schaltung sollte also in jedem Fall eine Sicherung haben.<br />
<br />
=====Einfache Ansteuerung=====<br />
Etwas sicherer ist es, die Schaltung so aufzubauen, dass ein Kurzschluss nicht dauerhaft geschaltet werden kann.<br />
<br />
Hierzu habe ich die Schaltung so aufgebaut, dass die Gates einer Seite jeweils gemeinsam geschaltet werden. <br />
<br />
Bei einer Gate-Spannung von 0V sperrt der N-[[MOSFET]] (U<sub>GS</sub>=0V), der P-[[MOSFET]] leitet bei dieser Gate-Spannung, da hier U<sub>GS</sub>=-UB ist. <br />
<br />
Bei einer Gate-Spannung von UB verhält es sich genau umgekehrt: Der N-[[MOSFET]] leitet (U<sub>GS</sub>=UB) und der P-[[MOSFET]] sperrt (U<sub>GS</sub>=0V)<br />
<br />
Diese einfache Ansteuerung benötigt lediglich zwei Transistorschalter und auch nur 2 Port-Pins, hat jedoch den Nachteil, dass während des Umschaltens die oben beschriebenen Querströme auftreten können. Außerdem ist die gemeinsame Ansteuerung der Gates nur für Spannungen von etwa 6V bis 12 V möglich.<br />
<br />
=====Verbesserungsmöglichkeiten=====<br />
Zur Lösung des Querstrom-Problems gibt es mehrere Ansatzmöglichkeiten, die ebenfalls mit zwei Controller-Ausgängen auskommen.<br />
----<br />
Mittels Logik-Bausteinen werden zwei Ausgänge des Controllers so umgesetzt, dass die folgenden Zustände geschaltet werden können:<br />
<br />
# Motor-Stop: untere Transistoren leitend, obere sperrend (oder umgekehrt)<br />
# Motor-Vorlauf: 1. Diagonale leitend<br />
# Motor-Rücklauf: 2. Diagonale leitend<br />
# Motor-Leerlauf: Alle Transistoren sperrend<br />
<br />
Die Querstrom-Problematik kann hierbei softwaremäßig gelöst werden, indem beim Umschalten jeweils kurz der Leerlauf geschaltet wird, damit alle Transistoren sperren.<br />
----<br />
Eine andere Möglichkeit besteht darin, das Umladen der Gate-Kapazität asymmetrisch zu gestalten, so dass die Transistoren schneller auf sperrend als auf leitend geschaltet werden. Eine einfache Möglichkeit ist die Parallelschaltung einer Diode und eines Widerstandes: In Sperr-Richtung fließt die Ladung langsamer als in die Durchlass-Richtung.<br />
<br />
===Heidingscher Encoder===<br />
Aufgrund der Kritik an der alten Schaltung(siehe '''Alte Schaltungsbeschreibung''') entschied ich mich einen neuen, einfachen sowie preisgünstigen Encoder zu entwickeln, den man mit der 74series aufbauen kann. Als Treiber können sowohl Transistoren verwendet werden, dabei aber Vorwiderstände nicht vergessen! Die [[Im RN-Wiki verwendete ICs|74series]] sind mit 20 mA Treiberstrom also natürlich nicht zum direkten Treiben geeignet.<br />
Die Logikanzeigen in den Grafiken sollen je einen Transistor bzw. Mosfet darstellen. Eventuelle Freilaufdioden müssen natürlich noch hinzugefügt werden.<br />
<br />
====PR Encoder====<br />
[[Bild:Prtreiber.png]]<br />
<br />
Der PR Encoder(PWM-Richtung Encoder) ist mit zwei NOR Gates sowie eines Inverters aufgebaut, d.h. man kann ihn mit nur einem [[Im RN-Wiki verwendete ICs|IC(74HC(T)02)]] aufbauen. Will mein 2 Encoder verwenden, empfiehlt sich den Inverter auszulagern [[Im RN-Wiki verwendete ICs|(74HC(T)04]] oder [[Im RN-Wiki verwendete ICs|74HC(T)14]]. Sollte man keinen Schmitt-Trigger benötigen empfiehlt sich aus Schnelligkeitsgründen die [[Im RN-Wiki verwendete ICs|74HC(T)04]] Variante). <br />
Alternativ ist es noch möglich sich den Inverter zu sparen, und die Ansteuerung für den P(WM) Kanal invertiert laufen zu lassen.<br />
<br />
====PRK Encoder====<br />
[[Bild:Prktreiber.png]]<br />
<br />
Der Prk-Encoder([[PWM]]-Richtung-Kurzschluss-Encoder) ist eine Erweiterung des PR-Encoders. Er erlaubt es zusätzlich, die Motoren durch einen Kurzschluss zu stoppen.<br />
Aufgebaut werden kann dieser aus 1 NOR und 1 NAND Gate. Dabei werden 3 NAND-Gates als Inverter beschaltet (d.h. eine Leitung, die übrigen bleiben auf VCC).<br />
<br />
====Support====<br />
Fragen einfach in das Forum posten, oder mich anschreiben (User s.o.)<br />
<br />
===Alte Schaltungsbeschreibung===<br />
{{FarbigerRahmen|<br />
Achtung! Die Schaltung ist so nicht zu verwenden! Siehe unter '''Kritik an der Schaltung'''<br />
}}<br />
Wesentlich günstiger und auch beliebter ist die Ansteuerung von Motoren mit MOS-FETs. Also Transistoren, die quasi leistungslos nur durch Spannungen geschaltet werden und extrem hohe Ströme verkraften. Zu diesem Thema findet man unzählige Beiträge im Roboternetz. Eine der interessantesten Schaltungen, die im Roboternetz vorgestellt wurde, dürfte diese sein:<br />
<br />
<br />
[[Bild:hbrueckemosfet.gif|center]]<br />
<br />
<br />
Anmerkung: Den 74HC26N gibts wohl nicht , nur die TTL-Version [[Im RN-Wiki verwendete ICs|74LS26]], die HC-Mos-Version lautet [[Im RN-Wiki verwendete ICs|74HC03]].<br />
<br />
Eine sogenannte H-Brücke, die nur aus zwei MOSFETSs und einem Logik-IC besteht. Mit zwei Controllerports kann diese Schaltung sowohl Geschwindigkeit als auch Drehrichtung regeln. Für die Geschwindigkeit ist ein sogenannter [[PWM]]-Port notwendig. Also ein Port, der durch ein gepulstes Signal den Motor etlichemal innerhalb einer Sekunde ein- und ausschaltet und somit quasi die Leistung regelt (siehe [[PWM]]).<br />
Die Schaltung ist so konstruiert, dass immer nur zwei Transistoren durchschalten. Auf diese Weise fließt einmal der Strom von links oben nach rechts unten und einmal von rechts oben nach links unten, der Motor wird also ähnlich wie bei der Relaisschaltung umgepolt. <br />
Bei niedriger [[PWM]]_Frequenz sollte die Schaltung durchaus für einige Ampere geeignet sein, wobei ca. 8 bis 13 V ideal sein sollten.<br />
<br />
Das Logic-IC wurde durch 3x [[Im RN-Wiki verwendete Transistoren|BC547]] Transitoren ersetzt.<br />
<br />
<br />
[[Bild:Hbrückenmosfet BD547.PNG|center|900px]]<br />
<br />
====Kritik an der Schaltung====<br />
<br />
Diese Schaltung wird [http://www.roboternetz.de/phpBB2/viewtopic.php?t=33067&sid=892e80c6cd2d003292e607bcd7a7123aim hier Forum von mehreren Leuten, u.A. Ratber, shaun, massiv kritisiert].<br />
<br />
Ich habe leider nicht das Wissen eine bessere Lösung zu liefern. Das Problem sind die Querströme: Im Umschaltmoment sind highside und lowside switch für kurze Zeit beide leitend. Das entspricht einem Kurzschluss der Versorgungsleitung bei jedem Umschalten mit allen damit verbundenen Problemen (Erwärmung, Schwingung, Sicherungen, Reset). Aus diesem Grund sind NAND-Gatter nicht geeignet!<br />
<br />
Zum Umschalten muss man<br />
*den bisher leitenden [[MOSFET]] ausschalten,<br />
*dann etwas warten,<br />
*und dann den nächsten [[MOSFET]] schließen.<br />
<br />
Dies kann man erreichen, indem man den Einschaltmoment <br />
*durch RC-Glieder verzögert und <br />
*den Ausschaltmoment durch Dioden beschleunigt.<br />
Die entstehenden Schaltungen sind komplex, benötigen viele Bauteile und sind fehleranfällig.<br />
<br />
<br />
Am sinnvollsten sind integrierte [[MOSFET]]-Treiber. Diese haben oft eine einstellbare Tot-Zeit (''Dead-Time''), können hohe Leistungen zum Umladen der Gatekapazität liefern und beachten andere Effekte wie ''Propagation-Time'', Veränderung des Source Potentials beim Highside-switch, etc.<br />
<br />
'''Erklärung von shaun:'''<br />
<br />
Die gezeigte Schaltung taugt auch nur als Prinzipschaltung bedingt, da man einen variierenden Aufwand in eine sichere Verriegelung investieren müsste. Bei fixer und nicht zu hoher Betriebsspannung könnte man mit RD-Kombinationen in den Gateleitungen das Ausschalten beschleunigen und das Einschalten verzögern, so dass die Querleitung wegfällt. Allerdings bewirkt diese simple R-Cg-Verzögerung größere Schaltverluste. <br />
<br />
Setzt man die Verzögerung vor dedizierte Treiber, müssen diese wiederum leistungsfähig genug zum Umladen der Gates sein und bis an die Versorgung heranreichen, weshalb man an diesem Punkt überlegen sollte, ob 95% duty cycle nicht auch reichen würden ''(Anmerkung: Bezug auf bootstrapping?)'' und man integrierte Treiber für reine N-Kanal-Bestückung einsetzen sollte - spart dann wieder etwas Verluste am Highside-Switch, weil N-Kanäler gleicher Generation und Leistungsklasse einen niedrigeren Rds(on) als ihre P-Pendants haben.<br />
<br />
{{Ausbauwunsch|Eine vernünftige diskrete Ansteuerung für eine H-Brücke.<br />
Korrektur auf Rechtschreibfehler, Zeichensetzung, Schreibstil, Fachausdrücke. Gibt's denn keinen, der etwas verbessern möchte?}}<br />
==Ansteuerung mit einem LeistungsOPV==<br />
Die wohl preislich und platztechnisch günstigste Alternative zur Ansteuerung von Motoren in H-Brücken ist die Verwendung von (Leistungs-)Operationsverstärkern.<br />
<br />
===Heidingscher Motortreiber=== <br />
Bei dem Heidingschen Motortreiber wird jeder Anschluss des Motors mit einem Ausgang des Operationsverstärker verbunden, die Eingänge des OPVs selbst als Komparator. Diese Methode ist für kleine und mittlere Motoren(=< 1A) und mäßige PWM-Frequenzen(<10kHz) gut geeignet. Ein RB35 von Conrad kann damit problemlos angesteuert werden. Bei zu hohen [[PWM]]-Frequenzen ist die SlewRate von vielen OPVs zu gering und die entsprechenden OPVs sind dann viel zu teuer und man sollte eine Ansteuerung per [[MOSFET]] (s.o.) bevorzugen. Momentan hat sich der [[Im RN-Wiki verwendete ICs|TCA 0372 DP1]] (0,57€ bei Reichelt) Verwendung gefunden. <br />
Weitere Informationen sind in [http://www.roboternetz.de/phpBB2/viewtopic.php?t=38412 diesem Forumsbeitrag] zu finden.<br />
<br />
===Gleichstromansteuerung===<br />
Eine weitere Möglichkeit ist es, dem Operationsverstärker eine Gleichspannung vorzugeben, mit denen der OPV die Motoren ansteuert. Diese Methode eignet sich sehr gut für analoge Schaltkreise. Der Wirkungsgrad ist allerdings nicht der beste, da die restliche Spannung in Wärme umgesetzt wird. Zudem werden viele weitere Komponenten benötigt, was den Aufbau teurer und fehleranfälliger macht.<br />
Der entsprechende Schaltkreis ist im Datenblatt des TCA 0372 DP1 zu finden.<br />
<br />
==Ansteuerung mit Treiber IC L293 D==<br />
<br />
Dies ist ohne Zweifel die am häufigsten genutzte Ansteuerung bei Roboter-Bastlern: Man nimmt einfach das IC L293D, denn darin sind sogar zwei H-Brücken enthalten. Also mit einem IC lassen sich ohne weitere externe Bauteile gleich zwei Motoren ansteuern. Zwar nur bis ca. 600mA, aber das reicht oft schon für kleinere bis mittlere Roboteranwendungen aus.<br />
<br />
[[Bild:L293Pinout.JPG|center]]<br />
<br />
<br />
[[Bild:hbrueckel293d.gif|center]]<br />
<br />
Wie aus dem Schaltbild zu ersehen ist, werden für die Ansteuerung jedes Motors 3 Ports benötigt. Die Enable-Leitung führt man oft auf einen [[PWM]]-Port welcher wie bei der [[MOS-FET]] Schaltung oben die Geschwindigkeit regelt. Die beiden anderen Ports geben die Drehrichtung an. Immer wenn die Ports unterschiedliche Polarität haben dreht der Motor in eine bestimmte Richtung, je nachdem wo Low und High anliegt. Das Besondere ist, dass wenn an beiden Ports der gleiche Pegel anliegt, also zweimal Low oder High, dann wird nämlich der Motor kurzgeschlossen, das dann als Bremse fungiert. Das Bremsen kann bei Robotern durchaus nützlich sein. Zudem ist bei schnellen Richtungswechseln immer zu empfehlen zuerst kurz zu bremsen, um nicht den Motor oder Motortreiber zu stark zu belasten.<br />
<br />
==Ansteuerung mit dem Schaltkreis L298==<br />
<br />
Der Schaltkreis [[Im RN-Wiki verwendete ICs|L298]] ist quasi der große Bruder des [[Im RN-Wiki verwendete ICs|L293D]]. Er beinhaltet auch zwei komplette H-Brücken, kann also auch zwei Motoren ansteuern. Die Pinbelegung ist ebenfalls dem [[Im RN-Wiki verwendete ICs|L293D]] sehr ähnlich, jedoch verfügt er über eine andere Bauform:<br />
<br />
<br />
[[Bild:L298Pinout.JPG|center]]<br />
<br />
<br />
Der wichtigste Unterschied besteht jedoch darin, dass jede H-Brücke bei [[Im RN-Wiki verwendete ICs|L298]] bis zu 2 A belastet werden kann. Damit lassen sich also schon wesentlich größere Motoren ansteuern. Ein weiterer Vorzug sind die sogenannten SENSE-Ausgänge, über die der komplette Strom fließt. Oft wird hier ein Hochlastwiderstand angeschlossen, um aus der abfallenden Spannung den Strom berechnen zu können. Dies machen sich Steuerungen wie [http://www.roboternetz.de/phpBB2/viewtopic.php?t=2741 RN-Motor] oder aber andere Schrittmotoransteuerungen zunutze, um den Strom zu regeln. Benötigt man keine Strommessung, so müssen die Sense-Ausgänge direkt mit GND verbunden werden. Anders als beim [[Im RN-Wiki verwendete ICs|L293D]] werden hier externe Freilaufdioden gebraucht.<br />
<br />
<br />
[[Bild:hbrueckel298.gif|center]]<br />
<br />
<br />
Ein weiteres Schaltbild gibt es hier [http://www.roboternetz.de/bilder/schaltung298getriebe.gif]<br />
<br />
==Ansteuerung mit L6205==<br />
Der Schaltkreis [[Im RN-Wiki verwendete ICs|L6205]] stellt eine etwas modernere Alternative zur L298-Ansteuerung dar. Die Ansteuerung ist praktisch identisch, der Schaltungsaufbau in etwa gleich. Beim L6205 sind keine externen Freilaufdioden mehr notwendig, dafür ist ein Kondensator und zwei Dioden für die interne Spannungserzeugung notwendig.<br />
Ein großer Vorteil ist auch, dass kein extra Kühlkörper mehr notwendig ist. Viele integrierte Schutzfunktionen im L6205 sorgen dafür, dass der Chip nicht so einfach zerstört werden kann. In der Praxis sind die angegeben 2,8 A jedoch mit Vorsicht zu genießen. Bei Testlayouts erwärmten sich die ICs bereits bei 2 A Dauerstrom (PWM) oft so stark, dass die automatische Temperaturabschaltung reagierte, somit wird man vermutlich ohne Kühlung oder großes Kühllayout auf der Platine auch nicht mehr als beim [[Im RN-Wiki verwendete ICs|L298]] erreichen. <br />
<br />
[[Bild:l6205ic.gif]] [[Bild:l6205pinbelegung.gif]]<br />
<br />
<br />
[[Bild:l6205.gif|center]]<br />
<br />
==Noch mehr Power gewünscht?==<br />
<br />
Obwohl der L298 schon einiges abdeckt, so kommt er spätestens bei den Scheibenwischermotoren langsam an seine Grenzen. Bei starker Belastung können solche Motoren kurzzeitig bis ca. 10 A und mehr ziehen. Für solch starke Motoren gibt es jetzt einen ganz interessanten Motorchip aus dem Kfz-Bereich: vnh3sp (Datenblatt im Roboternetz Download-Bereich). <br />
Mit ihm lassen sich sogar recht große Motoren ansteuern; vorausgesetzt, man kühlt ihn entsprechend, so verträgt der Chip bis zu 30 A. Aber selbst ohne Kühlung bietet er bedeutet mehr Leistung als der L298. Das Schöne, die Ansteuerung ist kaum anders als beim L298 und L293D.<br />
<br />
Kleiner Nachteil: Da es ein SMD-Chip mit 1mm Kontaktabstand ist, muss man schon eine geeignete Platine (spezielles Layout mit Kühlflächen) und etwas Löterfahrung besitzen. Inzwischen gibt es aber schon verschiedene RN-Projekte mit dem Chip (RN-Power, RN-Mini H-Bridge), Platinen und Chip können über den [http://www.shop.robotikhardware.de/shop/catalog/index.php Robotikhardware.de-Platinenservice] bezogen werden. <br />
<br />
<br />
[[Bild:minihbridge_ansteuerung.gif|center]]<br />
<br />
<br />
Alternativ zum [[SMD]]-Chip VNH3SP30 gibt es noch die Alternative VNH2SP30. Dieser Chip erlaubt zwar nur Motorspannungen zwischen 6 und 16 Volt, jedoch hat er einen wesentlich geringeren Innenwiderstand und wird deshalb nur etwa halb so warm wie der VNH3SP30. <br />
Aus diesem Grund eignet er sich auch ideal für kleine Doppelmotorsteuerungen.<br />
Natürlich gibt's auch hierfür ein Projekt und eine Bauanleitung, siehe [[RN-VNH2Dualmotor]]<br />
<br />
Das Schöne ist, dass es dieses RN-Projekt jetzt auch als Fertigmodul gibt!<br />
<br />
<br />
[[Bild:rndualmotoransteuerung.jpeg|center]]<br />
<br />
==Endstufen mit I2C-Bus / RS232==<br />
[[Bild:motctrl.png|thumb|Motoransteuerung über RS232, I2C, RC]]Verwendet man eine der oben vorgestellten H-Bridges, so wird immer vorausgesetzt, dass ein PWM-Signal und mehrere Ports zur Ansteuerung bereitstehen. Ist dies nicht der Fall, weil diese vielleicht schon belegt sind, so lassen sich Endstufen durch einen zusätzlichen Microcontroller auch um beliebige Schnittstellen erweitern. Insbesondere über I2C lassen sich dadurch mehrere Motorboards über einen einzigen Bus ansteuern. Ein Beispiel ist der programmierte Controller MOTCTRL, der speziell für diese Aufgabe gedacht ist. Die Grundschaltung sieht man in der rechten Skizze.<br />
<br />
==Und nie vergessen Motoren zu entstören==<br />
<br />
Das Entstören dient dazu, eine Ausbreitung von Funkstörungen durch das sogenannte "Bürstenfeuer" zu verhindern. Und so wird's gemacht:<br />
<br />
<br />
[[Bild:entstoerung.gif|center]]<br />
<br />
Bei Steuerung des Motors per PWM sind die Induktivitäten hilfreich. Sie verhindern das bei den steilen Flanken des PWM Signals große Ströme duch die Kondensatoren fließen. Alternativ zu den 2 Kondensatoren (C2,C3) gegen das Gehäuse kann das Gehäuse auch direkt an Masse angeschlosssen werden. Bei einer PWM Steuerung ist das die bessere Lösung.<br />
<br />
==Siehe auch==<br />
* [[Getriebemotoren]]<br />
* [[RN-VNH2Dualmotor]]<br />
<br />
==Weblinks==<br />
* [http://www.roboternetz.de/phpBB2/motordrehmoment.php Drehmoment Berechnung]<br />
* [http://www.roboternetz.de/motoruebersicht.html Motoren Übersicht]<br />
* [http://www.shop.robotikhardware.de/shop/catalog/index.php?cPath=65 Bauteilesets]<br />
* [http://www.roboternetz.de/robotertutorial.html Roboter-Tutorial]<br />
* [http://www.roboternetz.de Roboternetz Forum]<br />
<br />
[[Category:Robotikeinstieg]]<br />
[[Category:Praxis]]<br />
[[Category:Grundlagen]]<br />
[[Category:Motoren]]<br />
[[Category:Elektronik]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Avr&diff=14653Avr2009-03-16T06:19:21Z<p>Holzi: </p>
<hr />
<div>[[Bild:AtmelController.jpg|thumb|Beispiel eines AVR Controllers]]<br />
'''AVR''' ist eine 8-Bit [[Microcontroller]]-Familie mit RISC-Architektur.<br />
Im Gegensatz zu vielen anderen Microcontroller-Architekturen hat die AVR-Architektur keine Vorgänger. Sie ist ein komplettes Neudesign, das Anfang der 90-Jahre an der Universität von Trondheim/Norwegen entwickelt und vom (bis heute einzigen) Hersteller [[Atmel]] aufgekauft wurde. Es gibt eine ganze Serie von AVR-Controllern. Sie alle werden ähnlich programmiert, haben vergleichbaren Befehlssatz und physikalische Eigenschaften, bieten jedoch unterschiedliche Features und Peripherie. <br />
<br />
Es gibt zahlreiche und kostenlose Entwicklungssysteme in den Sprachen Basic, C/C++, Pascal und Assembler für diese Controller-Familie. <br />
<br />
== Wofür steht AVR? ==<br />
"AVR" steht angeblich für ''Advanced Virtual RISC'' (in einem Paper der Entwickler des AVR-Kerns Alf Egin Bogen und Vegard Wollan). Laut [[Atmel]] bedeutet es nichts.<br />
<br />
== Hardware ==<br />
AVR-Controller besitzen eine zweistufige Pipeline (fetch and execute), die es ermöglicht, die meisten Befehle innerhalb eines einzigen Prozessortaktes auszuführen. Dadurch ist ein AVR wesentlich schneller als etwa 8051-Controller, bei denen der Prozessortakt intern noch durch 12 geteilt wird.<br />
<br />
*AVR-Kern<br />
** Harvard-Architektur (getrennter Befehls- und Datenspeicher) <br />
** 32 Register, kein Akkumulator, 3 Pointerregister <br />
** EEPROM-Datenspeicher<br />
** [[Watchdog]], [[Bootloader]]-Support, verschiedene Stromspar-Modi, Brownout-Erkennung, Interner Oszillator<br />
** Lineares Speichermodell (keine Segmentierung)<br />
** 8-Bit Architektur ist für Hochsprachen (C) optimiert <br />
* In-System programmierbar: die Controller können sehr einfach über ein Programmierkabel (oft ISP-Kabel genannt), das mit dem PC verbunden wird, programmiert werden &ndash; auch dann, wenn sie sich nicht in einer Schaltung befindet.<br />
* umfangreiche Peripherie<br />
** 8- und 16-Bit-Timer/Counter mit [[PWM]], Capture/Compare, externe Betaktung, asynchrone Operation<br />
** Kommunikation: [[UART|USART]], [[SPI]], [[I2C]] ([[TWI]])<br />
** Analog-Comparator, Analog-Digital-Wandler <br />
** unterschiedlichste externe und interne Interrupt-Quellen (UART, SPI, Timer, A/D-Wandler, Analog-Comparator, ...)<br />
** JTAG (Debugerinterface)<br />
* AVR Typen (AT90 "Classic AVR", ATtiny, ATmega) <br />
* erhältlich in unterschiedlichen Gehäusen, idR Durchsteck und als [[SMD]]<br />
* Viele Entwicklungsboards erhältlich, z.B. das Roboternetzboard [[RN-Control]]<br />
<br />
==Einige Pinbelegungen der populärsten AVR-Controller==<br />
(in etwa nach Leistungsfähigkeit sortiert)<br />
<br />
* [[AT90S2313]]<br />
<br />
[[Bild:at90s2313tiny.png|center]]<br />
<br />
<br />
* [[Atmel Controller Mega8]]<br />
* [[Atmel Controller Mega48 Mega88 Mega168]]<br />
<br />
[[Bild:mega8kompatibel.png|center]]<br />
<br />
* [[Atmel Controller Mega16 und Mega32]]<br />
<br />
[[Bild:Mega1632.gif|center]]<br />
<br />
<br />
* [[Atmel Controller Mega128]] ([[SMD]]-Chip)<br />
<br />
[[Bild:mega128pin.gif|center]]<br />
<br />
<br />
----<br />
<br />
=== Die AVR-Pin-Bezeichnungen und deren Funktion ===<br />
Die meisten Ports sind doppelt belegt und besitzen neben der normalen Port-Funktion noch eine Sonderfunktion. Die verschiedenen Pinbezeichnungen und Sonderfunktionen werden hier beschrieben:<br />
<br />
{| {{Blauetabelle}}<br />
|+ '''Tabelle: Die AVR-Pin-Bezeichnungen und deren Funktion'''<br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Versorgungs- und Referenzpins, Reset<br />
|-<br />
|'''[[VCC]]''' <br />
| Versorgungsspannung von 2,7 V bis 5,5 V bei den L-Varianten (low power), ansonsten 4,5V bis 5,5 V. Neuere AVR ab 2,7 V und ab 1,8 V in V-Variante.<br />
|-<br />
|'''[[GND]]''' <br />
|Masse <br />
|-<br />
|'''AREF''' <br />
|Referenzspannung für den Analog-Digital-Wandler. Auch die interne Bandgap-Referenzspannung kann über diesen Pin entstört werden (dann KEINE externe Spannung an diesen Pin geben (Kurzschluss)!). <br />
|-<br />
|'''AGND''' <br />
|Analoge Masse für AD Wandler und dazugehörige Ports. Sollte in aller Regel mit GND verbunden werden.<br />
|-<br />
|'''AVCC''' <br />
| <br />
Die Betriebsspannung für den Analog-Digital-Wandler (und einiges mehr) (siehe Beschaltungsskizze). Die Pins AVCC und AGND müssen immer beschaltet werden, selbst wenn man den AD-Wandler und Port A nicht benutzt. <br />
|-<br />
|'''RESET''' <br />
|Rücksetz-Eingang, intern über einen [[Pullup]] mit VCC verbunden. Ein LOW–Pegel an diesem Pin für die Dauer von mindestens zwei Zyklen des Systemtaktes bei aktivem Oszillator setzt den Controller zurück. Rücksetzen der Ports erfolgt unabhängig von einem evtl. anliegenden Systemtakt.<br />
|-<br />
|'''PEN'''<br />
|Programming Enable - Diesen Pin gibt es nur beim Mega128/64 u.ä. Wird dieser Pin beim Power-On Reset nach Masse gezogen, geht der Controller in den [[ISP]] Programmiermodus. Man kann ihn also alternativ zu Reset verwenden. In der Regel verwendet man aber die Reset-Leitung und PEN sollte man direkt mit VCC verbinden.<br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| System-Takt<br />
|-<br />
|'''XTAL1''' <br />
|Eingang des internen Oszillators zur Erzeugung des Systemtaktes bzw. Eingang für ein externes Taktsignal, wenn der interne Oszillator nicht verwendet werden soll bzw. Anschluss von Quarz/Keramik-Resonator/RC-Glied.<br />
|-<br />
|'''XTAL2''' <br />
|Anschluss von Quarz oder Keramik-Resonator oder Ausgang des integrierten Oszillators zur Nutzung als Systemtakt (Je nach Fuse-Einstellungen). <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Digitale bidirektionale I/O-Ports<br />
|- <br />
| colspan="2"| Jeder Pin der Ports kann individuell als Eingang oder Ausgang konfiguriert werden. Die I/O-Ports sind maximal 8 Bit breit und verfügen ja nach AVR-Typ über eine unterschiedliche Anzahl von Pins. An jedem als Eingang (Input) geschalteten Pin gibt es zuschaltbare [[Pullup]]-Widerstände, die teilweise auch bei aktivierter Sonderfunkton verfügbar sind.<br />
<br />
Bei eingeschalteten Sonderfunktionen wie UART, SPI, ADC, etc. sind die entsprechenden Pins nicht als "normale" digitale I/O verwendbar, sondern dienen der Sonderfunktion. Die Anzahl der als I/O verwendbaren Pins ist auch abhängig von den Fuse-Einstellungen (Vorsicht beim Umstellen, Handbuch GENAU lesen!).<br />
|-<br />
|'''PA 0 – 7''' || Port A <br />
|-<br />
|'''PB 0 – 7''' || Port B <br />
|-<br />
|'''PC 0 – 7''' || Port C <br />
|-<br />
|'''PD 0 – 7''' || Port D <br />
|-<br />
|'''PE 0 – 7''' || Port E <br />
|-<br />
|'''PF 0 – 7''' || Port F <br />
|-<br />
|'''PG 0 – 7''' || Port G <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Externe Interrupts<br />
|- <br />
| colspan="2"| Die PCINT-Interrupts gibt es nur für neuere AVRs wie den [[ATmega88]]. Falls die Anzahl an externen Interrupts nicht ausreicht, kann evtl. auch andere Hardware dafür eingesetzt werden, etwa der Analog-Comparator mit interner Bandgap-Referenz, falls er anderwärtig nicht gebraucht wird.<br />
|-<br />
|'''INT0''' ||Externer Interrupt 0<br />
|-<br />
|'''INT1''' ||Externer Interrupt 1<br />
|-<br />
|'''INT2''' ||Externer Interrupt 2 <br />
|-<br />
|'''PCINTx''' ||Pin-Change Interrupt<br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| [[Timer]] und [[PWM]]<br />
|-<br />
|'''T0''' <br />
|Timer 0: externer Takteingang.<br />
|-<br />
|'''T1''' <br />
|Timer 1: externer Takteingang.<br />
|-<br />
|'''OC0''' <br />
|PWM bzw. Output Compare Ausgang des Timers 0 <br />
|-<br />
|'''OC1A''' <br />
|Ausgang für die Compare-Funktion des integrierten Zeitgeber- / Zählerbausteines <br />
Der erste PWM-Ausgang des Timers1. Er kann zum Regeln der Bot-Motorgeschwindigkeit benutzt werden. <br />
|-<br />
|'''OC1B''' <br />
|Ausgang für die Compare-Funktion des integrierten Zeitgeber- / Zählerbausteines <br />
Der zweite PWM-Ausgang des Timers1. Er kann zum Regeln der Bot-Motorgeschwindigkeit benutzt werden. <br />
|-<br />
|'''ICP1''' <br />
|Eingang für die [[Timer/Counter_(Avr)#Input_Capture|Capture-Funktion]] des integrierten Zeitgebers / Zählerbausteines <br />
<br />
|-<br />
|'''OC2''' <br />
|[[Pwm]] bzw. Output Compare Ausgang des Timers2. Er kann zum Regeln der Bot-Motorgeschwindigkeit benutzt werden. <br />
|-<br />
|'''TOSC1, TOSC2''' <br />
|TOSC1 und TOSC2 sind Eingänge für den asynchronen Modus von Timer2. Sie sind vorgesehen für den Anschluss eines externen Uhrenquarzes ( 32.768 kHz ). Damit lassen sich zum Beispiel sehr genaue Ein-Sekunden-Impulse für eine Uhr generien. <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Analog-Digital-Wandler<br />
|-<br />
|'''ADC0''' bis '''ADC7''' <br />
|Eingänge des AD-Wandlers. Spannungen können hier gemessen werden oder an den Analog-Komparator weiter geleitet werden. <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Analog-Komparator<br />
|-<br />
|'''AIN0, AIN1''' <br />
|Die beiden externen Eingänge des Analog-Komparators. <br />
Mit AIN0(+) und AIN1(-) kann man zwei Spannungen miteinander vergleichen. Wenn die Spannung an AIN0 höher als bei AIN1 ist, liefert der Komparator "High", ansonsten ein "Low". Als interne Eingänge des Komparators können die Interne Bandgap-Referenzspannung oder Ausgänge des ADC-Multiplexers dienen.<br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| Serielle Schnittstelle ([[UART|USART]])<br />
|-<br />
|'''RXD''' <br />
|Eingang der Seriellen Schnittstelle (Receive Data), TTL-Pegel <br />
|-<br />
|'''TXD''' <br />
|Ausgang Serielle Schnittstelle (Transmit Data), TTL-Pegel <br />
|-<br />
|'''XCK''' <br />
|Externe Takt für den USART. Wird nur in Sonderfällen für den Takt benötigt. <br />
USART ("Universal Synchronous/Asynchronous Receiver and Transmitter"). Das ist die serielle Schnittstelle, die zur Datenübertragung zwischen Mikrocontroller und PC genutzt wird. Zur bidirektionalen Übertragung werden zwei Pins am Controller benötigt: TXD und RXD. Über TXD ("Transmit Data") werden Daten gesendet, RXD ("Receive Data") dient zum Empfang. <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| [[SPI]]-Schnittstelle<br />
|-<br />
|'''SS''' <br />
|SPI-Interface – wird benötigt, um den richtigen Slave am Bus zu wählen <br />
|-<br />
|'''MOSI''' <br />
|SPI-Interface – Datenausgang (als Master) oder Dateneingang (als Slave), verwendet bei ISP (In-System-Programmierung)<br />
|-<br />
|'''MISO''' <br />
|SPI-Interface – Dateneingang (als Master) oder Datenausgang (als Slave), verwendet bei ISP (In-System-Programmierung)<br />
|-<br />
|'''SCK''' <br />
|SPI-Interface – Bustakt vom Master, verwendet bei ISP (In-System-Programmierung)<br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| [[I2C|I<sup>2</sup>C]]-Schnittstelle ([[TWI]])<br />
|-<br />
|'''SDA''' <br />
|I2C-Schnittstelle (Bus aus 2 Leitungen) Datenleitung <br />
|-<br />
|'''SCL''' <br />
|I2C-Schnittstelle (Bus aus 2 Leitungen) Clockleitung <br />
<!-------------------------------------------------------------------------------------><br />
|- {{Hintergrund1}}<br />
! colspan="2"| [[JTAG]]-Interface<br />
|-<br />
|'''TDI''' <br />
|JTAG-Debug Interface - Über dieses Interface kann man den AVR programmieren und debuggen. Die Schnittstelle ist ähnlich wie die SPI Schnittstelle und hat getrennte Dateneingangs- und Datenausgangsleitungen sowie eine Taktleitung. TDI ist die Dateneingangsleitung<br />
|-<br />
|'''TDO''' <br />
|JTAG-Debug Interface - TDO ist die Datenausgangsleitung des JTAG Interface<br />
|-<br />
|'''TMS''' <br />
|JTAG-Debug Interface<br />
|-<br />
|'''TCK''' <br />
|JTAG-Debug Interface <br />
|}<br />
<br />
== Timer/Counter ==<br />
Für Infos zu Timer und Counter siehe Artikel [[Timer/Counter (Avr)]].<br />
<br />
== Analog-Digital-Wandler ==<br />
Für Infos zu Analog-Digital-Wandler siehe Artikel [[ADC (Avr)]].<br />
<br />
== Analog-Komparator ==<br />
Für Infos zu Analog-Komparator siehe Artikel [[Analog Komparator (Avr)]].<br />
<br />
== TWI/I2C ==<br />
Für Details über das Two-wire Serial Interface (kurz [[TWI]]) siehe Artikel [[TWI]].<br />
<br />
== UART/USART ==<br />
Für Details über den UART/USART siehe Artikel [[UART]].<br />
<br />
== SPI - Serial Peripheral Interface ==<br />
Für Details über SPI siehe Artikel [[SPI]].<br />
<br />
Näheres zu SPI beim AVR siehe [[SPI (AVR)]].<br />
<br />
== USI - Universal Serial Interface ==<br />
Für Infos zu USI (Universal Serial Interface) siehe Artikel [[USI (Avr)]].<br />
<br />
== Die Fusebits ==<br />
Zur Konfigurierung eines AVR-Controllers werden Fusebits benutzt. Bei der Auslieferung neuer AVR Controller sind die Fusebits bereits vorkonfiguriert, in der Regel auf den internen RC Oszillator und etwa 1 MHz Frequenz. In vielen Fällen kann die Konfiguration unverändert bleiben. Bei den Typen Mega xxx bestimmen einige Fusebits beispielsweise, dass der interne Taktgeber aktiviert ist. Soll z.B. dagegen ein externer Quarz anschlossen oder die Taktfrequenz geändert werden, so müssen auch die Fusebits geändert werden. Auch das Deaktivieren des "[[On Chip Debugging]]" Modus ist oft notwendig, wenn alle Ports genutzt werden sollen. <br />
<br />
Die Fusebits werden in der Regel über die Software eingestellt, welche auch für das Übertragen des Programmcodes zuständig ist. Besonders einfach geht dies beispielsweise mit der Entwicklungsumgebung [[Bascom]]. Aber auch andere Programme wie [[PonyProg]] können für die Umstellung der Fusebits genutzt werden. Einmal eingestellte Fusebits bleiben bis zur erneuten Fusebit-Änderung erhalten. Der normale Programmiermodus verändert die Fusebits nicht. <br />
<br />
Je nach AVR Controllertyp sind unterschiedliche Fusebits (Einstellungen) vorhanden. Die genaue Beschreibung findet man im jeweiligen Datenblatt. Da aber falsch gesetzte Fusebit-Einstellungen zu den häufigsten Problemen gehören, liste ich hier die Funktion der üblichen Fusebits nochmals genauer auf:<br />
<br />
{| {{Blauetabelle}}<br />
|'''CKSEL0, CKSEL1, CKSEL2, CKSEL3'''<br />
|Die Kombination dieser 4 Fusebits bestimmt die Taktquelle des Controllers. Das kann eine interner Taktgenerator, ein Quarz, Quarzoszillator, RC-Glied und ähnliches sein.<br />
|-<br />
|'''JTAGEN'''<br />
|Hiermit wird die "[[On Chip Debugging]]" Schnittstelle aktiviert bzw. deaktiviert. Das sind die Bits mit den Bezeichnungen TDI, TDO, TMS und TCK. Möchte man diese Pins als normalen Port nutzen, so muss diese Schnittstelle immer deaktiviert werden. Alternativ kann man das JTAG aber auch per Software deaktivieren.<br />
|-<br />
|'''SUT0, SUT1'''<br />
|Die sogenannte StartUp-Zeit (PowerOn delay). Diese Einstellung muss abhängig von der Art des Taktgenerators eingestellt werden, genaueres im jeweiligen Datenblatt. <br />
|-<br />
|'''SPIEN'''<br />
|Hiermit kann die serielle [[AVR-ISP Programmierkabel|ISP-Programmierung]], welche die meisten Programmierkabel nutzen, deaktiviert werden. Dies sollte man lieber vermeiden, denn wenn dieser Programmiermodus deaktiviert wurde, kann nur noch der Parallel-Programmiermodus genutzt werden. Der Parallel-Programmiermodus benötigt jedoch ein spezielles Programmiergerät, das die wenigsten Bastler besitzen. ''Also Vorsicht!''<br />
|-<br />
|'''BODEN'''<br />
|Über dieses Bit wird der '''Brown-out Detector''' aktiviert bzw. deaktiviert. Dies ist eine Überwachung der Betriebsspannung, die dafür sorgt, dass bei Spannungseinbrüchen ein ordentlicher RESET durchgeführt wird. Dadurch wird verhindert, dass der Controller in einen undefinierten Zustand gerät (hängen bleibt) oder versehentlich das EEPROM / Flash verändert. In der Regel sollte man daher den '''Brown-out Detector''' aktivieren.<br />
|-<br />
|'''BOOTLEVEL'''<br />
|Über dieses Bit kann die Spannung festgelegt werden, ab welcher der '''Brown-out Detector''' den Controller neu startet (also RESET ausführt). <br />
|-<br />
|'''BOOTRST'''<br />
|Gewöhnlich startet ein Programm im Controller nach einem RESET ab Adresse 0. Durch dieses Fusebit kann der Controller jedoch veranlasst werden, nach einem Reset einen sogenannten Bootloader-Bereich auszuführen. Ein [[Bootloader]] kann genutzt werden, um Controller über andere Schnittstellen (z.B. RS232) zu programmieren.<br />
|-<br />
|'''BOOTSZ0, BOOTSZ1'''<br />
|Der zuvor genannte Bootloaderbereich kann bei AVR-Controllern verschieden groß sein. Über diese beiden Bits können vier verschiedene Größen eingestellt werden. Siehe unter [[Bootloader]].<br />
|-<br />
|'''EESAVE'''<br />
|Dieses Bit legt fest, ob beim Programmieren des Controllers (man nennt es auch brennen) immer das EEPROM gelöscht werden soll.<br />
|-<br />
|'''CKOPT'''<br />
|Abhängig von den Einstellungen von CKSEL kann hier dir Oszillator-Verstärkung eingestellt werden. Genaueres im Datenblatt des jeweiligen Controllers.<br />
|-<br />
|'''WDTON'''<br />
|Schaltet den WatchDog-Timer beim Booten ein/aus. Dies ist auch per Software möglich<br />
|-<br />
|'''RSTDISBL'''<br />
|Durch dieses Bit kann man den RESET-Pin deaktivieren und dann als normalen I/O-Port nutzen. Aber Vorsicht! Da die RESET-Leitung beim Programmieren (Brennen) des Chips genutzt wird, kann man nach dessen Deaktivierung den Controller mit den üblichen [[AVR-ISP Programmierkabel|ISP-Adaptern]] nicht mehr programmieren. In diesem Fall könnte man zwar den Controlle noch mit speziellen Programmiergeräten im Parallelmodus programmieren, aber in der Praxis verfügen nur wenige Bastler über ein Programmiergerät, das dies leistet.<br />
|-<br />
|'''LB1, LB2'''<br />
|Das sind die sogenannten Lockbits, mit denen sich das Auslesen des Flash- als auch EEPROM-Speichers verhindern läßt. Zwar können andere Anwender immer noch Daten lesen, allerdings handelt es sich dabei nicht mehr um den wirklichen Inhalt sondern lediglich um wirre Datenbytefolgen. Programmierer, die den erarbeiteten Code vor Raubkopierern schützen wollen, nutzen diese Lockbits. Das Programmieren ist auch bei gesetzen Lockbits noch möglich. Der Bootloader-Bereich wird nicht durch die Lockbits geschützt.<br />
|-<br />
|'''BLB01, BLB02'''<br />
|Durch diese Bits kann der Code sogar vor dem Zugriff durch den Bootloader geschützt werden<br />
|-<br />
|'''BLB11, BLB12'''<br />
|Diese Bits schützen den Bootloaderbereich selbst<br />
|}<br />
<br />
Wie man die Fusebits mit [[Bascom]] einstellt, wird im Beitrag [[Bascom - Erstes Programm in den AVR Controller übertragen]] erläutert.<br />
<br />
''Autoren des Artikels: Frank, Luma''<br />
<br />
== Siehe auch ==<br />
* [[AVR-Einstieg leicht gemacht]]<br />
===Entwicklungsumgebungen===<br />
'''[http://www.roboternetz.de/wissen/index.php/Microsoft Das neueste Microsoft Visual Studio: Die kostenlose Version (Express Edition) setzt auf WinAVR und auf den GCC auf, compiliert über custom-build und generiert ein Script für Ponyprog. Alles mit einem Klick.]'''<br />
<br />
* [[Bascom]] - Basic-Entwicklungssystem<br />
* [[Bascom - Erstes Programm in den AVR Controller übertragen]]<br />
* [[Avr-gcc|avr-gcc]] - Leistungsfähiger AVR-Port des freien Compilers GCC<br />
* [[WinAVR]] - Freies, kostenloses Werkzeugpaket mit avr-gcc, binutils, tools ([[make]], [[Programmer's Notepad]], [[avrdude]], etc.) für MS-Windows.<br />
* [[Linuxdistribution_Avr-live-cd]]<br />
* [[AVR_Assembler_Einf%C3%BChrung|AVR Assembler Einführung (AvrStudio)]]<br />
* [http://www.mikroe.com/en/compilers/mikropascal/avr/ MikroPascal for AVR] Sehr gute kommerzielle Pascal Entwicklungsumgebung. Der Compiler ist auch für PIC und andere Controller verfügbar.<br />
<br />
=== Hardware ===<br />
* [[AVR-ISP Programmierkabel]] - Bauanleitung für die AVR Controller Programmierkabel<br />
* [[RN-Control]] - Eines der beliebtestet AVR-Boards im Roboternetz<br />
* [[RNBFRA-Board]] - Größeres Board mit zwei Atmel Controllern<br />
===Sonstiges===<br />
* [[Atmel]]<br />
* [[HEX Beispiel-Dateien für AVR]]<br />
* [[Bootloader]]<br />
* [[On Chip Debugging]]<br />
<br />
== Weblinks ==<br />
* [http://www.atmel.com/dyn/products/param_table.asp?family_id=607&OrderBy=part_no&Direction=ASC Aktuelle AVR Vergleichstabelle]<br />
* [http://www.atmel.com/dyn/products/devices.asp?family_id=607 Die Datenblätter zu Atmel Controllern]<br />
* [https://mpg.dnsalias.com/~magerlu/rn-wiki/avrtimer_applet Java Applet Timer Berechnung] <br />
* [http://www.roboternetz.de/phpBB2/dload.php?action=file&file_id=169 AvrTimer Windows Berechnungstool (für Bascom, nur nach Anmeldung)]<br />
* [http://people.freenet.de/gjl/helferlein/avr-uart-rechner.html AVR-Baudraten-Rechner (JavaScript)]<br />
<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Grundlagen]]<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Abkürzung|AVR]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Linuxdistribution_Avr-live-cd_DISCONTINUED&diff=14650Linuxdistribution Avr-live-cd DISCONTINUED2009-03-15T07:27:06Z<p>Holzi: </p>
<hr />
<div>Die Avr-live-CD hat die Zielsetzung, ein komfortables und kostenloses Betriebsystem bereitstellen, das <br />
möglichst viele Funktionen für das Programmieren von [[AVR]]s zur Verfügung stellt. <br />
[[Bild:Avrlivecd_screen1.png|thumb|Desktop]]<br />
== Grundlagen ==<br />
[[Bild:Avrlivecd_screen2.png|thumb|Kontrollerlab]]<br />
Die Avr-live-CD basiert auf Slax. Slax basiert auf der Linuxdistribution Slackware und hieß Ursprünglich "Linux Live CD". <br />
Für das Compilieren des Quelltextes wird [[avr-gcc]] verwendet. Der Binärcode in Hex-Form wird mittels avrdude auf den AVR geladen. Kontrollerlab wird als Interface und Programmierumgebung genutzt. <br />
<br />
Diese CD bietet dem Nutzer somit eine kostenlose Softwarelösung, die auf fast jedem PC lauffähig ist. Es werden durch avrdude und avr-gcc viele Programmierkabel, AVRs und Programmiersprachen untersützt. Eine komfortable Bedienung vereinfacht das Entwickeln. Bald wird auch ein Simulator folgen. Diese CD ist nicht nur für Linuxprofis geeignet, sondern wurde auf eine einfache Bedienung ausgelegt. Es sind die schnelleren, aber umständlicheren Konsolenprogramme vorhanden, jedoch lassen sich alle Entwicklungsaufgaben auch über grafische Benutzeroberflächen erledigen. Die CD wurde speziell für diese Aufgaben entwickelt und hat die benötigten Anwendungen schon vorinstalliert.<br />
<br />
== Installation ==<br />
Um die Avr-live-CD zu verwenden, entpacke man das RAR-Verzeichnis und brenne die ISO Datei. <br />
Der Computer wird nun neu gestartet und es wird das Bios aufgerufen. Hier muss die Bootreihenfolge<br />
geändert werden. Die CD muss hierbei von höherer Priorität sein als die Harddisk. Das geänderte BIOS abspeichern und den Computer weiter mit eingelegter Avr-Live-CD hochfahren lassen.<br />
<br />
=== Hinweise zur Benutzung/Eigenarten ===<br />
Im Moment ist es nötig in das Verzeichnis, in der sich der Quelltext befindet, eine Datei zu kopieren. Diese Datei heist "crt[avrtyp].o". Diese Dateien sind unter "Avrlibs" auf dem Destop verlinkt. In der neuen Version der AvrLiveCD ist dieser Bug behoben.<br />
<br />
== Relases ==<br />
=== Alpha (relased) ===<br />
Die AvrLiveCD hatte mitte Dezember 2006 das 1. Relase. Erhaten sind die Grundlegenden AVR-Tools wie [[avr-gcc]] und [[avrdude]].<br />
=== Betha (released)===<br />
Die neue Version wurde abgespeckt, sodass nurnoch die Notwendigen Funktionen enthalten sind. Die neue Version von Kontrollerlab ist installiert. Für gute Codeoptimierung sorgt jetzt der Gcc 4.1.2.<br />
=== Neue Distribution (alpha release)===<br />
Ich habe mich dieses Projektes nach Rücksprache wieder angenommen und ein neues Livesystem zusammengebaut. Zu finden ist es unter:<br />
[http://chepaz.endofinternet.net/avrslax.php AVR-Slax Reloaded]<br />
Jegliches Feedback ist erwünscht.<br />
mfg, Jöran<br />
<br />
== Feedback ==<br />
Hier werden alle Feedbacks über die AvrLiveCD gelistet.<br />
<br />
<pre>Außerdem wollt ich Dir noch zu Deinem großartigen Projekt gratulieren. Ich denke, dass <br />
speziell viele Windows-Leute genau auf sowas gewartet haben, und dass sie dann damit<br />
vielleicht auch in die Linux-Community gelockt werden.</pre><br />
* 7. Jan. 2007<br />
== Mitarbeit ==<br />
Jeder kann bei der Avr-live-CD mitarbeiten. Jeder kann die Versionen nach belieben modifizieren, verändern, etc. Nun nurnoch hochladen und hier publizieren.<br />
<br />
<br />
<br />
<br />
{{Ausbauwunsch|Diesen Artikel bitte noch erweitern. Dabei eventuell die Installation und eine Benutzertutorial erstellen.}}<br />
<br />
== Autoren ==<br />
--[[Benutzer:Overthere|Overthere]] 08:12, 15. Dez 2006 (CET)<br />
<br />
==Siehe auch==<br />
* [[AVR]]<br />
<br />
==Weblinks==<br />
* [http://www.avrlivecd.umfragen-service.de/ Projekthomepage]<br />
* [http://www.slax.org Slax]<br />
* [http://www.cadmaniac.org Kontrollerlab] <br />
* [http://www.roboternetz.de/phpBB2/viewtopic.php?t=25912 Forumbeitrag]<br />
* [http://avrlivecd.xfuture-server.de/ Avr-Live-CD] <br />
* [http://www.xfuture-media.de Xfuture-Media(Hoster der Avr-Live-CD)]<br />
<br />
=== Sponsoring ===<br />
Die Avr-live-CD [http://www.xfuture-media.de Xfuture-Media] hat sich bereiterklärt die Avr-Live-CD zu hosten. Herzlichen Dank!<br />
<br />
=== Download ===<br />
* [http://www.avrlivecd.umfragen-service.de/ Projekthomepage]<br />
* [http://avrlivecd.xfuture-server.de/ AvrLiveCD-Slaxmodule(21 Mb) (Qt-Lib noch notwendig)]<br />
* Version auswählen und .mo Datei downloaden.<br />
* [http://www.slax.org/modules.php?category=libraries&id=1422&name=Qt+Libraries Qt-Lib]<br />
<br />
<br />
<br />
[[Kategorie:Software]]<br />
[[Kategorie:Microcontroller]]<br />
[[Kategorie:Robotikeinstieg]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Diode&diff=14649Diode2009-03-15T07:21:41Z<p>Holzi: </p>
<hr />
<div>Eine Diode hat die Eigenschaft, Strom nur in einer Richtung durchzulassen.<br />
Sehr häufig werden Dioden als sogenannte Gleichrichterdioden in einem Wechselstromkreis verwendet. Dadurch, dass Dioden Strom nur in eine Richtung durchlassen, wird am Ausgang ein pulsierenden Gleichstrom erzeugt, der dann mit Hilfe eines Elkos geglättet wird. Es gibt jedoch noch viele weitere Anwendungen in der Elektronik, bei denen es darauf ankommt, daß sehr kleine Steuerströme nur in eine Richtung fließen können. Dioden werden auch als Schutzdioden genutzt, um eine teure Schaltung (Controllerboards) vor der Zerstörung durch eine Verpolung zu schützen. <br />
<br />
Eine Diode besteht aus zwei Schichten, einem n-dotierten und einem p-dotierten Halbleitermaterial, die sich berühren. Aufgrund von Abstoßung bzw. Anziehung von gleichen Ladungen findet, abhängig von der Polung einer externen Spannungsquelle, entweder ein Stromfluß statt oder wird komplett unterbunden. Somit leitet eine Diode nur in eine Richtung. <br />
<br />
==Schaltzeichen==<br />
<br />
[[Bild:schaltzeichendiode.jpg]] [[Bild:Diodebeispiel.gif]]<br />
<br />
<br />
[[Bild:kennliniediode.jpg|Kennlinienverlauf von Germanium- und Silizium-Dioden]]<br />
<br />
<br />
<br />
== Diodentypen ==<br />
<br />
===Gleichrichterdiode===<br />
Gleichrichterdioden sind die "normale" Form der Dioden. Neben den langsamen Ausführungen für Netzfrequenz gibt es auch schnelle (fast, ultra fast) Ausführungen für Schaltnetzteile und ähnliche Anwendungen. Das schnell bei den Dioden bezieht sich dabei auf den Übergang vom leitenden in den sperrenden Zustand. Wenn die Spannung schnell von Vorwärts- in Sperrichtung wechselt, kann bei langsamen Dioden noch einige Mikrosekunden lang Strom in Speerichtung fleißen. Beim Wechsel von sperrend nach leitend sind alle Dioden schnell.<br />
<br />
===Schottky Diode===<br />
[[Bild:Schaltsymbol_Schottkydiode.png|left|Schaltsymbol Schottkydiode]]<br />
Hier erfolgt die Sperrschichtbildung zwischen einem N-dotierten Siliziumkristall und einer Metallelektrode (Randschichttheorie nach W. Schottky, 1938). Kennzeichen des nach dem Planarverfahren hergestellten Metall-Halbleiterübergangs sind eine gegenüber Silizium niedrige Kniespannung (0,3V...0,4V), ein sehr scharfer Kennlinienknick in Durchlaß- und Sperrichtung, niedrige Sperrspannung, hohe Sperrströme, geringes Rauschen und extrem schnelle Schaltzeiten. Wegen der schnellen Schaltzeiten und geringen Durchlassspannung werden Schottkydioden häufig in Schaltnetzteilen eingesetzt.<br />
<br />
===Lawinen-Gleichrichterdiode===<br />
Im Gegensatz zu normalen Dioden darf die Durchbruchspannung U(BR) mit nichtperiodischen Verlustleistungsimpulsen überschritten werden, ohne daß damit die Lawinen-Gleichrichterdiode (Si-Diode mit kontrolliertem Durchbruchverhalten) zerstört wird.<br />
<br />
===Selengleichrichter===<br />
Die Selengleichrichter (polykristallin) haben im Vergleich zu Siliziumgleichrichtern größere Abmessungen und hohe Durchlaß- und Sperrverluste. Vorteilhaft ist eine höhere Überlastbarkeit und der Überlastschutz mit normalen flinken Sicherungen. Je Gleichrichterplatte werden bis zu 45 Volt Sperrspannung und Stromdichten bis zu 150mA/cm2 erreicht.<br />
<br />
===Zenerdiode===<br />
[[Bild:Schaltsymbol_Zenerdiode.png|left|Schaltsymbol Zenerdiode]]<br />
<br />
Wird die Sperrspannung einer Diode Überschritten, dann leitet die auch in Sperrrichtung; sie ''bricht durch''.<br />
<br />
Zener-Dioden sind Dioden, die für den Betrieb in Sperrichtung ausgelegt sind. Sie haben bei der sogenannten Zenerspannung eine sehr steile Kennlinie, die relativ temperaturstabil ist.<br />
Daher werden Zenerdioden meist zur Spannungsstabilisierung eingesetzt. Den niedrigsten Temperatukoeffizienten und den schärfsten<br />
Kennlinienknick haben Zenerdioden mit einer Sperrspannung zwischen 5V und ca 6V. Zenerdioden werden gefertigt für Spannungen von wenigen Volt bis ca. 200V. Für kleine Durchbruchsspannungen von z.B. 1.4V kann man zwei Si-Dioden in Reihe oder eine LED in Vorwärtsrichtung betreiben.<br />
<br />
===Lumineszenzdiode===<br />
[[Bild:Schaltsymbol_Lunineszenzdiode.png|left|Schaltsymbol Lunineszenzdiode (LED)]]<br />
Besser bekannt als "[[Leuchtdioden|Leuchtdiode]]" oder kurz LED. In Durchlassrichtung wird ein Teil der beim Passieren des pn-Übergangs freiwerdenden Energie in Form von Licht charakteristischer Wellenlänge frei.<br />
<br />
Die Vorwärtsspannung der Leuchtdiode ist um so größer, je höher die Energie der ausgesendeten Photonen ist. Sie ist am kleinsten für Infrarotdioden (IR-Diode, ca. 1.2V) und steigt von Rot (ca. 1.5-1.8V) über Gelb, Grün bis zu Blau/Weiss und Ultraviolett (UV-Diode, ca. 3-3.5V). Sie sind sensibel gegen Überstrom und Falschpolung, denn sie haben sehr geringe Sperrspannungen!<br />
<br />
Eine Leuchtdiode kann in gewissem Umfang also auch als Photodiode eingesetzt werden. Sie ist aber unempfindlich auf Licht längerer Wellenlängen.<br />
<br />
===Photodiode===<br />
[[Bild:Schaltsymbol_Photodiode.png|left|Schaltsymbol Photodiode (LED)]]<br />
Auf die pn-Schicht auftreffende Photonen oberhalb einer bestimmten Frequenz trennen dort Ladungsträger, was zu einer intensitätsabhängigen Spannung führt, bzw. die Photodiode wird zu einer Stromquelle. Auch Leuchtdioden sind in gewissem Umfang als Photodioden einsetzbar. Siehe auch [[Fotodiode]].<br />
<br />
<br style="clear:left"/><br />
<br />
===Tunneldiode===<br />
[[Bild:Schaltsymbol_Tunneldiode.png|left|Schaltsymbol Tunneldiode]]<br />
<br />
Bei einer Tunneldiode ist die Dotierung der Halbleiterschichten so hoch, dass bereits bei kleiner Flusspannung ein Stromfluss stattfindet (Esaki-Strom). Mit wachsender Flussspannung verschwindet dieser Effekt, und die Kennlinie beginnt zu fallen. Für größere Spannungen nimmt die Kennlinie die gewohnte Form an. Eine Tunneldiode hat also in Durchlassrichtung ein lokales Leitfähigkeits-Maximum. Sie zeichnen sich also dadurch aus, daß sie für bestimmte Spannungen einen negativen differenziellen Widerstand haben, also gilt<br />
:<math><br />
\frac{\mathrm{d}I(U)}{\mathrm{d}U} < 0<br />
</math><br />
In dem Bereich ist die Kennlinie fallend, und nicht wie sonst üblich überall mit der Spannung steigend.<br />
<br />
Bei Sperrpolung tritt ein kräftiger Stromfluss auf, d.h. Tunneldioden haben keine Sperrfähigkeit<br />
<br />
===Backward-Diode===<br />
[[Bild:Schaltsymbol_Backwarddiode.png|left|Schaltsymbol Backwars-Diode]]<br />
<br />
Spezialfall der Tunneldiode, die kein Leitfähigkeitsmaximum in Flussrichtung aufweist und in Sperrichtung leitet. Backward-Dioden sind geeignet zum Gleichrichten von Spannungen im Millivolt-Bereich, wobei die dann in Flussreichtung sperren und in "Sperrichtung" leiten.<br />
<br />
<hr style="visibility:hidden; clear:both"/><br />
<br />
===Kapazitätsdiode===<br />
[[Bild:Schaltsymbol_Kapazitätsdiode.png|Schaltsymbol Kapazitätsdiode]]<br />
Bei allen Dioden ist die Kapazität in Sperrichtung abhängig von der Spannung. Durch Spannung in Sperrichtung verbreitert sich die Verarmungsschicht am PN Übergang und die Kapazität wird kleiner. Bei Kapazitätsdioden wird auf eine definierte Kapazität und Spannungsabhängigkeit geachtet. Die typische Anwendung sind Radioempfänger und Spannungsgesteuerte Oszillatoren.<br />
<br />
===Laser-Diode===<br />
Laser-Dioden sind im Prinzip spezielle,hochwertige LEDs. Bei niedrigen Strömen verhalten sich Laserdioden auch wie normale LEDs. Ab einer Schwellstromstärke erhöht sich Effizienz und es wird kohärentes, fast ideal einfarbiges (monochromatisches) Laser-Licht erzeugt. Bei den gewöhnlichen Laserdioden tritt an 2 gegenüberliegenden Seiten aus einem kleinen Bereich an stark divergentes Lichtbündel aus. Das Licht der einen Seite wird oft von einer Photodiode im gleichen Gehäuse aufgefangen. Laser-dioden sind sehr empfindlich gegen elektrostatische Ladungen und zu hohe Ströme.<br />
Wegen der hohen Intensität und Leuchtdichte sind Laserdioden gefährlich für das Auge und entsprechende Sicherheitsvorschriften müssen eingehalten werden.<br />
<br />
===Röhrendiode===<br />
[[Bild:Schaltsymbol_Röhrendiode.png|left|Schaltsymbol Diode (Röhre)]]<br />
Die älteste Form der Diode. Eine Röhrendiode ist eine Elektronenröhre mit zwei Elektroden: Kathode und Anode. An der Kathode treten durch Glüh-, Photo oder Feldemmission Elektronen aus. Ist die Anode positiv gegenübder der Kathode, werden die Elektronen von der Kathode "abgesaugt" und es fliesst ein Strom. Ist die Anode negativ, fliesst kein Strom, da die Anode keine Elektroden emittieren kann.<br />
Die Kathode ist oft mit einem speziellen Material überzogen, das eine niedrige Austrittsenergie für Elektronen aufweist und zudem als Heizwendel ausgebildet. <br />
<br />
Bei Beleuchtung der Kathode können Ladungsträger durch den äusseren Photoeffekt gebildet werden und die Diode wird zu einer Stromquelle (Photodiode).<br />
<br />
== Schaltbeispiele ==<br />
<br />
===Freilaufdiode===<br />
[[Bild:Freilaufdiode.png|left]]<br />
Bei einer Freilaufdiode handelt es sich nicht um einen bestimmten Diodentyp, der Begriff bezeichnet vielmehr eine Diode, die wie gezeigt verschaltet ist. Damit der Strom durch die induktive Last (Motor, Relaisspule, etc) nach Abschalten der Spannung (Öffnen des Schalters) weiter fliessen kann bzw. Spannungsspitzen durch Induktion vermieden werden, wird antiparallel zur Stromflussrichtung durch die Last eine Diode angeschlossen. Die Freilaufdiode muß also wenigstens kurzzeitig den Laststrom verkraften. Wenn nicht nur gelegentlich, sondern schnell (z.B. für PWM)geschaltet wird, ist die Geschwindigkeit der Diode wichtig. Bei PWM-Schaltungen sind in der Regel nur schnelle Diode oder Shottkydioden als Freilaufdioden geeignet.<br />
<br />
Ist der Schalter geschlossen und wird die Last von aussen mit Energie versorgt, dann arbeitet die Diode in Sperrrichtung; sie muss also eine Sperrspannung haben, die mindestens so groß ist wie die maximale Spannung an der Last. Ist der Schalter offen, dann arbeitet die Diode in Vorwärtsrichtung und hält den Stromfluß durch die Last aufrecht und vermeidet dadurch auch induktive Spannungsspitzen, die ansonsten zur Zerstörung anderer Bauteile oder zu Problemen in der Schaltung führen könnten.<br />
<br />
<br style="clear:both"/><br />
<br />
==Siehe auch==<br />
* [[Leuchtdioden]]<br />
* [[Gleichrichter]]<br />
<br />
==Weblinks==<br />
* [http://geoastro.de/Quiz/Schaltung/Schaltung.html Dioden Lerntest]<br />
* [http://de.wikipedia.org/wiki/Diode Wikipedia]<br />
<br />
<br />
<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Feldeffekttransistor&diff=14648Feldeffekttransistor2009-03-15T07:18:38Z<p>Holzi: </p>
<hr />
<div>Der Feldeffekttransistor, meist als FET (Field Effect Transistor) bezeichnet, ist ein unipolarer [[Transistor]]. Unipolar deshalb, weil im Gegensatz des bipolaren Transistors, je nach Typ, entweder nur Löcher oder Elektronen am Stromtransport beteiligt sind. <br />
<br />
Der FET hat 3 Anschlüsse, Source (Zufluss, Quelle), Gate und Drain (Abfluss). Ein vierter Anschluss Bulk (Substrat) ist bei Einzeltransistoren i.d.R. mit Source verbunden und nicht extra herausgeführt.<br />
<br />
Die Steuerspannung zwischen Gate und Source erzeugt ein elektrisches Feld. Die dazugehörigen Ladungen beeinflussen die Leitfähigkeit des Source-Drain-Kanals des Feldeffekt-Transistors. Je nach benutzter Isolierung wird zwischen MOSFET und JFET (Junction- oder Sperrschicht-FET) unerschieden. <br />
<br />
Es gibt folgende Formen von FETs:<br />
* Sperrschicht-Feldeffekt-Transistor (JFET)<br />
* Metalloxidhalbleiter-Feldeffekt-Transistor (MOSFET)<br />
* dual Gate MOSFET : Spezialltype, hauptsächlich für HF<br />
* Schottky-Feldeffekt-Transistor (MESFET) - Spezialtype für HF<br />
* High Electron Mobility Transistor (HEMT) - Spezialtype für HF, > 1 GHz<br />
* Ionen-Sensitiver Feldeffekt-Transistor (ISFET) - als Sensor<br />
<br />
==Schaltsymbole==<br />
;N-MOSFET: [[Bild:Schaltsymbol NFET.png]]<br />
<br />
;P-MOSFET: [[Bild:Schaltsymbol PFET.png]]<br />
<br />
;N-Kanal JFET: [[Bild:Schaltsymbol JFETN.png]] [[Bild:Schaltsymbol JFETN2.png]]<br />
<br />
;P-Kanal JFET: [[Bild:Schaltsymbol JFETP.png]] [[Bild:Schaltsymbol JFETP2.png]]<br />
<br />
<br />
==JFET==<br />
JFETs nutzen einen in Sperrrichtung betriebenen p-n-Übergang, um das elektrische Feld zu bilden. Theoretisch kann er auch in Flussrichtung betrieben werden, was allerdings den Vorteil der leistungslosen Ansteuerung zunichte macht. Bei vielen JFETs gibt es keinen, oder wenig, Unterschied zwischen Drain und Source. Sie können also für beide Stromrichtungen benutzt werden.<br />
Ohne Gate-Source Spannung ist ein JFET leitend. Durch Spannung in Sperrichtung wird der Strom reduziert und erreicht bei der Abschnürrspannung schließlich 0. Bei kleinen Drain-Source Spannung verhält sich der JFET wie ein Spannungsgesteuerter Widerstand. Bei Drain-Source Spannung über etwa 1-2 V verhält sich ein JFET wie eine Spannungsgesteuerte Strombegrenzung. JFets werden hauptsächlich als Schalter für Signalspannungen und als schnelle hochohmige Verstärker eingesetzt. Es gibt viele Operationsverstärker mit JFET Eingängen.<br />
Gebräuchliche JFETS sind: BF245, BF256, 2N4416.<br />
<br />
==MOSFET==<br />
MOSFETs haben eine dünne Oxidschicht als Isolierung zwischen Gate und dem Kanal. MOSFETs können so hergestellt werden, dass sie ohne Gate-Source Spannung sperren (Enhancement-Typ) oder leiten (Depletion-Typ). Die einzeln erhältlichen MOSFETs sind aber ohne Gate-Source-Spannung fast alle sperrend (Enhancement-Typ). Ab einer Gate-Source-Spannung von z.B. +2 V (N-Channel FET) steigt die Leitfähigkeit bzw. der Drain-Source-Strom an. Für den maximalen Strom sind typisch 10 V oder bei sogenannten Logic-Level Mosfets ca. 4 V nötig. Die maximal zulässige Gate-Source-Spannung liegt je nach Typ bei etwa 20-30 V. Bei fast allen MOSFETs ist eine Diode zwischen Drain und Source enthalten. Es kann also Drain und Source hier nicht vertauscht werden, wenn mehr als 0,5 V Spannung anliegen. Die integrierte Diode kann bei Brückenschaltungen oft als Freilaufdiode genutzt werden. Besonders kleine MOSFETs sind empfindlich gegen elektrostatische Aufladungen.<br />
<br />
== Verwendung für Schaltanwendungen ==<br />
<br />
Mosfets werden oft für Schaltanwendungen verwendet, da sie grössere Leistungen als bipolare Transistoren schalten können und geringere Verluste haben. Anders als bipolare Transistoren können MOSFETs als Schalter (d.h. bei kleiner Drain-Source Spannung, oder ausgeschaltet) problemlos parallelgeschaltet werden. Ein weiterer, wesentlicher Vorteil ist, dass sie leistungslos geschaltet werden. Wenn das Gate einmal auf eine bestimmte Spannung aufgeladen wurde, dann ist keine weitere Steuerleistung nötig. Bei bipolaren Transistoren muss die ganze Zeit ein relativ hoher Basisstrom fliessen. Allerdings hat das Gate eine relativ hohe Kapazität (ca. 1 nF für einen 10 A MOSFET). Um die Verluste beim Schalten zu minimieren, muss das Gate schnell geladen und wieder entladen werden. Dafür ist ein relativ hoher Strom nötig. Aus diesem Grund gibt es fertige Treiberbausteine, wie den ICL7667, die das Gate sehr schnell umladen können. Ein schnelles Schalten des Mosfets ist insbesondere dann wichtig, wenn der Mosfet mit einer hohen Frequenz an- und ausgeschaltet wird (z.B. [[PWM]], Schaltnetzteile). <br />
<br />
Andererseits darf das Schalten auch nicht schneller erfolgen als der Rest der Schaltung es verträgt. Begrenzend sind hier z.B. ungewollte Induktivitäten, die Erhohlzeiten von Dioden und die Gefahr von Funkstörungen. Für eine definierte Schaltzeit wird oft ein kleiner Widerstand (ca. 100 Ohm) vor das Gate geschaltet. Wichtig ist der Widerstand besonders dann, wenn der Aufbau nicht für hohe Frequenzen ausgelegt ist, denn sonst besteht die Gefahr, dass es zwischenzeitlich zu HF-schwingungen und damit Funkstörungen kommt. <br />
<br />
In der Praxis werden wesentlich häufiger N-Kanal Mosfets als P-Kanal Mosfets verwendet. Das liegt daran, dass sich die Elektronen im Halbleiter leichter bewegen können als Löcher. Aus diesem Grund haben N-Kanal Mosfets einen geringeren RDS_ON und damit geringere Verluste. <br />
<br />
Die folgende Schaltung zeigt die Verwendung eines Mosfets zum Regeln eines Motors über [[PWM]]. Der eingezeichnete BS170 ist allerdings nur für kleine Lasten geeignet.<br />
<br />
[[Bild:fetschaltstufe.jpg|center]]<br />
<br />
== Bauform Beispiel ==<br />
<br />
[[Bild:fetbs170.gif|center]]<br />
<br />
<br />
[[Kategorie:Elektronik]]</div>Holzihttps://rn-wissen.de/wiki/index.php?title=Transistor&diff=14647Transistor2009-03-15T07:17:19Z<p>Holzi: </p>
<hr />
<div>Ein Transistor ist ein elektronisches Halbleiterbauelement. Ein Transistoren wird zum Schalten und Verstärken benutzt. Die Bezeichnung ''Transistor'' ist ein Kurzwort, das sich vom englischen ''Transfer Varistor'' ableitet und den Transistor als bei bipolaren durch Strom bzw. bei FETs durch Spannung steuerbaren Widerstand umschreibt. <br />
<br />
Transistoren werden in zwei Gruppen unterteilt:<br />
* Bipolare Transitoren<br />
* [[Feldeffekttransistor]]en (FETs)<br />
<br />
Bipolare Transistoren werden durch Stromfluss angesteuert. Die Anschlüsse des bipolaren Transistors sind ''Kollektor'', ''Basis'' und ''Emitter''. Ein kleiner Strom auf der Basis-Emitter-Strecke kann dabei einen großen Strom auf der Kollektor-Emitter-Strecke steuern. Es wird unter anderem auch zwischen NPN- und PNP-Transistoren unterschieden.<br />
<br />
Bei FETs werden die Anschlüsse als Gate (engl. Tor, Gatter), Drain (engl. Abfluss), Source (engl. Quelle) bezeichnet. Der Strom auf der Drain-Source-Strecke wird hier durch die Spannung zwischen Gate und Source gesteuert. Die Steuerung mit Gleichspannung erfolgt stromlos. Bei Steuerung mit Wechselspannung wird ein Strom fürs Umladen der Gate-Kapazität benötigt.<br />
<br />
{{Ausbauwunsch|<br />
}}<br />
<br />
== Funktionsprinzip ==<br />
<br />
[[Bild:Ib-Kennlinie, BC547.gif|thumb|Spannungs-Strom-Kennlinie der Basis-Emitter-Strecke]]<br />
Gehen wir zunächst von einem NPN-Transistor aus, dessen Emitter auf Masse liegt. Durch ihn können zwei Ströme fließen: Der Basis-Emitter-Strom (Kurz: I<sub>b</sub>) und der Collector-Emitter-Strom (Kurz: I<sub>c</sub>). Der Basisstrom I<sub>b</sub> ist der Steuerstrom. Die Spannungs-Strom-Kennlinie der Basis-Emitter-Strecke ähnelt einer Diodenkennlinie: Bis ca. 0,6V fließt kaum Strom, danach steigt die Stromstärke schnell an (siehe Grafik). Diese Kennlinie ist auch noch temperaturabhängig, bei höheren Temperaturen kann ein höherer Strom fließen. Wenn man nun eine Schwellenspannung (= ab dieser Spannung lässt die Basis Strom fließen, hier gehen wir von Silizium aus; bei Germanium würde die Schwellenspannung schon bei 0,35V sein) von 0,7V an die Basis anlegen würde, würde zuerst nur ein kleiner Strom fließen. Mit der Zeit würde sich der Transistor erwärmen, wodurch ein höherer Strom fließen kann. Dadurch wird jedoch auch wieder die Wärmeabgabe größer, ein Teufelskreis entsteht und irgendwann brennt der Transistor durch. Um das zu verhindern, benutzt man, je nachdem wie groß die Last ist, die am Transistor angeschlossen ist, Basis-Vorwiderstände in der Größenordnung von 220 Ohm bis 100 kOhm. Diese werden zwischen die Ansteuerung und die Basis des Transistors geschaltet und begrenzen den Strom, der durch die Basis fließen kann.<br />
[[Bild:Ic-Kennlinie, BC547.gif|thumb|Spannungs-Strom-Kennlinine der Collector-Emitter-Strecke]]<br />
Die Collector-Emitter-Strecke des Transistors hat eine Kennlinie, die zuerst in etwa linear ansteigt und dann bei einer bestimmten Stromstärke in eine fast waagrechte Gerade übergeht (siehe Grafik).<br />
Bei welcher Stromstärke die Gerade abknickt, hängt von dem Strom ab, der durch die Basis-Emitter-Strecke fließt. Je höher dieser ist, desto später knickt die Gerade ab, und desto größere Lasten kann man schalten. In einem begrenzten Bereich ändert sich der Basisstrom linear zum Collectorstrom. Die Basis-Emitter-Stromstärken betragen in der Grafik von unten nach oben 0mA, 5mA, 10mA, 15mA und 20mA.<br />
Das Verhältnis aus dem Strom, der auf der Collector-Emitter-Strecke fließen kann, und dem Strom, der dazu als Steuerstrom benötigt wird, nennt man Verstärkungsfaktor. Der Verstärkungsfaktor, der bei einem Transistor angegeben ist, ist jedoch eine rein theoretische Größe. Die Werte, die im Datenblatt angegeben sind, beziehen sich meistens auf eine Collector-Emitter-Spannung von 5V, bei höheren Lastströmen sinkt der Verstärkungsfaktor weiter. Für Schaltanwendungen sollte man daher von etwa der halben Stromverstärkung ausgehen, damit die Emitter-Collector-Spannung sicher klein bleibt. <br />
Wie groß man I<sub>b</sub> wählen muss, probiert man in einer Schaltungssimulation aus, oder berechnet es näherungsweise.<br><br><br />
Bei einem PNP-Transistor sind im Grunde alle Spannungen umgedreht. Der Emitter liegt nicht auf Masse, sondern auf Vcc (meist 5V). Die Basis muss auf einer niedrigeren Spannung liegen, beispielsweise 4,3V, damit der Transistor durchschaltet. Der Strom fließt aber weiterhin von + nach - (technische Stromrichtung angenommen)<br />
<br />
== Schaltsymbol und Anschlussbelegung ==<br />
[[Bild:Transistor.JPG|thumb|300px|{{FarbigerRahmen|<br />
'''Warnung:'''<br />
Es gibt ebenso Transistoren im TO-92 Gehäuse, deren Basis an der Seite liegt. <br />
Bevor du einen Transistor verwendest, solltest du auf jeden Falls sein Datenblatt gelesen haben<br />
bzw. dir sicher sein, wo sich welcher Anschluss befindet!<br />
}}]]<br />
<br />
[[Bild:Schaltsymbol NPN.png|thumb|250px|left|Schaltsymbol npn-Transistor. Der Pfeil zeigt von der Basis (p) zum Emitter (n)]] <br />
<br style="clear:left"/><br />
[[Bild:Schaltsymbol PNP.png|thumb|250px|left|Schaltsymbol pnp-Transistor. Der Pfeil zeigt vom Emitter (p) zur Basis (n)]] <br />
<br />
<br />
<br style="clear:both"/><br />
<br />
== Grundschaltungen ==<br />
=== Emitterschaltung ===<br />
==== Grundschaltung eines NPN-Transitors ====<br />
[[Bild:Emitterschaltung.gif|thumb|Grundschaltung der Emitterschaltung]]<br />
(1) Die Emitterschaltung besteht hauptsächlich aus dem Transistor, dem Kollektorwiderstand und dem Basis-Vorwiderstand. Ist an der Basis eine Spannung von unter 0,6V anlegt, ist der Transistor nicht leitend, also hochomig. Weil der hochomige Transistor einen höheren Widerstand als der Kollektorwiderstand aufweist fällt bei ihm die größte Spannung ab. Der Ausgang der Schaltung wird durch den Widerstand auf die positive Versorgungsspannung (Vcc) "gezogen". <br><br />
<br><br />
(2) Wenn man nun eine Spannung am Eingang anlegt, die größer als ca. 0,6V ist, fließt ein Strom durch die Basis des Transistors. Der Transistor wird leitend und zieht den Ausgang der Schaltung auf 0V (GND).<br><br />
Durch die Offsetspannung von 0,6V ist diese Schaltung nicht zum linearen Verstärken von Signalen geeignet. Die Schaltung kann nur als Schalter genutzt werden, sei es um die Flanken auf einem Signal zu verbessern (steiler zu machen) oder um Lasten zu schalten.<br><br />
<br><br />
In ersterem Fall muss man beachten, dass die Emitterschaltung das Signal invertiert, d.h. bei 0V am Eingang liegen 5V am Ausgang an und umgekehrt.<br />
In letzterem Fall wird die Last (beispielsweise eine Glühbirne) statt Rc angeschlossen. Sobald man nun eine Spannung an die Basis anlegt, wird der Transistor leitend und es kann ein Strom durch die Last fließen, die Lampe leuchtet.<br />
Bei großen Lasten benötigt der Transistor einen entsprechend hohen Basisstrom, der durch den Basis-Vorwiderstand eingestellt wird.<br />
<br />
==== Erweiterte Emitterschaltung ====<br />
[[Bild:Emitterschaltung, erweitert.gif|thumb|Emitterschaltung zum linearen Verstärken von Wechselspannungen]]<br />
Wenn man die Emitterschaltung zum linearen Verstärken eines Signals nutzen will, muss man sie noch ein wenig erweitern. An die Basis wird zusätzlich ein Pullup-Widerstand angeschlossen. Dieser sorgt dafür, dass der Transistor "vorgespannt" wird. Der Widerstand wird dabei gerade so groß gewählt, dass der Ausgang möglichst genau zwischen GND und der Versorgungsspannung liegt.<br><br />
Hinter den Ausgang und vor den Eingang müssen zusätzlich so genannte Koppelkondensatoren geschaltet werden. Diese sorgen am Eingang dafür, dass die angelegte Eingangsspannung die Vorspannung nicht zerstört und am Ausgang dafür, dass kein Gleichstrom durch die Last fließen kann. Dies ist vor allem bei Lautsprechern wichtig.<br><br />
Die Emitterschaltung kann in dieser Form sowohl negative als auch positive Wechselspannungen verstärken. Für Gleichspannungen ist sie nicht mehr geeignet, da die Koppelkondensatoren diesen sperren.<br><br />
Wenn man eine Wechselspannung anlegt, fließt zusätzlich zu dem Vorspannstrom ein Eingangsstrom, der den Transistor entweder leitender (positive Halbwelle) oder weniger leitend (negative Halbwelle) macht.<br><br />
In ersterem Fall wird der Kollektor des Transistors durch selbigen auf eine negativere Spannung gezogen. Durch den Koppelkondensator am Ausgang fließt dann ein Strom in Richtung des Kollektors, bis der Kondensator durch diesen weit genug aufgeladen ist.<br><br />
im anderen Fall wird der Transistor weniger leitend, der Kollektor des Transistors wird dann durch den Widerstand Rc auf eine positivere Spannung gezogen. Folglich fließt durch den Koppelkondensator am Ausgang ein Strom in Richtung der Last, allerdings auch hier nur solange der Kondensator nicht vollständig geladen ist.<br />
<br />
=== Kollektorschaltung ===<br />
[[Bild:Kollektorschaltung.gif|thumb|Kollektorschaltung mit NPN-Transistor]]<br />
Für eine Kollektorschaltung werden zunächst nur ein Transistor und ein Widerstand benötigt.<br><br />
Ohne Eingangsspannung leitet der Transistor nicht, der Ausgang liegt also auf 0V.<br><br />
Sobald man am Eingang eine Spannung anlegt, wird der Transistor jedoch leitend, die Ausgangsspannung wird größer. Gleichzeitig wird dadurch die Basis-Emitterspannung kleiner. Der Ausgang erreicht also maximal etwa die Eingangsspannung abzüglich der 0,7 Volt, die benötigt werden, damit auf der Basis-Emitterstrecke ein Strom fließen kann. Die Spannungsverstärkung ist folglich etwas kleiner als 1. Im Gegenzug besitzt die Kollektorschaltung eine sehr hohe Stromverstärkung und dadurch auch einen sehr hohen Eingangswiderstand. Die Kollektorschaltung wird auch als Emitterfolger bezeichnet.<br><br />
Bei dieser Schaltung kann auf den Basis-Vorwiderstand verzichtet werden, solange man am Eingang keine Spannung anlegt, die größer ist als die Versorgungsspannung. Der Strom durch die Basis reguliert sich durch die variable Emitterspannung selbst. Allerdings kann ein Basis-Vorwiderstand auch als Kurzschlussschutz dienen, da bei einem begrenzten Basisstrom auch der Kollektor-Emitterstrom begrenzt ist.<br />
<br />
=== Basisschaltung ===<br />
[[Bild:Pegelwandler.png|thumb|Pegelwandler für 3 V auf 5 V Logicpegel, mit NPN Transistor in Basisschaltung.]]<br />
In der Basisschaltung wird die Basis fest auf eine mittlere Spannung gelegt. Der Strom am Emitter dient als Eingang, der Strom am Kollektor als Ausgang. Wenn man den kleinen Basisstrom vernachlässigt, sind der Emitter- und Kollektorstrom gleich groß. Wenn der Widerstand (bzw. die Impedanz) an der Emitterseite niedriger als an der Kollektorseite ist, ergibt sich eine Spannungsverstärkung. Die Basisschaltung wird hauptsächlich in HF-Schaltungen benutzt. <br />
<br />
Eine weitere Anwedung sind Pegelwandler. Die Schaltung im Bild rechts dient dazu, ein Digitalsignal von einem IC mit 2-3 V Versorgung auf 5 V zu Verstärken. Wenn am Eingang mehr als etwa 1 V anliegen, sperrt der Transistor, und am Ausgang liegt die Spannung über den 1 K Widerstand. Wenn der Eingang auf GND Potential ist, ist der Transistor durchgeschaltet und der Ausgang liegt fast auf GND Potential. Der Basisstrom wird durch den 22 K Widerstand auf rund 0,2 mA begrenzt. Die Schaltung ist keine reine Basisschaltung, denn die Spannung an der Baisis ändert sich hier ein wenig.<br />
<br />
=== Darlingtonschaltung ===<br />
[[Bild:Darlington.png|thumb|Darlingtonschaltung (NPN)]]<br />
Wenn die Stromverstärkung eines einzelnen Transistors nicht ausreicht, können zwei Transistoren so zusammengeschaltet werden, dass der Emitter des ersten Transistors an die Basis des zweiten Transistors geht. Die Collectoren sind miteinander verbunden. Diese Schaltung verhält sich dann ganz ähnlich wie ein Transistor mit einer Stromverstärkung, die dem Produkt der beiden Stromverstärkungen entspricht. In einem Gehäuse zusammengefasst bezeichnet man diese Schaltung als Darlingtontransistor. Der im Bild gezeigte Widerstand kann auch weggelassen werden. Er macht die Schaltung schneller und reduziert den Leckstrom.<br />
<br />
=== Prinzipien ===<br />
==== Verstärkungsregelung ====<br />
Spannungsgegenkopplung:<br />
<br />
[[Bild:Spannungsgegenkopplung.png|thumb|Verstärker mit Spannungsgegenkopplung]]<br />
<br />
Die Verstärkung mit der Emitterschaltung ist von den Eigenschaften (besonders Verstärkungsfaktor) des verwendeten Transistors abhängig und damit auch temperaturabhängig. Außerdem ist die Verstärkung nicht besonders linear.<br />
Die Schaltung im Bild zeigt einen Weg eine stabilere Verstärkung zu erzeugen. Über den Widerstand R2 wirkt die Ausgangsspannung der Eingangsspannung entgegen. <br />
Diese Schaltungprinzip wird daher Spannungsgegenkopplung genannt.<br />
Die Verstärkung ist in diesem Fall auf -R2/R3 = -5 fach festgelegt. Damit die Gegenkopplung wirken kann, muss die Verstärkung ohne die Gegenkopplung wesentlich höher sein, als sie durch die Widerstände eingestellt wird. Durch die Gegenkopplung reduziert sich die Verstärkung zugunsten einer besseren Linearität und Stabilität. <br />
<br />
<br />
Stromgegenkopplung:<br />
<br />
[[Bild:Stromgegenkopplung.png|thumb|Verstärker mit Stromgegenkopplung]]<br />
<br />
Eine andere Form der Gegenkopplung zeigt das Bild rechts. Hier ist die Rückkopplung nicht so klar zu sehen, denn die Rückkopplung wirkt nicht auf die Basis, sondern auf den Emitter. Der Kollektorstrom hängt vom Basistrom ab und damit von der Spannung zwischen Basis und Emitter. Eine höhere Spannung am Emitter ist daher gleichbedeutend mit einer niedrigeren Spannung an der Basis und weniger Strom. Durch Strom durch dem Kollektor fleißt auch durch den Widerstand am Emitter, erhöht dort die Spannung und wirkt so einem höheren Strom entgegen. Man nennt diese Schaltung daher auch Stromgegenkopplung. Auch hier reduziert sich die Verstärkung auf etwa -R2/R3.<br />
<br />
=== Logische Interpretation der Schaltungen ===<br />
====Die NOT-Verknüpfung====<br />
<br />
[[Bild:NOT Gatter.JPG]]<br />
<br />
Diese einfache Schaltung, bestehend aus einem NPN-Transistor und zwei Widerständen, invertiert das Eingangssignal, sodass aus beispielsweise +5V (oder logisch 1) 0V (oder logisch 0) erzeugt werden.<br />
Die daraus resultierende Wertetabelle sieht folgendermaßen aus:<br />
<br />
<div align = "center"><br />
{| {{Blauetabelle}}<br />
| '''Eingang'''<br />
| '''Ausgang'''<br />
|-<br />
| 0V<br />
| +5V<br />
|-<br />
| +5V<br />
| 0V<br />
|}<br />
</div><br />
Wenn also an der Transistorbasis +5V angelegt werden (+0,7V reichen meistens auch schon), dann schaltet der Transistor durch und am Ausgang liegen 0V an. Der Strom, der nun durch den Transistor fließt, wird durch den Widerstand R<sub>2</sub> begrenzt. Wird dieser Widerstand weggelassen, dann wird durch den entstehenden Kurzschluss der Transistor unweigerlich zerstört.<br />
Legt man nun am Eingang 0V an, so sperrt der Transistor und am Ausgang liegen +5V an. <br />
<br />
<br />
Der Basisstrom wird durch den Widerstand R<sub>1</sub> bestimmt. Ein kleiner Widerstand beschleunigt die Schaltgeschwindigkeit des Transistors, ein großer ermöglicht die Ansteuerung auch mit kleinen Strömen.<br />
<br />
====Die NAND Verknüpfung====<br />
<br />
[[Bild:NAND_Gatter.jpg]]<br />
<br />
Die NAND ('''N'''ot'''AND''', d.h. die invertierte Form einer AND Verknüpfung) Verknüpfung besteht aus zwei Transistoren und damit auch zwei Eingängen. Es gibt auch NAND Verknüpfungen mit mehr Transistoren und folglich auch mehr Eingängen, diese sind im Aufbau aber sehr ähnlich zu der vorgestellten Grund-NAND Verknüpfung.<br />
Schauen wir uns zunächst die Wertetabelle an:<br />
<div align = "center"><br />
{| {{Blauetabelle}}<br />
| '''Eingang 1 (E1)'''<br />
| '''Eingang 2 (E2)'''<br />
| '''Ausgang (A1)'''<br />
|-<br />
| 0V<br />
| 0V<br />
| +5V<br />
|-<br />
| +5V<br />
| 0V<br />
| +5V<br />
|-<br />
| 0V<br />
| +5V<br />
| +5V<br />
|-<br />
| +5V<br />
| +5V<br />
| 0V<br />
|}<br />
</div><br />
<br />
Wie kommt es nun zu dieser Werte- oder auch Wahrheitstabelle?<br />
<br />
Wenn an den beiden Eingängen 0V anliegen, dann schaltet keiner der beiden Transistoren durch und der Ausgang ist über den Widerstand R<sub>3</sub> mit +5V verbunden.<br />
Wechselt nun einer der beiden Eingänge auf 1, dann schaltet auch nur einer der beiden Transistoren durch und am Ausgang liegen immer noch +5V an. Werden nun aber beide Eingänge mit +5V verbunden, dann schalten beide Transistoren durch und der Ausgang ist leitend mit Masse verbunden.<br />
<br />
Die Widerstände (R<sub>1</sub>, R<sub>2</sub>, R<sub>3</sub>) haben die gleiche Funktion wie auch in der NOT Verknüpfung.<br />
<br />
== Transistor-Kennwerte ==<br />
Die Transistorkennwerte sind grundsätzlich in Grenzdaten und Kenndaten unterteilt. Grenzwerte dürfen auf keinen Fall überschritten werden, da eine Zerstörung des Transistors möglich ist. Eigenschaften eines Transistors werden als Kenndaten angegeben, die das Verhalten in bestimmten Arbeitspunkten kennzeichnen.<br />
<br />
==Grenzwerte für Sperrschichttemperatur==<br />
Durch die Verlustleistung bei Dauerbetrieb entsteht in der Sperrschicht Wärme, durch die sich die Sperrschichttemperatur erhöht. Die Sperrschichttemperatur '''T<sub>J</sub> ''' , darf bestimmte Werte nicht überschreiten, da sich sonst die Eigenschaften des Transistors stark verändern würden (z.B. sehr hoher Leckstrom), was oft eine Zerstörung zur Folge hat. Die maximale Temperatur hängt vom Halbleitermaterial ab.<br />
<br />
'''T<sub>J</sub> ''' : 90°C Germaniumtransistoren<br />
<br />
'''T<sub>J</sub> ''' : 150 - 200°C Siliziumtransistoren<br />
<br />
==Zulässiger Arbeitsbereich==<br />
In Transistorschaltungen dürfen bestimmte Grenzwerte nicht überschritten werden. Der zulässige Arbeitsbereich einer Transistorschaltung wird somit durch den Kollektorstrom '''I<sub>c</sub> ''', durch die Kollektor - Emitterspannung '''U<sub>CE</sub> ''' und durch die Verlustleistung '''P<sub>tot</sub> ''' begrenzt. Wird der Transistor außerhalb des erlaubten Arbeitsbereiches betrieben wird der Transistor zerstört. <br />
Die zulässige Verlustleistung wird bei kleinen Transistoren oft für 25°C Umgebungstemperatur angegeben. Bei Leistungstransistoren wird oft 25°C Gehäusetemperatur vorausgesetzt. Bei höheren Temperaturen oder schlechterer Kühlung, was fast immer der Fall ist, reduziert sich die zulässige Verlustleistung. In den Datenblättern findet man dazu Zahlenwerte und teilweise Diagramme zur zulässigen Verlustleistung als Funktion der Umgebungstemperatur. Je nach Wärmewiderstand '''R<sub>Th</sub> ''' eines ggf. vorhandenen Kühlkörpers ergeben sich unterschiedliche Kurven.<br />
<br />
<br />
==Kenndaten==<br />
Von den Kenndaten ist im wesentlichen der Stromverstärkungsfaktor ('''h<sub>ef</sub> ''') wichtig. Für Schaltanwendungen interessiert noch die Kollektor-Emitter-Sättigungsspannung. Die anderen Kenndaten sind im wesentlichen für fortgeschrittene Schaltungen wichtig.<br />
<br />
<br />
''Autor: ZwieBack - Wiki Konvertierung Frank''<br />
<br />
==Siehe auch==<br />
* [[Feldeffekttransistor|FET]]<br />
<br />
==Weblinks==<br />
* [http://www.nano.physik.uni-muenchen.de/elektronik/nav/k5t2.html Grundlagen Transistorschaltungen] <br />
<br />
<br />
[[Kategorie:Elektronik]]<br />
[[Kategorie:Grundlagen]]</div>Holzi