<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="de">
		<id>https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=SprinterSB</id>
		<title>RN-Wissen.de - Benutzerbeiträge [de]</title>
		<link rel="self" type="application/atom+xml" href="https://rn-wissen.de/wiki/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=SprinterSB"/>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Spezial:Beitr%C3%A4ge/SprinterSB"/>
		<updated>2026-04-11T12:25:48Z</updated>
		<subtitle>Benutzerbeiträge</subtitle>
		<generator>MediaWiki 1.25.1</generator>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Inline-Assembler_in_avr-gcc&amp;diff=25359</id>
		<title>Inline-Assembler in avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Inline-Assembler_in_avr-gcc&amp;diff=25359"/>
				<updated>2014-10-25T11:38:34Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Quellen */ linkfix&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In C versteht man unter '''Inline Assembler''' die Möglichkeit, direkt Assembler-Befehle in den Code einzufügen bzw. die eingefügten Assembler-Befehle selbst. &lt;br /&gt;
&lt;br /&gt;
Neben den einzufügenden Befehlen muss beschrieben werden, welche Nebeneffekte die Befehle auf die Maschine haben und wo/wie Parameter übergeben werden, bzw. wie die Zuordnung von Variablen zu den Registern ist. Diese Beschreibung ist notwendig weil der [[Compiler]] keine Vorstellung davon hat, welche Effekte und Nebenwirkungen die Assembler-Kommandos auf Register, Variablen und Speicher haben, denn der Assembler-Schnippsel ist für den Compiler lediglich eine &amp;quot;Black Box&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Obgleich das dazu verwendete Schlüsselwort &amp;lt;tt&amp;gt;__asm&amp;lt;/tt&amp;gt; zum ANSI-C-Standard gehört, ist dies in jedem C-Compiler anders implementiert. Das gilt insbesondere für die Schnittstellenbeschreibung Variablen/Register. Dieser Artikel bezieht sich auf den Inline Assembler von [[avr-gcc]]. &lt;br /&gt;
Viele Erklärungen aus diesem Artikel sind auch gültig für Inline-Assembler anderer C-Compiler der  [[gcc]]-Familie. Instruktionen und Registerklassen werden sich aber unterscheiden, weil diese natürlich abhängig sind vom verwendeten Controller bzw. der Controller-Familie.&lt;br /&gt;
&lt;br /&gt;
=Assembler oder Inline-Assembler?=&lt;br /&gt;
;Assembler: Längere und komplexere Code-Stücke sind komfortabler direkt in Assembler auszudrücken. Dazu schreibt man Assembler-Funktionen und ruft diese von C aus auf. Natürlich können auch C-Funktionen von Assembler aus aufgerufen werden. Zudem kann man im Assembler den C-Präprozessor nutzen, was bei Inline-Assembler nur auf C-Ebene geht. Der Build-Prozess wird allerdings komplizierter, da extra asm-Dateien übersetzt werden müssen. Ein typischer Fall ist es, eine komplette ISR in Assembler zu schreiben.&lt;br /&gt;
;Inline-Assembler: Mit Inline-Assembler kann man kleine Assembler-Stückchen direkt in den C-Code einbetten. Es muss dann keine Assembler-Funktion aufgerufen werden. Dies kann von der Registerverwendung her deutlich günstiger sein, da [[gcc]] genau weiß, welche Register gebraucht werden und welche nicht. &lt;br /&gt;
:Eine (Assembler-)Funktion ist hingegen eine Black Box, bei der von der Standard-[[avr-gcc/Interna#Registerverwendung|Registerverwendung]] ausgegangen werden muss, auch wenn weniger Register in der Funktion verwendet werden. Ein Funktionsaufruf bedeutet also meistens einen Laufzeit-Overhead im Vergleich zu einem Inline-Code. &lt;br /&gt;
:Bei mehrfacher Verwendung einer längeren Codesequenz ist eine Funktion jedoch sparsamer im [[Flash]]-Verbrauch. Legt man eine Funktion als C-Funktion an und ihren Body als Inline-Assembler (eine s.g. Stub-Funktion, von engl. ''Stub'' = Stumpf), dann übernimmt gcc das Verwalten von Funktions-Argumenten, return-Wert, etc. und man brauch sich nicht selber um die Aufruf-Konvention zu kümmern. Auch innerhalb einer Funktion kann C mit Assembler gemischt werden.&lt;br /&gt;
:Ein Vorteil von Inline-Assembler ist, daß eine C-Funktion, die Inline-Assembler enthält, vom C-Compiler [[C-Tutorial#Inlining|geinlinet]] werden kann. Dies ist mit einer reinen Assembler-Funktion nicht möglich.&lt;br /&gt;
&lt;br /&gt;
=Begriffe=&lt;br /&gt;
;Assembler-Template: Das Template (''Schablone'') ist ein statischer, konstanter String im Sinne von C. Es enthält die Assembler-Befehle sowie Platzhalter, in deren Stelle später die Operanden treten&lt;br /&gt;
;Constraint: Die Constraints (''Nebenbedingungen'') beschreiben Einschränkungen an die zu verwendeten Register. Dies ist notwendig, da nicht alle Maschinenbefehle auf alle Register anwendbar sind&lt;br /&gt;
;Clobber-List: Das ist eine Liste von Registern, deren Inhalt durch den Inline-Assembler zerstört wird&lt;br /&gt;
&lt;br /&gt;
=Syntax und Semantik=&lt;br /&gt;
Das Schlüsselwort, um eine Inline-Assembler Sequenz einzuleiten, ist &amp;lt;tt&amp;gt;__asm&amp;lt;/tt&amp;gt; (ANSI). Oft ist auch &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;__asm__&amp;lt;/tt&amp;gt; verwendbar. Um zu kennzeichnen, daß die Sequenz keinesfalls wegoptimiert werden darf &amp;amp;ndash; etwa dann, wenn der Assembler keine Wirkung auf C-Variablen hat &amp;amp;ndash; wird dem &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; ein &amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;__volatile&amp;lt;/tt&amp;gt; nachgestellt. Danach folgen in runden Klammern die durch &amp;lt;tt&amp;gt;''':'''&amp;lt;/tt&amp;gt; getrennten Abschnitte des Inline-Assemblers:&lt;br /&gt;
 asm volatile ([[#Assembler-Template|asm-template]] : [[#Operanden und Constraints|output-operand-list]] : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]]);&lt;br /&gt;
&lt;br /&gt;
Abschnitte, die leer sind, können auch weggelassen werden, wenn dahinter kein weiterer Abschnitt folgt:&lt;br /&gt;
 asm volatile (asm-template);&lt;br /&gt;
&lt;br /&gt;
Oder, wenn weder Input- noch Output-Operanden gebraucht werden, aber Register oder Speicher verändert werden:&lt;br /&gt;
 asm volatile (asm-template ::: clobber-list);&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen |&lt;br /&gt;
Aus Compiler-Sicht werden die Assembler-Befehle im Template parallel, also ''gleichzeitig'' ausgeführt! Dies ist zu bedenken, wenn Register sowohl als Input als auch als Output verwendet werden.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
Ab Version 4.5 kennt GCC &amp;lt;tt&amp;gt;asm goto&amp;lt;/tt&amp;gt;, mit dem ausgedrückt werden kann, dass der Codefluß des Assembler-Teils u.U. zu einem Stück C-Code springt:&lt;br /&gt;
 asm goto ([[#Assembler-Template|asm-template]] : {{comment|Leer}} : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]] : [[#asm goto mit C-Labels|C-labels]]);&lt;br /&gt;
&lt;br /&gt;
== Assembler-Template ==&lt;br /&gt;
&lt;br /&gt;
Im Template stehen die durch Zeilenumbrüche getrennten Assembler-Befehle. Das Template kann zudem &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;-Ausdrücke als Platzhalter enthalten, welche durch die Operanden ersetzt werden. Dabei bezieht sich &amp;lt;tt&amp;gt;%0&amp;lt;/tt&amp;gt; auf den ersten Operanden, &amp;lt;tt&amp;gt;%1&amp;lt;/tt&amp;gt; auf den zweiten Operanden, etc. &lt;br /&gt;
Die Operanden selbst werden im zweiten und dritten Abschnitt des Templates als Komma-getrennte Liste angegeben.&lt;br /&gt;
Diese Ersetzung findet jedoch nur dann statt, wenn das asm nicht nur aus einem String besteht:&lt;br /&gt;
 asm (&amp;quot;10% mehr&amp;quot;);    {{comment|&amp;quot;10% mehr&amp;quot;}}&lt;br /&gt;
 asm (&amp;quot;10%% mehr&amp;quot; :); {{comment|&amp;quot;10% mehr&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
Ein Platzhalter kann zusätzlich einen einbuchstabigen Modifier enthalten, um den Operanden in printf-ähnlicher Manier in einem speziellen Format darzustellen. Wird z.B. ein Wert ab Register &amp;lt;tt&amp;gt;r28&amp;lt;/tt&amp;gt; (dem Y-Register) gehalten, dann wären folgende Ersetzungen denkbar (als erstes Argument):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r28&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%A0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r28&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%B0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r29&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%C0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r30&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%D0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%a0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;y&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Falle enthält das Templater nur einen Befehl:&lt;br /&gt;
 &amp;quot;nop&amp;quot;&lt;br /&gt;
oder sogar garkeinen Befehl oder lediglich einen Kommentar:&lt;br /&gt;
 &amp;quot;; ein Kommentar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: asm-Platzhalter und ihre Modifier, Sonderzeichen'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Platzhalter || wird ersetzt durch || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%''n''&amp;lt;/tt&amp;gt; || Wird ersezt durch Argument &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; mit &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; = 0...9&lt;br /&gt;
| &lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%A''n''&amp;lt;/tt&amp;gt; || das erste (untere) Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 0...7)&lt;br /&gt;
|align=&amp;quot;center&amp;quot; rowspan=&amp;quot;4&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%B''n''&amp;lt;/tt&amp;gt; || das zweite Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 8...15)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%C''n''&amp;lt;/tt&amp;gt; || das dritte Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 16...23)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%D''n''&amp;lt;/tt&amp;gt; || das vierte Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 24...31)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%a''n''&amp;lt;/tt&amp;gt; || Ausgabe des Arguments als Adress-Register,&amp;lt;br/&amp;gt;also als &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;. Erlaubt zusammen mit Constraint &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%i''n''&amp;lt;/tt&amp;gt; || Ab 4.7. Ausgabe einer RAM-Adresse als I/0-Adresse. Beispiel: &amp;lt;tt&amp;gt;0x30&amp;lt;/tt&amp;gt; wird auf Xmega-Controllern als &amp;lt;tt&amp;gt;0x30&amp;lt;/tt&amp;gt; ausgegeben und auf nicht-Xmega als &amp;lt;tt&amp;gt;0x10&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%r''n''&amp;lt;/tt&amp;gt; || Ab 4.8. Ausgabe eines Registers ohne die Register-Präfix &amp;quot;r&amp;quot;.  Damit kann per Inline-Assembler auf 64-Bit Variablen zugegriffen werden, z.B. kann mit &amp;lt;tt&amp;gt;&amp;quot;clr %r0+7&amp;quot;&amp;lt;/tt&amp;gt; das High-Byte gelöscht werden.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%T''n''%T''m''&amp;lt;/tt&amp;gt; || Ab 4.7. Gibt einen Doppel-Operanden aus wie er zum Beispiel in BLD oder BST benötigt wird, d.h. durch ein Komma getrennte Register- und Bitnummer. Das erste &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt; erhält ein Register und speichert es zwischen bis zum nächsten &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt;, das die konstante Bitnummer ''m'' enthält. Die Ausgabe erfolgt erst mit dem zweiten &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt;: Beispielsweite kann durch folgende Zeile das High-Bit von ''var'' gelöscht werden:&lt;br /&gt;
 asm (&amp;quot;clt $ bld %T[v]%T[b]&amp;quot; : [v] &amp;quot;+r&amp;quot; (var) : [b] &amp;quot;n&amp;quot; (8*(sizeof var)-1));&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%T''n''%t''m''&amp;lt;/tt&amp;gt; || Ab 4.7. Funktioniert wie &amp;lt;tt&amp;gt;%T''n''%T''m''&amp;lt;/tt&amp;gt;, es wird aber nur das zum Bit&amp;amp;nbsp;''m'' gehörende Register ausgegeben, d.h. weder Komma noch Bitnummer.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%x''n''&amp;lt;/tt&amp;gt; || Ab 4.5. Gibt ein Label ohne Operand-Modifier &amp;lt;tt&amp;gt;gs()&amp;lt;/tt&amp;gt; aus.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%~&amp;lt;/tt&amp;gt; || wird auf AVR mit Flash bis max. 8kiByte durch ein &amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt; ersetzt, ansonsten bleibt es leer.&amp;lt;br/&amp;gt;Zum Aufbau von Sprungbefehlen, etwa &amp;quot;&amp;lt;tt&amp;gt;%~call foo&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%!&amp;lt;/tt&amp;gt; || Ab 4.4. Wird auf AVR mit Flash ab 128kiByte durch ein &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ersetzt, ansonsten bleibt es leer.&amp;lt;br/&amp;gt;Zum Aufbau von indirekten Sprungbefehlen, etwa &amp;quot;&amp;lt;tt&amp;gt;%!icall&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%=&amp;lt;/tt&amp;gt; || eine für dieses asm-Template und die Übersetzungseinheit eindeutige Zahl.&amp;lt;br/&amp;gt;Zum Aufbau  lokaler Sprungmarken.&lt;br /&gt;
| &lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Sequenz || wird ersetzt durch Sonderzeichen || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%%&amp;lt;/tt&amp;gt; || das &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;-Zeichen selbst&lt;br /&gt;
|&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\n&amp;lt;/tt&amp;gt; || ein Zeilenumbruch zum Trennen mehrerer asm-Befehle/Zeilen&lt;br /&gt;
| &lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;$&amp;lt;/tt&amp;gt; || trennt mehrere Befehle in der gleichen Zeile&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\t&amp;lt;/tt&amp;gt; || ein TAB, zur Übersichtlichkeit im erzeugten asm ||&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\&amp;quot;&amp;lt;/tt&amp;gt; || ein &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; wird eingefügt ||&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\\&amp;lt;/tt&amp;gt; || das &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;-Zeichen selbst ||&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Kommentar || Beschreibung || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;; ''Text''&amp;lt;/tt&amp;gt; || einzeiliger Kommentar bis zum Ende des Templates bzw. nächsten Zeilenumbruch&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;/* ''Text'' */&amp;lt;/tt&amp;gt; || mehrzeiliger Kommentar wie in C ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Operanden und Constraints ==&lt;br /&gt;
&lt;br /&gt;
Ein Operand besteht aus der Angabe des Constraint-Strings (also der Registerklasse und Kennzeichnung, ob es sich um einen Output-Operanden handelt) und dahinter in runden Klammern der C-Ausdruck, der in Register der angegebenen Klasse geladen werden soll. Die Operanden werden mit 0 beginnend von links nach rechts durchnumeriert und über diese Nummer angesprochen, um sie ins Assembler-Schnippsel einzufügen.&lt;br /&gt;
&lt;br /&gt;
Mehrere Input- bzw. Output-Operanden werden durch Komma getrennt.&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: Constraints und ihre Bedeutung'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Constraint || Register || Wertebereich&lt;br /&gt;
|rowspan=&amp;quot;14&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
! Constraint || Konstante || Wertebereich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;||einfache obere Register||&amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r23&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;G&amp;lt;/tt&amp;gt;||Floatingpoint-Konstante ||&amp;lt;tt&amp;gt;0.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;||Pointer-Register ||&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;||Konstante, entspricht &amp;lt;tt&amp;gt;&amp;quot;sn&amp;quot;&amp;lt;/tt&amp;gt; ||&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;d&amp;lt;/tt&amp;gt;||obere Register ||&amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;s&amp;lt;/tt&amp;gt;||symbolischer Wert || &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt;||Pointer-Register ||&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;||Wert bekannt zur Compilezeit ||&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;||untere Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r15&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;||positive 6-Bit-Konstante ||0...63&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;q&amp;lt;/tt&amp;gt;||Stack-Pointer ||&amp;lt;tt&amp;gt;SPH:SPL&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;J&amp;lt;/tt&amp;gt;||negative 6-Bit Konstante ||&amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;63...0&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;||ein Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;M&amp;lt;/tt&amp;gt;||8-Bit Konstante ||0...255&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;t&amp;lt;/tt&amp;gt;||Scratch-Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot; |&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;w&amp;lt;/tt&amp;gt;||obere Register-Paare ||&amp;lt;tt&amp;gt;r24&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r26&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r28&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r30&amp;lt;/tt&amp;gt;&lt;br /&gt;
!{{Hintergrund1}}| Constraint ||{{Hintergrund1}}| Memory ||{{Hintergrund1}}| Wertebereich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;||Pointer-Register X ||&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r27:r26&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|&amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt;|| Memory || &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;||Pointer-Register Y ||&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r29:r28&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot; rowspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;||Pointer-Register Z ||&amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r31:r30&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;9&amp;lt;/tt&amp;gt;||colspan=&amp;quot;2&amp;quot;|Identisch mit dem angegebenen Operanden&amp;lt;br/&amp;gt;Wird verwendet, wenn ein Operand sowohl als Input&amp;lt;br/&amp;gt;als auch als Output dient, um sich auf diesen&amp;lt;br/&amp;gt;Operanden zu beziehen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: Constraint Modifier'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Modifier || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; || der Operand ist Output-Operand&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; || diesen Operanden ''nicht'' als Input-Operanden verwenden,&amp;lt;br/&amp;gt;sondern nur als Output-Operand&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; || dieser Operanden ist Input- und Output-Operand&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Input-Operand könnte also so aussehen, wobei &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; eine C-Variable ist. Als Register dient ein (je nach Typ von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; auch mehrere) obere Register, irgendwo von &amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt; (Constraint &amp;lt;tt&amp;gt;&amp;quot;d&amp;quot;&amp;lt;/tt&amp;gt;):&lt;br /&gt;
 &amp;quot;d&amp;quot; (foo)&lt;br /&gt;
&lt;br /&gt;
In den Klammern kann ein beliebiger, gültiger C-Ausdruck stehen, der beim folgenden Beispiel in irgendeinem Register landet (Constraint &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot;&amp;lt;/tt&amp;gt;), ohne weitere Einschränkung an das Register:&lt;br /&gt;
 &amp;quot;r&amp;quot; ((foo &amp;gt;= 0) ? foo : -foo)&lt;br /&gt;
&lt;br /&gt;
Um einen Operanden als Output-Operanden zu kennzeichnen, wird dem Constraint ein &amp;lt;tt&amp;gt;&amp;quot;=&amp;quot;&amp;lt;/tt&amp;gt; vorangestellt.&lt;br /&gt;
Soll &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; ein Output-Operand sein, der in den Registern &amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r15&amp;lt;/tt&amp;gt; landen soll (Constraint &amp;lt;tt&amp;gt;&amp;quot;l&amp;quot;&amp;lt;/tt&amp;gt;, sieht es so aus. Dabei muss &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; ein sogenannter Lvalue sein, also ein Wert, dem etwas zugewiesen werden kann:&lt;br /&gt;
 &amp;quot;=l&amp;quot; (foo)&lt;br /&gt;
&lt;br /&gt;
Ist &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; sowohl Input als auch Output, schreibt man &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Output- und als Input-Operand hin. In der Input-Constraint bezieht man sich dann auf die Operanden-Nummer von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt;. Hier ein komplettes Beispiel, das die Nibbles von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; tauscht. Weil &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; auf alle Register anwendbar ist, kann als Registerklasse &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot;&amp;lt;/tt&amp;gt; genommen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char foo;&lt;br /&gt;
...&lt;br /&gt;
asm (&amp;quot;swap %0&amp;quot; : &amp;quot;=r&amp;quot; (foo) : &amp;quot;0&amp;quot; (foo));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Input-Operand soll im gleichen Register liegen wie &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Output-Operand. Daher wird als Constraint &amp;lt;tt&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/tt&amp;gt; angegeben, d.h. es wird ins gleiche Register geladen wie der Operand Numero&amp;amp;nbsp;0 &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot; (foo)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Benannte Constraints ===&lt;br /&gt;
&lt;br /&gt;
Um das Assembler-Schnippsel besser lesbar zu halten, kann man Constraints einen Namen geben:&lt;br /&gt;
 asm (&amp;quot;swap %[bar]&amp;quot; : [bar] &amp;quot;+r&amp;quot; (foo));&lt;br /&gt;
Damit ist der Assembler auch unabhängig von der Reihenfolge der Operanden. Das macht die Anpassung, wenn ein neuer Operand hinzukommt, wesentlich einfacher und den Schnippsel zudem besser lesbar. &lt;br /&gt;
&lt;br /&gt;
Hier wird &amp;lt;tt&amp;gt;bar&amp;lt;/tt&amp;gt; als Alias für die C-Variable &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; benutzt; es könnte aber auch jeder andere gültige C-Bezeichner sein, also insbesondere auch &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Instruktionen und Constraints ===&lt;br /&gt;
&lt;br /&gt;
Die folgende Tabelle enhält eine Auflistung von AVR-Instruktionen und dazu passende Argumente bzw. Constraints. Nicht alle Shorthands sind in der Tabelle enthalten, so ist &amp;quot;&amp;lt;tt&amp;gt;clr Rn&amp;lt;/tt&amp;gt;&amp;quot; nur eine Abkürzung für &amp;quot;&amp;lt;tt&amp;gt;eor Rn, Rn&amp;lt;/tt&amp;gt;&amp;quot;, ähnliches gilt für den Zoo von Instruktionen rund um das SREG wie  branch, bit set, bit clear, etc., die im Endeffekt auf nur vier Instruktionen abbilden. Instruktionen wie &amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt;, die keine Argumente brauchen, sind ebenfalls nicht in der Tabelle enthalten. Gleiches gilt für den Krypto-Befehl &amp;lt;tt&amp;gt;des&amp;lt;/tt&amp;gt;, für die keine Constraint verfügbar ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;quot;load&amp;quot;&amp;lt;/tt&amp;gt; ist ein &amp;lt;tt&amp;gt;&amp;quot;load from SRAM&amp;quot;&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;quot;store&amp;quot;&amp;lt;/tt&amp;gt; ist &amp;lt;tt&amp;gt;&amp;quot;store to SRAM&amp;quot;&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+'''Tabelle: Übersicht AVR-Instruktionen und passende Constraints'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Mnemonic || Constraint ||Bedeutung ||rowspan=&amp;quot;35&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
!Mnemonic || Constraint ||Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;adc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || add with carry&lt;br /&gt;
| &amp;lt;tt&amp;gt;add&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || add&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;adiw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;w,I&amp;lt;/tt&amp;gt; || add immediate to word&lt;br /&gt;
| &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || and&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;andi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || and with immediate &lt;br /&gt;
| &amp;lt;tt&amp;gt;asr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || arithmetic shift right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;bclr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;   || bit clear in SREG&lt;br /&gt;
| &amp;lt;tt&amp;gt;bld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt;  || bit load from T&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;brbc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,label&amp;lt;/tt&amp;gt; || branch if bit in SREG clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;brbs&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,label&amp;lt;/tt&amp;gt; || branch if bit in SREG set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;bset&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;  || bit set in SREG&lt;br /&gt;
| &amp;lt;tt&amp;gt;bst&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || bit store from T&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cbi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || clear bit in I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;com&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || complement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cp&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || compare&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || compare with carry&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || compare against immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpse&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;|| compare, skip if equal&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;dec&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;[e]lpm&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,z&amp;lt;/tt&amp;gt;|| load from program memory&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;eor&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || exclusive-or&lt;br /&gt;
| &amp;lt;tt&amp;gt;fmul*&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;a,a&amp;lt;/tt&amp;gt; || fractional multiply&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt;  || input from I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;inc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;lac&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;lat&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and toggle&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;las&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and set&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,e&amp;lt;/tt&amp;gt;   || load indirect&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,e+&amp;lt;/tt&amp;gt;  || load indirect, post-increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,-e&amp;lt;/tt&amp;gt;  || load indirect, pre-decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,b+I&amp;lt;/tt&amp;gt; || load indirect with displacement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ldi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || load immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;lds&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,label&amp;lt;/tt&amp;gt; || load direct from SRAM&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;t,z&amp;lt;/tt&amp;gt;  || load from program memory&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
| &amp;lt;tt&amp;gt;lsr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || logical shift right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mov&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || move&lt;br /&gt;
| &amp;lt;tt&amp;gt;movw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || move word&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mul&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || multiply unsigned&lt;br /&gt;
| &amp;lt;tt&amp;gt;muls&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,d&amp;lt;/tt&amp;gt;  || multiply signed &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mulsu&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;a,a&amp;lt;/tt&amp;gt;  || multiply signed/unsigned &lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;neg&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || negate&lt;br /&gt;
| &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;   || or&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ori&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt;  || or with immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,r&amp;lt;/tt&amp;gt;  || output to I/O&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;pop&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || pop from Stack&lt;br /&gt;
| &amp;lt;tt&amp;gt;push&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || push to Stack&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ror&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || rotate right&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || subtract with carry&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbci&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || subtract with carry immediate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbic&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || skip if bit in I/O clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbis&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || skip if bit in I/O set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt;  || set Bit in I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbiw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;w,I&amp;lt;/tt&amp;gt; || subtract immediate from word&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbrc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || skip if bit in register clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbrs&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || skip if bit in register set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;e,r&amp;lt;/tt&amp;gt;  || store indirect&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;e+,r&amp;lt;/tt&amp;gt;  || store indirect, post-increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;-e,r&amp;lt;/tt&amp;gt;  || store indirect, pre-decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;std&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;b,r&amp;lt;/tt&amp;gt; || store indirect with displacement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sts&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;label,r&amp;lt;/tt&amp;gt; || store direct&lt;br /&gt;
| &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || subtract&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;subi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || subtract immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || swap nibbles&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;xch&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || exchange&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&amp;amp;nbsp;Je nach Derivat werden die folgenden &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;-Ausprägungen unterstützt oder nicht:&lt;br /&gt;
* &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;lpm r,z&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;lpm r,z+&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;elpm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;elpm r,z&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;elpm r,z+&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch ein paar der gebräuchlichsten Shorthands und deren Abbildung auf &amp;quot;Basis&amp;quot;-Instruktionen:&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+'''Tabelle: Shorthands'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Shorthand || gleichbedeutend mit || Bedeutung ||rowspan=&amp;quot;5&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
!Shorthand || gleichbedeutend mit || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;rol r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;adc   r,r&amp;lt;/tt&amp;gt;   || rotate left&lt;br /&gt;
| &amp;lt;tt&amp;gt;cbr r,M&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;andi  r, ~M&amp;lt;/tt&amp;gt; || clear bits in reg&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;clr r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;eor  r,r&amp;lt;/tt&amp;gt;   || clear reg to zero &lt;br /&gt;
| &amp;lt;tt&amp;gt;lsl r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;add  r,r&amp;lt;/tt&amp;gt;   || logical shift left&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbr d,M&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;ori  d, M&amp;lt;/tt&amp;gt; || set bits in reg&lt;br /&gt;
| &amp;lt;tt&amp;gt;ser d&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;ldi  d, 0xff&amp;lt;/tt&amp;gt; || set all bits in reg&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;tst r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;and  r,r&amp;lt;/tt&amp;gt;   || test against zero&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Clobbers==&lt;br /&gt;
&lt;br /&gt;
In der Komma-getrennten Clobber-Liste kann man angeben, welche Register durch den Inline-Assembler ihren Wert ändern. Ändern z.B. &amp;lt;tt&amp;gt;r2&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;r3&amp;lt;/tt&amp;gt; ihre Werte, dann ist die Clobber-Liste&lt;br /&gt;
 &amp;quot;r2&amp;quot;, &amp;quot;r3&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Wird schreibend auf das RAM zugegriffen, dann muss man das auch mitteilen, damit RAM-Inhalte, die sich evtl. in Registern befinden, nach dem Inline-Assembler neu gelesen werden. Der Clobber dafür ist:&lt;br /&gt;
 &amp;quot;memory&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Beispiel:'''&lt;br /&gt;
&lt;br /&gt;
Es soll ein Inline-Assembler geschrieben werden, das den Inhalt zweier aufeinanderfolgender Speicherstellen austauscht. Die Adresse soll in &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; stehen. Sie ist Input-Operand und muss in Register X, Y oder Z stehen, um den &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;-Befehl anwenden zu können. Die passende Constraint ist also &amp;lt;tt&amp;gt;&amp;quot;e&amp;quot;&amp;lt;/tt&amp;gt;. Nach der Sequenz liegt &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; unverändert vor.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;ld r2,  %a0+&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;ld r3,  %a0&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;st %a0,  r2&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;st -%a0, r3&amp;quot;&lt;br /&gt;
         : /* keine Output-Operanden */&lt;br /&gt;
         : &amp;quot;e&amp;quot; (addr)&lt;br /&gt;
         : &amp;quot;r2&amp;quot;, &amp;quot;r3&amp;quot;, &amp;quot;memory&amp;quot;&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
avr-gcc entscheidet sich dazu, das Z-Register für &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; zu verwenden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ld r2,  Z+&lt;br /&gt;
	ld r3,  Z&lt;br /&gt;
	st Z,  r2&lt;br /&gt;
	st -Z, r3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Günstiger ist es jedoch, dem Compiler auch die Entscheidung zu überlassen, welche(s) Register als Hilfsregister verwendet werden sollen. Ein Register kann &amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; sein, für das zweite  legen wir eine lokale 8-Bit-Variable &amp;lt;tt&amp;gt;hilf&amp;lt;/tt&amp;gt; an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   {&lt;br /&gt;
      char hilf;&lt;br /&gt;
	&lt;br /&gt;
      asm volatile (&lt;br /&gt;
         &amp;quot;ld __tmp_reg__,  %a1+&amp;quot;           &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;ld %0,           %a1&amp;quot;            &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;st %a1,          __tmp_reg__&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;st -%a1,         %0&amp;quot;&lt;br /&gt;
            : &amp;quot;=&amp;amp;r&amp;quot; (hilf)&lt;br /&gt;
            : &amp;quot;e&amp;quot;   (addr)&lt;br /&gt;
            : &amp;quot;memory&amp;quot;&lt;br /&gt;
      );&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; (also &amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;) brauch nicht in die Clobber-Liste aufgenommen zu werden. Um das zweite benötigte Register (hier &amp;lt;tt&amp;gt;r24&amp;lt;/tt&amp;gt;, in dem &amp;lt;tt&amp;gt;hilf&amp;lt;/tt&amp;gt; lebt) kümmert sich avr-gcc und sichert es, falls nötig&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       	ld	r0, Z+&lt;br /&gt;
       	ld	r24, Z&lt;br /&gt;
       	st	Z, r0&lt;br /&gt;
       	st	-Z, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen |&lt;br /&gt;
Falls das Register &amp;lt;tt&amp;gt;r1&amp;lt;/tt&amp;gt; verändert wird &amp;amp;ndash; was z.B. geschieht, wenn man Multiplikationsbefehle verwendet &amp;amp;ndash; dann muss am Ende des Templates das Register wieder auf&amp;amp;nbsp;0 gesetzt werden, denn bei avr-gcc enthält dieses Register immer den Wert&amp;amp;nbsp;0.&lt;br /&gt;
Das Register in die Clobber-Liste aufzunehen bleibt wirkungslos. Hat man es zerstört,&lt;br /&gt;
dann schreibt man ans Ende des Templates ein&lt;br /&gt;
 clr __zero_reg__&lt;br /&gt;
und stellt es dadurch wieder her.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== asm goto mit C-Labels == &lt;br /&gt;
&lt;br /&gt;
Ab Version 4.5 kennt GCC &amp;lt;tt&amp;gt;asm goto&amp;lt;/tt&amp;gt;, mit dem ausgedrückt werden kann, dass der Codefluß des Assembler-Teils u.U. zu einem Stück C-Code springt:&lt;br /&gt;
&lt;br /&gt;
 asm goto ([[#Assembler-Template|asm-template]] : {{comment|Leer}} : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]] : [[#asm goto mit C-Labels|C-labels]]);&lt;br /&gt;
&lt;br /&gt;
Die Codefluß-Analyse des Compilers muss wissen, daß die angegebenen C-Code Sequenzen verwendet werden, damit sie  nicht wegoptimiert werden.  Solch ein Inline-Assembler mit &amp;lt;tt&amp;gt;goto&amp;lt;/tt&amp;gt; darf keine Output-Operanden haben, denn der Compiler hat keine Möglichkeit, Code für die entsprechenden Output-Reloads zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
;Beispiel:&lt;br /&gt;
&lt;br /&gt;
 extern void __attribute__((noreturn))&lt;br /&gt;
 panic (void);&lt;br /&gt;
 &lt;br /&gt;
 char panic_if_x (char x)&lt;br /&gt;
 {&lt;br /&gt;
     asm goto (&amp;quot;cpse %0, __zero_reg__&amp;quot; &amp;quot;\n\t&amp;quot;&lt;br /&gt;
               &amp;quot;%~jmp %x1&amp;quot;             &amp;quot;\n\t&amp;quot;&lt;br /&gt;
               &amp;quot;%~jmp %x2&amp;quot;&lt;br /&gt;
               :: &amp;quot;r&amp;quot; (x) :: proceed, do_panic);&lt;br /&gt;
     __builtin_unreachable();&lt;br /&gt;
     &lt;br /&gt;
     if (0)&lt;br /&gt;
     {&lt;br /&gt;
     do_panic:&lt;br /&gt;
         panic();&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if (0)&lt;br /&gt;
     {&lt;br /&gt;
     proceed:&lt;br /&gt;
         x++;&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     return x;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der Inline-Assembler nur über die Marken &amp;lt;tt&amp;gt;do_panic&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;proceed&amp;lt;/tt&amp;gt; verlassen, weshalb der Code direkt danach unerreichbar ist.  Dies wird der Codefluß-Analyse per &amp;lt;tt&amp;gt;__builtin_unreachable()&amp;lt;/tt&amp;gt; mitgeteilt.  Es wird folgender Code erzeugt:&lt;br /&gt;
&lt;br /&gt;
 panic_if_x:&lt;br /&gt;
 {{comment|#APP}}&lt;br /&gt;
 	cpse r24,__zero_reg__&lt;br /&gt;
 	rjmp .L2&lt;br /&gt;
 	rjmp .L3&lt;br /&gt;
 {{comment|#NOAPP}}&lt;br /&gt;
 .L3:&lt;br /&gt;
 	rcall panic&lt;br /&gt;
 .L2:&lt;br /&gt;
 	subi r24,lo8(-(1))&lt;br /&gt;
 	ret&lt;br /&gt;
&lt;br /&gt;
=Vordefinierte Bezeichner und Makros=&lt;br /&gt;
Je nach Assembler, für den avr-gcc Code erzeugt, gibt es unterschiedliche vordefinierte Funktionen/Makros, die von Inline-Assembler aus verwendbar sind.&lt;br /&gt;
&lt;br /&gt;
== GNU-Assembler ==&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}} &lt;br /&gt;
|+ '''Vordefinierte Makros und&amp;lt;br/&amp;gt;Relocatable Expression Modifiers'''&amp;lt;br/&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Bezeichner || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SP_L__&amp;lt;/tt&amp;gt; || unteres Byte des Stack-Pointers, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SP_H__&amp;lt;/tt&amp;gt; || oberes Byte des Stack-Pointers, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SREG__&amp;lt;/tt&amp;gt; || Status-Register, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; || ein Register zur temporären Verwendung (&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__zero_reg__&amp;lt;/tt&amp;gt; || ein Register, das 0 enthält (&amp;lt;tt&amp;gt;r1&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;lo8(''const'')&amp;lt;/tt&amp;gt; || Bits 0...7 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;hi8(''const'')&amp;lt;/tt&amp;gt; || Bits 8...15 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;hlo8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;hh8(''const'')&amp;lt;/tt&amp;gt; || Bits 16...23 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;hhi8(''const'')&amp;lt;/tt&amp;gt; || Bits 24...31 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;pm(''const'')&amp;lt;/tt&amp;gt; || Konstante &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt; durch 2 geteilt,&amp;lt;br/&amp;gt;zur Berechnung von Word-Adressen für &amp;lt;tt&amp;gt;icall&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;ijmp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;pm_lo8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;pm_hi8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;pm_hh8(''const'')&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Abkürzung für &amp;lt;tt&amp;gt;lo8(pm(''const''))&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;Abkürzung für &amp;lt;tt&amp;gt;hi8(pm(''const''))&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;Abkürzung für &amp;lt;tt&amp;gt;hh8(pm(''const''))&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;gs(''label'')&amp;lt;/tt&amp;gt; || Word-Adresse von &amp;lt;tt&amp;gt;''label''&amp;lt;/tt&amp;gt;. Für Devices mit mehr als 128k Flash wird die Adresse eines Jump-Pads eingetragen. Der Linker erzeugt ein Jump-Pad, das einen direkten Sprung zu &amp;lt;tt&amp;gt;label&amp;lt;/tt&amp;gt; erhält. &amp;lt;tt&amp;gt;gs(label)&amp;lt;/tt&amp;gt; wird durch diese Adresse ersetzt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Beispiele=&lt;br /&gt;
&lt;br /&gt;
==nop==&lt;br /&gt;
Mit den bisherigen Vorkenntnissen ist zu &amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt; nicht viel zu sagen:&lt;br /&gt;
 asm volatile (&amp;quot;nop&amp;quot;);&lt;br /&gt;
Oder als C-Makro:&lt;br /&gt;
 #define nop() \&lt;br /&gt;
    asm volatile (&amp;quot;nop&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt; hat weder Input- noch Output-Operanden, und Register/RAM ändern sich natürlich nicht. Bei der Makro-Definition ist lediglich darauf zu achten, daß das Makro nicht mit einem&amp;amp;nbsp;&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; endet, damit man den C-Code wie gewohnt mit&amp;amp;nbsp;&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; schreiben kann:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (x)&lt;br /&gt;
   nop();&lt;br /&gt;
else&lt;br /&gt;
   ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==swap Nibbles==&lt;br /&gt;
Ein einfaches Beispiel für &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; haben wir bereits oben kennen gelernt. Der Inline-Assembler dreht die Nibbles von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; um:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char foo;&lt;br /&gt;
...&lt;br /&gt;
asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (foo));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wünschenswert wäre eher, &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; wie eine normale C-Funktion verwenden zu können und hinzuschreiben:&lt;br /&gt;
 a = swap(b);&lt;br /&gt;
ohne daß &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; seinen Wert ändert. Soll &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; geswappt werden, dann via&lt;br /&gt;
 b = swap(b);&lt;br /&gt;
zudem soll das Argument ein Ausdruck sein können:&lt;br /&gt;
 if (b == swap (b+1))&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Dazu verwenden wir eine lokale Variable &amp;lt;tt&amp;gt;_x_&amp;lt;/tt&amp;gt;, in die der ursprüngliche Wert &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; gesichert wird:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define swap(x)                                            \&lt;br /&gt;
 ({                                                        \&lt;br /&gt;
    unsigned char _x_ = (unsigned char) x;                 \&lt;br /&gt;
    asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (_x_));                          \&lt;br /&gt;
    _x_;                                                   \&lt;br /&gt;
  })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
alternativ könnten wir eine inline-Funktion definieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static inline unsigned char swap (unsigned char x)&lt;br /&gt;
{&lt;br /&gt;
    asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (x));&lt;br /&gt;
    return x;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==swap Bytes==&lt;br /&gt;
Werden Zahlen zwischen verschiedenen Plattformen übertragen, kann es sein, daß diese unterschiedlich dargestellt werden: Das low-Byte kann in sich im unteren Byte befinden (AVR), es kann aber auch im oberen Byte sein. Ist das so, dann müssen die Werte beim Senden/Empfang umgewandelt werden, indem die Bytes getauscht werden. Liegt der 16-Bit-Wert in &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; und soll der konvertierte Wert nach &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; gespeichert werden, dann könnte man auf die Idee kommen, so etwas zu schreiben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm (&lt;br /&gt;
      &amp;quot;mov %A0, %B1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;mov %B0, %A1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (x_out)&lt;br /&gt;
         : &amp;quot;r&amp;quot;  (x_in)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Daraus könnte folgender Code entstehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     mov    r24, r25&lt;br /&gt;
     mov    r25, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das ist offenbar Käse! Was ist passiert? &lt;br /&gt;
&lt;br /&gt;
avr-gcc hat sich dazu entschieden, &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;r25:r24&amp;lt;/tt&amp;gt; anzulegen. Auch &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; wird in diesen Registern angelegt. Das ist erst mal in Ordnung, wenn &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; nach dem Inline nicht mehr gebraucht wird. &lt;br /&gt;
&lt;br /&gt;
Allerdings wird das Inline nicht en bloc &amp;amp;mdash; also nicht zeitparallel &amp;amp;mdash; ausgeführt, sondern sequenziell. Bei ''gleichzeitiger'' Ausführung der beiden &amp;lt;tt&amp;gt;mov&amp;lt;/tt&amp;gt;-Instruktionen wäre auch nichts dagegen zu sagen! Ein &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt;-Kommando z.B. tauscht die Nibbles ''gleichzeitig'', und der Input-Operand kann im gleichen Register leben wie der Output-Operand, wenn der Input nicht weiter verwendet wird. &lt;br /&gt;
&lt;br /&gt;
Mit den beiden Bytes geht es aber nicht. Wir müssen daher kennzeichnen, daß sich &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; in einem Register befindet, das ''nur'' als Output dient, was durch das &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; in der Output-Constraint erreicht wird:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm (&lt;br /&gt;
      &amp;quot;mov %A0, %B1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;mov %B0, %A1&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (x_out)&lt;br /&gt;
         : &amp;quot;r&amp;quot;   (x_in)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit erfolgt eine korrekte Registerzuordnung. &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; steht jetzt in &amp;lt;tt&amp;gt;r19:r18&amp;lt;/tt&amp;gt; und überschneidet nich nicht mehr mit &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       	mov	r18, r25&lt;br /&gt;
       	mov	r19, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ können wir wie bei [[#swap Nibbles|swap Nibbles]] eine lokale Variable verwenden, und alles als (inline-)Funktion machen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Zugriff auf SFRs ==&lt;br /&gt;
Um auf SFRs zuzugreifen, können im asm-Template keine Defines aus &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; verwendet werden, weil der Präprozessor nicht mehr über den erzeugten Assembler-Code läuft (er läuft vor dem Compilieren). Um nicht die hex-Codes des SFRs angeben zu müssen, kann man dem Inline die Adressen als Konstanten übergeben. Weil die Adressen RAM-Adressen sind, müssen sie in das &amp;lt;tt&amp;gt;_SFR_IO_ADDR&amp;lt;/tt&amp;gt; Makro verpackt werden, um den Offset für den I/O-Bereich abzuziehen. &amp;lt;tt&amp;gt;tcnt1&amp;lt;/tt&amp;gt; wird auf den Inhalt von &amp;lt;tt&amp;gt;TCNT1&amp;lt;/tt&amp;gt; gesetzt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
   ... &lt;br /&gt;
   uint16_t tcnt1;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;in %A0, %1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;in %B0, %1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (tcnt1)&lt;br /&gt;
         : &amp;quot;M&amp;quot; (_SFR_IO_ADDR (TCNT1))&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
wird umgesetzt zu&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	in r24, 44&lt;br /&gt;
	in r25, 44+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab avr-gcc 4.7 kann auch der Operand-Modofier &amp;lt;tt&amp;gt;%i&amp;lt;/tt&amp;gt; verwendet werden, um eine RAM-Adresse, wie sie von &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; definiert werden, als I/O-Adresse auszugeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   uint16_t tcnt1;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;in %A0, %i1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;in %B0, %i1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (tcnt1)&lt;br /&gt;
         : &amp;quot;n&amp;quot; (&amp;amp; TCNT1)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das nur als Beispiel. Von C aus geht das natürlich auch mit&lt;br /&gt;
 uint16_t tcnt1 = TCNT1;&lt;br /&gt;
&lt;br /&gt;
== Zugriff aufs SRAM ==&lt;br /&gt;
Auf bekannte globale Symbole kann man direkt von Assembler aus zugreifen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   extern int einInt;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, einInt&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, einInt+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24, einInt&lt;br /&gt;
	lds r25, einInt+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
alternativ ginge&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, %A1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, %B1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;m&amp;quot; (einInt)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls die Adresse eines Objekts zur Compilezeit bekannt ist, kann man auch die Adresse von C aus übergeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct foo_t {&lt;br /&gt;
   int a[2], b[2];&lt;br /&gt;
} foo;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
{&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, %1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, %1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;i&amp;quot; (&amp;amp; foo.b[1])&lt;br /&gt;
   );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24, einStruct+6&lt;br /&gt;
	lds r25, einStruct+6+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls die Adresse zur Compilezeit nicht bekannt ist, muss sie natürlich in einem Adress- oder Basisregister übergeben werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void blah (struct foo_t * pfoo)&lt;br /&gt;
{&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;ld  %A0, %a1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;ldd %B0, %a1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;b&amp;quot; (&amp;amp; pfoo-&amp;gt;b[1])&lt;br /&gt;
   );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ld  r24, Z&lt;br /&gt;
	ldd r25, Z+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Auch hier muss der Output-Operand mit einem&amp;amp;nbsp;&amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; gekennzeichnet werden, damit er nicht ins gleiche Register geladen wird wie die Adresse.&lt;br /&gt;
&lt;br /&gt;
= Labels und Schleifen =&lt;br /&gt;
Für Labels in Sprüngen und Schleifen können keine festen Bezeichner verwendet werden, weil ein Label, der via Makro oder inline-Funktion in den Code eingefügt wird, nicht mehrfach vorkommen darf. Dazu kann man sich durch Einfügen von &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; Labels zusammenbauen, etwa &amp;lt;tt&amp;gt;L_a%=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;L_b%=&amp;lt;/tt&amp;gt;, etc. Das &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; wird durch eine für die Übersetzungseinheit und den Code-Schnippsel eindeutige Zahl ersetzt. Die obigen Sequenzen könnten also z.B. umgesetzt werden als &amp;lt;tt&amp;gt;L_a14&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;L_b14&amp;lt;/tt&amp;gt;, wenn sie im gleichen Schnippsel stehen.&lt;br /&gt;
&lt;br /&gt;
Etwas bequemer ist die Verwendung einer Ziffer als Label. Beim Sprung gibt man direkt hinter der Ziffer an, in welche Richtung das Label gesucht wird. Ist das Label &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt;, dann sucht und springt&lt;br /&gt;
*&amp;lt;tt&amp;gt;''n''b&amp;lt;/tt&amp;gt; zurück (backward)&lt;br /&gt;
*&amp;lt;tt&amp;gt;''n''f&amp;lt;/tt&amp;gt; nach vorne (forward)&lt;br /&gt;
&lt;br /&gt;
Es wird zum nächsten auffindbaren Label in der angegebenen Richtung gesprungen.&lt;br /&gt;
&lt;br /&gt;
==Bits zählen==&lt;br /&gt;
&lt;br /&gt;
Dieses Assembler-Schnippsel zählt die Anzahl der gesetzten Bits in einem Byte &amp;lt;tt&amp;gt;eingabe&amp;lt;/tt&amp;gt;. Die Eingabe wird nach rechts ins Carry geschoben, und das Carry zum Ergebnis dazu addiert.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static inline unsigned char count_bits (unsigned char eingabe)&lt;br /&gt;
{                                              &lt;br /&gt;
   unsigned char count;&lt;br /&gt;
&lt;br /&gt;
   asm ( &lt;br /&gt;
      &amp;quot;clr %0&amp;quot;                &amp;quot;\n&amp;quot;&lt;br /&gt;
      &amp;quot;0:&amp;quot;                    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lsr %1&amp;quot;                &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;adc %0, __zero_reg__&amp;quot;  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;tst %1&amp;quot;                &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;brne 0b&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (count), &amp;quot;+r&amp;quot; (eingabe)&lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
   return count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit kann man sich ein Parity bauen:&lt;br /&gt;
 #define parity(x) (count_bits(x) &amp;amp; 1)&lt;br /&gt;
und hätte eine schlankere (aber etwas langsamere) Parity-Implementierung als in &amp;lt;tt&amp;gt;avr/parity.h&amp;lt;/tt&amp;gt;. Ein &lt;br /&gt;
 if (parity(foo))&lt;br /&gt;
    ...&lt;br /&gt;
wird in Assembler dann zu (&amp;lt;tt&amp;gt;r24 = eingabe&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r25 = count&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24,foo&lt;br /&gt;
/* #APP */&lt;br /&gt;
	clr r25&lt;br /&gt;
0:&lt;br /&gt;
	lsr r24&lt;br /&gt;
	adc r25, __zero_reg__&lt;br /&gt;
	tst r24&lt;br /&gt;
	brne 0b&lt;br /&gt;
/* #NOAPP */&lt;br /&gt;
	sbrs r25,0&lt;br /&gt;
	rjmp .L1&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Fallstricke=&lt;br /&gt;
* Um die Sonderzeichen &amp;lt;tt&amp;gt;&amp;quot;%~&amp;quot;&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; benutzen zu können, muss bei parameterlosen Inline Assembler dem Template ein Doppelpunkt folgen:&lt;br /&gt;
:&amp;lt;pre&amp;gt;asm volatile (&amp;quot;%~call some_function&amp;quot; :);&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Steht das &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; an oberster Ebene — also außerhalb einer Funktion — ist weiter zu beachten:&lt;br /&gt;
** Jedes &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt; wird als solches ausgegeben, und es sind keine Operanden erlaubt.&lt;br /&gt;
** Falls die Reihenfolge von &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; und Funktionen beibehalten werden soll, muß mit &amp;lt;tt&amp;gt;-fno-toplevel-reorder&amp;lt;/tt&amp;gt; compiliert werden.&lt;br /&gt;
&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
; Dokumentation&lt;br /&gt;
&lt;br /&gt;
* AVR-LibC: [http://nongnu.org/avr-libc/user-manual/inline_asm.html ''Inline Assembler Cookbook'']&lt;br /&gt;
* GCC Wiki: [http://gcc.gnu.org/wiki/avr-gcc ''avr-gcc'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html ''Assembler Instructions with C Expression Operands'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Constraints.html ''Constraints for &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; Operands'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html ''Variables in Specified Registers'']&lt;br /&gt;
* GCC Internals: [http://gcc.gnu.org/onlinedocs/gccint/Constraints.html ''Operand Constraints'']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;GCC-Quellen:&lt;br /&gt;
&lt;br /&gt;
* [http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/avr.md?content-type=text%2Fplain&amp;amp;view=co ./gcc/config/avr/avr.md]&lt;br /&gt;
* [http://gcc.gnu.org/viewcvs/gcc/trunk/gcc/config/avr/constraints.md?content-type=text%2Fplain&amp;amp;view=co ./gcc/config/avr/constraints.md]&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[AVR Assembler Einführung]]&lt;br /&gt;
* [[:Kategorie:Quellcode Assembler_AVR|Quellcode Assembler]]&lt;br /&gt;
* [[Sourcevergleich#GCC (Assembler einfügen)]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Software]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Quellcode_Assembler_AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Speicherverbrauch_bestimmen_mit_avr-gcc&amp;diff=25256</id>
		<title>Speicherverbrauch bestimmen mit avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Speicherverbrauch_bestimmen_mit_avr-gcc&amp;diff=25256"/>
				<updated>2014-09-14T20:18:30Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Dynamischer RAM-Verbrauch */ static&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;Der Speicherverbrauch eines C-Programmes lässt sich unter verschiedenen Gesichtspunkten betrachten.&lt;br /&gt;
;Ort der Datenablage:&lt;br /&gt;
* SRAM&lt;br /&gt;
* Flash&lt;br /&gt;
* EEPROM &lt;br /&gt;
&lt;br /&gt;
;Art der Daten:&lt;br /&gt;
* Programmcode&lt;br /&gt;
* Daten&lt;br /&gt;
** veränderlich/unveränderlich&lt;br /&gt;
** persistent oder flüchtig&lt;br /&gt;
&lt;br /&gt;
;Speicherklasse der Daten&lt;br /&gt;
* Statischer Speicherverbrauch&lt;br /&gt;
* Dynamischer Speicherverbrauch&lt;br /&gt;
&lt;br /&gt;
Der Ort der Datenablage wird bestimmt von der Art der Daten. Daten, die nicht verändert werden dürfen oder nicht verändert werden müssen, wie der Programm-Code oder konstante Strings, wie sie oft zur Ausgabe verwendet werden, können im Flash gespeichert werden. Konstanten/Tabellen kann man auch im EEPROM speichern, wenn der Platz im Flash knapp ist. Der Programmcode selbst muss bei [[AVR]] im Flash liegen. Man kann den Code zwar auch ins RAM oder ins EEPROM legen, aber von dort nicht ausführen.&lt;br /&gt;
&lt;br /&gt;
Daten, die zur Laufzeit verändert werden müssen, wird man im SRAM speichern, wenn sie einen Reset bzw. ein Ausschalten des Controllers nicht überleben müssen. Sollen die Daten auch ohne Strom erhalten bleiben, muss man den EEPROM oder den Flash als Ablageort wählen. Dabei ist das Speichern von Daten im Flash zur Laufzeit sehr aufwändig, weil man einen [[Bootloader]] für ihre Änderung anstrengen muss. Andererseits kann wesentlich schneller auf das Flash zugegriffen werden als auf den EEPROM-Speicher.&lt;br /&gt;
&lt;br /&gt;
Die Art der Daten ergibt sich aus dem Programm und den zu lösenden Aufgaben,&lt;br /&gt;
gleiches gilt für die Speicherklassen. &lt;br /&gt;
&lt;br /&gt;
Die Ablageorte der statische Daten sind bereits zur Compilezeit &lt;br /&gt;
bekannt. Hierzu gehören globale und statische Variablen. Dementsprechend ist auch schon zur Compile- bzw. Linkzeit bekannt, wieviel Speicher diese Daten belegen. &lt;br /&gt;
&lt;br /&gt;
Speicherorte und Platzverbrauch dynamischer Variablen sind dem Compiler nicht bekannt. Sie ergeben sich erst zur Laufzeit durch das Allokieren von Speicher mit &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt;, oder durch den Aufbau eines Stapels, auf dem lokale Variablen gesichert werden, während eine Funktion aufgerufen wird. Je nach Verschachtelungstiefe der Funktionsaufrufe &amp;amp;mdash; dazu gehören auch [[Interrupt]] Service Routinen, die prinzipiell jederzeit aufgerufen werden können &amp;amp;mdash; wird dafür auch unterschiedlich viel Speicher benötigt.&lt;br /&gt;
&lt;br /&gt;
=Nutzung des SRAM durch avr-gcc=&lt;br /&gt;
[[Bild:Avr-ram.png|right|thumb|RAM-Layout für ein AVR mit 1kByte SRAM]]&lt;br /&gt;
[[avr-gcc]] legt die Daten in [[avr-gcc/Interna#Sections|Sections]] an.&lt;br /&gt;
Nach aufsteigenden Speicheradressen sortiert sind diese:&lt;br /&gt;
;&amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt;: Statische und (modul-)globale, initialisierte Daten, denen man per Initializer einen Wert ungleich&amp;amp;nbsp;0 zuweist. Beginnt an der unteren SRAM-Adresse &amp;lt;tt&amp;gt;0x60&amp;lt;/tt&amp;gt; nach dem SFR-Bereich, je nach AVR-Derivat auch an anderer Adresse.&lt;br /&gt;
;&amp;lt;tt&amp;gt;.bss&amp;lt;/tt&amp;gt;: Statische und (modul-)globale, initialisierte Daten, die zu&amp;amp;nbsp;0 initialisiert sind bzw. keinen Initializer haben (und also auch zu&amp;amp;nbsp;0 initialisiert werden).&lt;br /&gt;
;&amp;lt;tt&amp;gt;.noinit&amp;lt;/tt&amp;gt;: Statische und (modul-)globale Daten, die nicht vom Startup-Code initialisiert werden und zum Beispiel einen [[Watchdog]]-Reset überdauern.&lt;br /&gt;
&lt;br /&gt;
Auf diese Sections folgen noch zwei Speicherbereiche für dynamische Daten:&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;Heap&amp;lt;/tt&amp;gt;: Danach folgt der Heap. Das ist ein Speicherbereich, aus dem Speicherplatz via &amp;lt;tt&amp;gt;malloc&amp;lt;/tt&amp;gt; etc. allokiert wird.&lt;br /&gt;
;&amp;lt;tt&amp;gt;Stack&amp;lt;/tt&amp;gt;: Auf dem Stapel werden lokale Variablen/Register während Funktionsaufrufen gesichert. Der Stack wird teilweise auch zur Parameterübergabe verwendet und die return-Adresse von Funktionen und [[ISR]]s wird dort abgelegt. Der Stack beginnt an der oberen SRAM-Adresse und wächst nicht wie die andern Bereiche nach oben, sondern nach unten.&lt;br /&gt;
&lt;br /&gt;
Die Größe der ersten drei Speicherbereiche kann man für jedes Modul bereits zur Compile-Zeit bestimmen, da sie unabhängig sind von der Programmausführung. Wie viel Platz die letzten beiden Bereiche brauchen, ergibt sich erst zur Laufzeit des Programms. Diese Größen ändern sich in aller Regel mit der Zeit.&lt;br /&gt;
&lt;br /&gt;
Heap und Stack müssen sich den Speicher, der nicht von &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;.bss&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;.noinit&amp;lt;/tt&amp;gt; belegt ist, teilen &lt;br /&gt;
&lt;br /&gt;
Wird der Stackbereich zu groß, weil dort zu viele Daten abgelegt werden (zu viele lokale Variablen (lokale Arrays!), zu tief verschaltelte (rekursive) Funktionen, kaskadierende [[Interrupt]] Service Routinen, ...), dann überschreibt man damit womöglich andere Daten und es kommt zur Fehlfunktion des Programmes. Gleiches gilt, wenn die Obergrenze des Heap über der Untergrenze des Stabels hinauswächst.&lt;br /&gt;
&lt;br /&gt;
=Flash- und statischer RAM-Verbrauch =&lt;br /&gt;
Zur Bestimmung des Speicherplatzes, den statische Daten belegen, verwendet man &amp;lt;tt&amp;gt;avr-size&amp;lt;/tt&amp;gt;, das zu den Binutils gehört und z.B. bei [[WinAVR]] dabei ist. &lt;br /&gt;
&lt;br /&gt;
Abhängig von der [[avr-gcc#Sections|Section]] schlägt ihr Platzverbrauch in Flash/SRAM/[[EEPROM]] zu Buche:&lt;br /&gt;
&amp;lt;center&amp;gt;&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: Zuordung des Platzberbrauchs zur Section-Größe'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! |belegter Speicher || Sections (Einzelgrößen addieren) ||Beschreibung&lt;br /&gt;
 |-&lt;br /&gt;
 |Flash || &amp;lt;tt&amp;gt;.text&amp;lt;/tt&amp;gt; + &amp;lt;tt&amp;gt;.bootloader&amp;lt;/tt&amp;gt; + &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt; || Programmcode und Tabelle für initialisierte Daten&lt;br /&gt;
 |-&lt;br /&gt;
 |SRAM  || &amp;lt;tt&amp;gt;.data&amp;lt;/tt&amp;gt; + &amp;lt;tt&amp;gt;.bss&amp;lt;/tt&amp;gt; + &amp;lt;tt&amp;gt;.noinit&amp;lt;/tt&amp;gt;|| Daten (initialisiert + zu 0 initialisiert + nicht initialisiert)&lt;br /&gt;
 |- &lt;br /&gt;
 |EEPROM ||&amp;lt;tt&amp;gt;.eeprom&amp;lt;/tt&amp;gt;  ||Daten, die man ins EEPROM gelegt hat&lt;br /&gt;
 |}&lt;br /&gt;
&amp;lt;/center&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Beispiele:'''&lt;br /&gt;
&lt;br /&gt;
Das &amp;lt;tt&amp;gt;'&amp;gt;'&amp;lt;/tt&amp;gt; nicht mittippen, es ist der Kommandozeilen-Prompt.&lt;br /&gt;
&lt;br /&gt;
Verbrauch der einzelnen Module auflisten:&lt;br /&gt;
 &amp;gt; avr-size -x foo1.o foo2.o ...&lt;br /&gt;
&lt;br /&gt;
Verbrauch des gesamten Programms auflisten:&lt;br /&gt;
 &amp;gt; avr-size -x -A foo.elf&lt;br /&gt;
In neueren Versionen von avr-size geht auch&lt;br /&gt;
 &amp;gt; avr-size --mcu=atmega8 -C foo.elf&lt;br /&gt;
was den Verbrauch als Absolutwerte und in Prozentangabe auflistet. Ohne die Angabe der Controllers mit &amp;lt;tt&amp;gt;--mcu&amp;lt;/tt&amp;gt; können natürlich keine Prozentwerte berechnet werden, es werden dann nur die absoluten Verbrauche ausgedruckt.&lt;br /&gt;
&lt;br /&gt;
Platzverbrauch von Funktionen, Objekten, Variablen, etc. nach Größe sortiert:&lt;br /&gt;
 &amp;gt; avr-nm --size-sort --print-size foo.elf&lt;br /&gt;
Hilfe zu avr-nm siehe: /WinAVR/doc/binutils/binutils.html/nm.html&lt;br /&gt;
&lt;br /&gt;
Zusammenfassung aus www.mikrocontroller.net:&lt;br /&gt;
&lt;br /&gt;
Großbuchstaben =&amp;gt; globale Symbole / kleine Buchstaben =&amp;gt; local symbols   &lt;br /&gt;
&lt;br /&gt;
T/t : The symbol is in the text (code) section. &lt;br /&gt;
&lt;br /&gt;
D/d : The symbol is in the initialized data section. &lt;br /&gt;
&lt;br /&gt;
B/b : The symbol is in the uninitialized data section (known as BSS). &lt;br /&gt;
&lt;br /&gt;
Alle Symbole mit einem &amp;quot;T&amp;quot; (globale Funktionen), &amp;quot;t&amp;quot; (statische Funktionen) und letztlich auch mit einem &amp;quot;D&amp;quot; oder &amp;quot;d&amp;quot; (globale bzw. statische Daten, die haben ihre Initialisierungswerte im ROM) betreffen das FLASH-ROM. &amp;quot;B&amp;quot; und &amp;quot;b&amp;quot; brauchen ausschließlich RAM (werden beim Start mit 0 initialisiert). Die erste Spalte ist die Adresse des Symbols, die zweite ist die Größe (beides hexadezimal)&lt;br /&gt;
&lt;br /&gt;
=Dynamischer RAM-Verbrauch=&lt;br /&gt;
&lt;br /&gt;
Um den momentan freien Speicher zu bestimmen, zieht man einfach den Anfang des Heaps vom Stackpointer ab:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|__heap_start is declared in the linker script}}&lt;br /&gt;
 extern unsigned char __heap_start;&lt;br /&gt;
    ...&lt;br /&gt;
    uint16_t momentan_frei = SP - (uint16_t) &amp;amp;__heap_start;&lt;br /&gt;
&lt;br /&gt;
Interessanter ist es jedoch, den Maximalverbrauch an Speicher bzw. das Minimum an ungenutztem Speicher seit Programmstart zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Mit der folgenden kleinen Routine kann der noch freie SRAM-Bereich bestimmt werden. Es wird nicht der momentan freie Speicher bestimmt, sondern das Minimum an Speicher, das bis dato ungenutzt geblieben ist. Dazu wird im Startup-Code das Muster &amp;lt;tt&amp;gt;0xaa&amp;lt;/tt&amp;gt; in den SRAM geschrieben. Durch Aufruf der Funktion &amp;lt;tt&amp;gt;get_mem_unused&amp;lt;/tt&amp;gt; wird bestimmt, wieviel von diesem Muster zum Zeitpunkt des Aufrufs noch intakt ist.&lt;br /&gt;
&lt;br /&gt;
Dieses Vorgehen ist deshalb notwendig, weil unter Umständen auch [[ISR]]-Routinen dynamisch Speicherplatz belegen, man jedoch &amp;lt;tt&amp;gt;get_mem_unused&amp;lt;/tt&amp;gt; nicht ''in'' der ISR aufrufen will.&lt;br /&gt;
&lt;br /&gt;
Mit optimierendem Compiler brauchen die beiden Routinen zusammen 42 Bytes an Flash.&lt;br /&gt;
&lt;br /&gt;
Damit der Code den richtigen Wert liefert, darf keine dynamische Speicherallokierung mit &amp;lt;tt&amp;gt;malloc()&amp;lt;/tt&amp;gt; etc. geschehen sein; ein &amp;lt;tt&amp;gt;[[Avr-gcc/Interna#Dynamische Speicherallokierung|__builtin_alloca]]&amp;lt;/tt&amp;gt; ist hingegen kein Problem, da letzteres den Platz vom Stapel nimmt. &lt;br /&gt;
&lt;br /&gt;
Die Funktion &amp;lt;tt&amp;gt;init_mem&amp;lt;/tt&amp;gt; wird in der Init-Phase [[Avr-gcc/Interna#Frühe Codeausführung vor main()|vor &amp;lt;tt&amp;gt;main&amp;lt;/tt&amp;gt; aufgerufen]].&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;mem-check.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
 #ifndef MEM_CHECK_H&lt;br /&gt;
 #define MEM_CHECK_H&lt;br /&gt;
 &lt;br /&gt;
 extern unsigned short get_mem_unused (void);&lt;br /&gt;
 &lt;br /&gt;
 #endif  {{comment|MEM_CHECK_H}}&lt;br /&gt;
&lt;br /&gt;
;&amp;lt;tt&amp;gt;mem-check.c&amp;lt;/tt&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;  {{ccomment|RAMEND}}&lt;br /&gt;
 #include &amp;quot;mem-check.h&amp;quot;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Mask to init SRAM and check against}}&lt;br /&gt;
 #define MASK 0xaa&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|From linker script}}&lt;br /&gt;
 extern unsigned char __heap_start;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|!!! This doesn't work together with malloc et.al. (whose use is}}&lt;br /&gt;
 {{ccomment|!!! discouraged on AVR, anyway). alloca, however, is no problem}}&lt;br /&gt;
 {{ccomment|!!! because it allocates on stack.}}&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Get minimum of free memory (in bytes) up to now.}}&lt;br /&gt;
 unsigned short &lt;br /&gt;
 get_mem_unused (void)&lt;br /&gt;
 {&lt;br /&gt;
    unsigned short unused = 0;&lt;br /&gt;
    unsigned char *p = &amp;amp;__heap_start;&lt;br /&gt;
 &lt;br /&gt;
    do&lt;br /&gt;
    {&lt;br /&gt;
       if (*p++ != MASK)&lt;br /&gt;
          break;&lt;br /&gt;
 &lt;br /&gt;
       unused++;&lt;br /&gt;
    } while (p &amp;lt;= (unsigned char*) RAMEND);&lt;br /&gt;
 &lt;br /&gt;
    return unused;&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|!!! Never call this function, it is part of .init-Code}}&lt;br /&gt;
 static void [[Avr-gcc/Interna#Attribute|__attribute__]] ((naked, used, section(&amp;quot;.init3&amp;quot;)))&lt;br /&gt;
 init_mem (void)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|Use inline assembler so it works even with optimization turned off.}}&lt;br /&gt;
    {{ccomment|Apart from that, according to GCC docs, the only code that's safe}}&lt;br /&gt;
    {{ccomment|in a naked function is inline assembly.}}&lt;br /&gt;
    __asm volatile (&lt;br /&gt;
       &amp;quot;ldi r30, lo8 (__heap_start)&amp;quot;  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;ldi r31, hi8 (__heap_start)&amp;quot;  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;ldi r24, %0&amp;quot;                  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;ldi r25, hi8 (%1)&amp;quot;            &amp;quot;\n&amp;quot;&lt;br /&gt;
       &amp;quot;0:&amp;quot;                           &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;st  Z+,  r24&amp;quot;                 &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;cpi r30, lo8 (%1)&amp;quot;            &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;cpc r31, r25&amp;quot;                 &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;brne 0b&amp;quot;&lt;br /&gt;
          :&lt;br /&gt;
          : &amp;quot;i&amp;quot; (MASK), &amp;quot;i&amp;quot; (RAMEND)&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Der Grund, hier auf [[Inline-Assembler in avr-gcc|Inline Assembler]] zurückzugreifen, ist folgender: Durch normalem C/C++-Code kann man nicht garantieren, daß alle Variablen in Registern leben. In diesem Falle würden Variablen, die auf dem Stack angelegt werden, durch die init-Routine überschrieben.&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[AVR]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
* [[Inline-Assembler in avr-gcc|Inline-Assembler]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;br /&gt;
[[Kategorie:Quellcode Assembler AVR]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Avr-gcc&amp;diff=25255</id>
		<title>Avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Avr-gcc&amp;diff=25255"/>
				<updated>2014-09-14T07:48:47Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* ISR mit eigenem Prolog/Epilog */ Framepointer, used&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''avr-gcc''' ist ein freier C-[[Compiler]], mit dem C-Programme zu ausführbaren Programmen übersetzen werden können, die auf [[Microcontroller]]n der [[AVR]]-Familie lauffähig sind. &lt;br /&gt;
An Sprachen versteht avr-gcc sowohl C als auch [[#C%2b%2b|C++]]. &lt;br /&gt;
Neben Standard-C bzw. ANSI-C versteht avr-gcc auch GNU-C, das etwas mehr Möglichkeiten und kleinere Spracherweiterungen bietet.&lt;br /&gt;
&lt;br /&gt;
avr-gcc kann auch dazu verwendet werden, um C/C++ Programme nach Assembler zu übersetzen oder um Bibliotheken zu erstellen, die später in unterschiedlichen Projekten verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
Wie bei allen aus der UNIX-Welt kommenden Programmen ist das Kommando-Interface von avr-gcc die Shell bzw. die Kommandozeile, über die Optionen, Parameter, Einstellungen und die Namen der zu übersetzenden Dateien angegeben werden. &lt;br /&gt;
&lt;br /&gt;
=How to Read=&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel bespricht avr-gcc Version 3.x. Er ist kein C-Tutorial und kein AVR-Handbuch &amp;amp;ndash; das würde den Umfang des Artikels bei weitem sprengen. &lt;br /&gt;
&lt;br /&gt;
Der Artikel ist ein Handbuch zu avr-gcc. Er bespricht zum Beispiel, wie avr-gcc angenwendet wird und Besonderheiten von avr-gcc-C, die nicht zum Sprachumfang von C gehören.&lt;br /&gt;
Dazu zählen die Definition von [[#Interrupts|Interrupt]] Service Routinen ([[ISR|ISRs]]) &lt;br /&gt;
oder wie man Daten ins [[EEPROM]] legt.&lt;br /&gt;
&lt;br /&gt;
Es wird also besprochen, ''wie'' eine ISR zu definieren ist, aber nicht,&lt;br /&gt;
''warum'' das  gegebenenfalls notwendig oder nicht notwendig ist. &lt;br /&gt;
''Warum'' etwas gemacht wird, ist abhängig von der gestellten Aufgabe,&lt;br /&gt;
etwa ''&amp;quot;Initialisiere den [[UART]] zur Benutzung mit 9600 Baud&amp;quot;''.&lt;br /&gt;
Dafür enthält dieser Artikel zusammen mit dem AVR-Handbuch das Rüstzeug, &lt;br /&gt;
bietet aber keine Lösungen für konkrete Aufgaben.&lt;br /&gt;
&lt;br /&gt;
Neben diesem Artikel gibt es den Unterartikel [[avr-gcc/Interna|Interna von avr-gcc]] wo Dinge wie die Registerverwendung, Attribute, Builtins und Sections von avr-gcc dargestellt werden. Zudem findet sich dort ein Überblick über die Arbeitsweise von gcc mit den Schritten&lt;br /&gt;
* Precompilieren&lt;br /&gt;
* Compilieren&lt;br /&gt;
* Assemblieren&lt;br /&gt;
* Linken&lt;br /&gt;
Ein weiterer Unterartikel widmet sich dem Thema [[Inline-Assembler in avr-gcc]].&lt;br /&gt;
&lt;br /&gt;
In den [[:Kategorie:Quellcode C|C-Codebeispielen]]&lt;br /&gt;
befindet sich das ausführlichere Beispiel &amp;quot;[[Hallo Welt für AVR (LED blinken)]]&amp;quot;,&lt;br /&gt;
das nur eine [[Diode#Lumineszenzdiode|LED]] blinkt und zeigt, &lt;br /&gt;
wie ein kleines Projekt mit avr-gcc compiliert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es gibt ein [[C-Tutorial]], das jedoch noch unvollständig und teilweise feherhaft ist (Stand 02/2006). Darüber hinaus gibt es ein [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial C-Tutorial bei www.mikrocontroller.net].&lt;br /&gt;
&lt;br /&gt;
=Benutzer-Schnittstelle=&lt;br /&gt;
&lt;br /&gt;
Die Benutzer-Schnittstelle von avr-gcc ist &amp;amp;ndash; wie für alle Programme, die aus der UNIX-Welt kommen &amp;amp;ndash; die Kommandozeile einer Shell, Console bzw. Eingabeaufforderung. &lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall sieht ein Aufruf von avr-gcc also so aus:&lt;br /&gt;
 &amp;gt; avr-gcc&lt;br /&gt;
Dabei das '&amp;lt;tt&amp;gt;&amp;gt;&amp;lt;/tt&amp;gt;' nicht mittippen, und ein ENTER am Ende der Zeile drücken.&lt;br /&gt;
Die Antwort bei korrekter Installation ist dann&lt;br /&gt;
 avr-gcc: no input files&lt;br /&gt;
Was bedeutet: das Programm avr-gcc wurde vom Betriebssystem gefunden und konnte/durfte gestartet werden. Dann gibt avr-gcc eine Fehlermeldung aus und beendet die Ausführung, weil er keine Eingabedatei(en) bekommen hat &amp;amp;#150; was ja auch stimmt. Soweit ist also alles in Butter.&lt;br /&gt;
&lt;br /&gt;
Um eine C-Datei &amp;lt;tt&amp;gt;foo.c&amp;lt;/tt&amp;gt; mir avr-gcc optimiert zu einem lauffähigen elf-Programm &amp;lt;tt&amp;gt;foo.elf&amp;lt;/tt&amp;gt; für einen [[ATmega32]] zu compileren, würde man angeben&lt;br /&gt;
 &amp;gt; avr-gcc -Os -mmcu=atmega32 foo.c -o foo.elf&lt;br /&gt;
Hat man seine Quellen auf zwei oder mehre Dateien verteilt, geht es analog:&lt;br /&gt;
 &amp;gt; avr-gcc -Os -mmcu=atmega32 foo.c foo2.c -o foo.elf&lt;br /&gt;
&lt;br /&gt;
Will man nur eine Objekt-Datei erstellen (nur compilieren, nicht linken), dann geht das wie folgt. Das kann günstig sein bei grösseren Projekten, wenn man das Projekt neu erzeugen will, aber nur in einer Quelldatei was geändert hat. Oder wenn das Objekt in einer Bibliothek landen soll.&lt;br /&gt;
 &amp;gt; avr-gcc -Os -c -mmcu=atmega32 foo.c -o foo.o&lt;br /&gt;
&lt;br /&gt;
Die ausführbare Gesamtdatei &amp;lt;tt&amp;gt;foo_all.elf&amp;lt;/tt&amp;gt; erhält man dann, indem alle Objekte zusammenlinkt:&lt;br /&gt;
 &amp;gt; avr-gcc -mmcu=atmega32 foo.o foo2.o foo3.o -o foo_all.elf&lt;br /&gt;
&lt;br /&gt;
Um die ausführbare Datei in das oft verwendete Intex-HEX-Format umzuwandeln (einmal fürs Programm, einmal für ein Abbild des [[EEPROM]]s) gibt man an:&lt;br /&gt;
 &amp;gt; avr-objcopy -O ihex -j .text -j .data                         foo_all.elf  foo_all.hex&lt;br /&gt;
 &amp;gt; avr-objcopy -O ihex -j .eeprom --change-section-lma .eeprom=1 foo_all.elf  foo_all_eeprom.hex&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[GCC]] war immer Kommandozeilen-orientiert und wird es auch immer bleiben, denn das hat gute Gründe:&lt;br /&gt;
* ein Compiler ist ein Compiler (und keine grafische Bedienschnittstelle)&lt;br /&gt;
* die Plattformabhängigkeit wird auf ein Minimum reduziert&lt;br /&gt;
* es gibt die Möglichkeit, avr-gcc per Skript oder [[make]] zu starten&lt;br /&gt;
* avr-gcc kann durchaus in eine Umgebung integriert werden: in einen Editor oder in eine GUI wie neuere Versionen von AVR-Studio erfolgreich beweisen, etc. Der avr-gcc-Aufruf kann sogar von einem Server-Socket oder einer Web-Application heraus erfolgen, welche ein C-Programm empfängt, es von avr-gcc übersetzen lässt, und das Resultat zurückschickt oder sonst was damit anstellt.&lt;br /&gt;
* Lizenzgründe: eine Umgebung, die avr-gcc integriert, kann durchaus proprietär oder nicht quelloffen sein und muss nicht der [[Freie Software|GPL]] unterliegen. Wieder ist AVR-Studio ein Beispiel.&lt;br /&gt;
&lt;br /&gt;
= Unterstützte AVR-Derivate=&lt;br /&gt;
&lt;br /&gt;
:→ ''[http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html GCC Manual: AVR Options]&lt;br /&gt;
&lt;br /&gt;
Diese Liste der unterstützten Devices kann man anzeigen lassen mit&lt;br /&gt;
 &amp;gt; avr-gcc --target-help&lt;br /&gt;
bzw. ab Version 4.7 mit&lt;br /&gt;
 &amp;gt; avr-gcc --help=target&lt;br /&gt;
&lt;br /&gt;
Siehe auch &amp;quot;AVR Options&amp;quot; in der GCC [[#Dokumentation|Dokumentation]].&lt;br /&gt;
&lt;br /&gt;
=Kommandozeilen-Optionen=&lt;br /&gt;
Die Codegenerierung bei avr-gcc wird über Kommandozeilen-Optionen gesteuert. Diese legen fest, für welchen Controller Code zu erzeugen ist, wie stark optimiert wird, ob Debug-Informationen erzeugt werden, etc. Die Optionen teilen sich in zwei Gruppen: Optionen, die für alle GCC-Ports verfürgbar sind und maschinenspezifische Optionen, die nur für AVR verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Aus der Masse an GCC-Optionen kann hier nur ein kleiner Auszug der wichtigsten und am häufigsten verwendeten Optionen vorgestellt werden. Eine Auflistung aller GCC-Optionen mit Kurzbeschreibung umfasst knapp 1000 Zeilen &amp;amp;#150; ohne undokumentierte Optionen, versteht sich.&lt;br /&gt;
&lt;br /&gt;
==Allgemeine Optionen für GCC==&lt;br /&gt;
; &amp;lt;tt&amp;gt;--help&amp;lt;/tt&amp;gt;: Anzeige der wichtigsten Optionen&lt;br /&gt;
; &amp;lt;tt&amp;gt;--help -v&amp;lt;/tt&amp;gt;: Überschüttet einen mit Optionen&lt;br /&gt;
; &amp;lt;tt&amp;gt;--target-help&amp;lt;br/&amp;gt;--help=target&amp;lt;/tt&amp;gt;: Anzeige der wichtigsten maschinenspezifischen Optionen und der unterstützten AVR-Derivate&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;: keine Optimierung - sinnvoll zum debuggen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O1&amp;lt;/tt&amp;gt;: Optimierung&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;: optimiert für Code-Größe – meist beste Wahl für µCs&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O2&amp;lt;/tt&amp;gt;: stärkere Optimierung für bessere Laufzeit&lt;br /&gt;
; &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;: erzeugt Debug-Informationen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-gdwarf-3 -gstrict-dwarf&amp;lt;/tt&amp;gt;: erzeugt Debug-Informationen nachdem DWARF-3 Standard und ohne GNU-spezifische Erweiterungen.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt;: (pre)compilert und assembliert nur bis zum Objekt (&amp;lt;tt&amp;gt;*.o&amp;lt;/tt&amp;gt;), kein Link-Lauf&lt;br /&gt;
; &amp;lt;tt&amp;gt;-S&amp;lt;/tt&amp;gt;: (pre)compilert nur und erzeugt Assembler-Ausgabe (&amp;lt;tt&amp;gt;*.s&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;-E&amp;lt;/tt&amp;gt;: nur Precompilat (&amp;lt;tt&amp;gt;*.i&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;*.ii&amp;lt;/tt&amp;gt;) erzeugen, kein Compilieren, kein Assemblieren, kein Linken&lt;br /&gt;
; &amp;lt;tt&amp;gt;-o &amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: legt den Name der Ausgabedatei fest&lt;br /&gt;
; &amp;lt;tt&amp;gt;-v&amp;lt;/tt&amp;gt;: zeigt Versionsinformationen an und ist geschwätzig (verbose): Anzeige der aufgerufenen tools&lt;br /&gt;
; &amp;lt;tt&amp;gt;-I&amp;lt;path&amp;gt;&amp;lt;/tt&amp;gt;: Angabe eines weiteren Include-Pfads, in dem Dateien mit &amp;lt;tt&amp;gt;#include &amp;lt;...&amp;gt;&amp;lt;/tt&amp;gt; gesucht werden&lt;br /&gt;
; &amp;lt;tt&amp;gt;-E -dM &amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Anzeige aller Defines&lt;br /&gt;
; &amp;lt;tt&amp;gt;-MM&amp;lt;/tt&amp;gt;: Für die angegebenen Eingabe-Dateien wird eine Ausgabe erzeugt, die als [[make|Makefile]]-Fragment dienen kann und die Anhängigkeiten (dependencies) der Objekte von den Quellen/Headern beschreibt.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-D&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;: Definiert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-D&amp;lt;name&amp;gt;=&amp;lt;wert&amp;gt;&amp;lt;/tt&amp;gt;: Definiert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt; zu &amp;lt;tt&amp;gt;&amp;lt;wert&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-U&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;: Undefiniert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-save-temps&amp;lt;/tt&amp;gt;: Temporäre Dateien (&amp;lt;tt&amp;gt;*.i&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.s&amp;lt;/tt&amp;gt;) werden nicht gelöscht.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wa,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;: übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Assembler (&amp;lt;tt&amp;gt;avr-as&amp;lt;/tt&amp;gt;)&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wa,-a=&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Assembler erzeugt ein Listing mit Name &amp;lt;tt&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wp,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;:  übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Preprozessor&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wl,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;:  übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Linker (&amp;lt;tt&amp;gt;avr-ld&amp;lt;/tt&amp;gt;)&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wl,-Map=&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Linker erzeugt ein Map-File mit Name &amp;lt;tt&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wl,--section-start=&amp;lt;section&amp;gt;=&amp;lt;address&amp;gt;&amp;lt;/tt&amp;gt;: Linker legt die [[avr-gcc/Interna#Sections|Section]] &amp;lt;tt&amp;gt;&amp;lt;section&amp;gt;&amp;lt;/tt&amp;gt; ab Adresse &amp;lt;tt&amp;gt;&amp;lt;address&amp;gt;&amp;lt;/tt&amp;gt;, z.B: &amp;lt;tt&amp;gt;.eeprom=0x810001&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wall&amp;lt;/tt&amp;gt;: gibt mehr Warnungen, aber immer noch nicht alle&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=gnu99&amp;lt;/tt&amp;gt;: Sagt dem Compiler, dass er C99 mit GNU-C Erweiterungen akzeptieren soll.  Das ist zum Beispiel der Fall, wenn man Embedded-C Code mit &amp;lt;tt&amp;gt;__flash&amp;lt;/tt&amp;gt; verwenden will.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c89&amp;lt;br/&amp;gt;-ansi&amp;lt;/tt&amp;gt;: bricht mit einer Fehlermeldung ab, wenn kein ANSI-C (ISO C89) verwendet wurde&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c99&amp;lt;/tt&amp;gt;: C99 mit einigen Erweiterungen, die nicht dem C99-Standard widersprechen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c99 -pedantic&amp;lt;/tt&amp;gt;: Bricht mit einer Fehlermeldung ab, wenn kein ISO C99 verwendet wird&lt;br /&gt;
&lt;br /&gt;
==Maschinenspezifische Optionen für avr-gcc==&lt;br /&gt;
&lt;br /&gt;
Maschinenabhängige Optionen beginnen immer mit '''-m'''&lt;br /&gt;
;-mmcu=xxx: Festlegen des Targets (Zielsystem/Controller), für das Code generiert werden soll. Je nach Target muss avr-gcc unterschiedliche Instruktionen verwenden und andere Startup-Dateien (&amp;lt;tt&amp;gt;crtxxx.o&amp;lt;/tt&amp;gt;) einbinden. avr-gcc setzt spezielle Defines, um auch in der Quelle zwischen den Targets unterscheiden zu können, falls das notwendig sein sollte: &lt;br /&gt;
:{| border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;0&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifdef __AVR_AT90S2313__&lt;br /&gt;
/* Code fuer AT90S2313 */&lt;br /&gt;
#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega32__)&lt;br /&gt;
/* Code fuer Mega8 und Mega32 */ &lt;br /&gt;
#else&lt;br /&gt;
#error Das ist noch nicht implementiert für diesen Controller!&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: Zwar gibt es für alle AVR-Derivate die &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt;, aber die AVR-Familien unterscheiden sich in ihrer Hardware; z.B. darin, wie I/O-Register heissen oder wie Hardware zu initialisieren ist. Diese Abhängigkeit kann man in unterschiedlichen Codestücken aufteilen und wie oben gezeigt bedingt übersetzen. Dadurch hat man Funktionalitäten wie &amp;lt;tt&amp;gt;uart_init&amp;lt;/tt&amp;gt; auf unterschiedlichen Controllern und wahrt den Überblick, weil nicht für jede Controller-Familie eine extra Datei notwendig ist.&lt;br /&gt;
&lt;br /&gt;
: Built-in Makros wie &amp;lt;tt&amp;gt;__AVR_ATmega8__&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;__AVR_ARCH__&amp;lt;/tt&amp;gt; sind ab Version 4.7 im Kapitel &amp;quot;AVR Options&amp;quot; in der GCC [[#Dokumentation|Dokumentation]] erklärt, siehe z.B. [http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html &amp;quot;AVR Built-in Macros&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
; -mint8: Datentyp &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; ist nur 8 Bit breit anstatt 16 Bit. Datentypen mit 64 Bit sind nicht verfügbar.  8-Bit &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; ist nicht C-Standard konform und wird nicht von der AVR Libc unterstützt (ausser in &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; -mno-interrupts: Ändert den Stackpointer ohne Interrupts zu deaktivieren&lt;br /&gt;
; -mcall-prologues: Funktions-Prolog und -Epilog werden als Unterroutinen umgesetzt, um die Codegröße zu verkleinern&lt;br /&gt;
; -mtiny-stack: Nur die unteren 8 Bit des Stackpointers werden verändert&lt;br /&gt;
&lt;br /&gt;
=C++=&lt;br /&gt;
&lt;br /&gt;
:''&amp;quot;C++ is a complex language and an evolving one, and its standard definition (the ISO C++ standard) was only recently completed. As a result, your C++ compiler may occasionally surprise you, even when its behavior is correct.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Zudem sollte der Einsatz von C++ aus Effizienzgründen sehr kritisch betrachtet werden:&lt;br /&gt;
:''&amp;quot;When programming C++ in space- and runtime-sensitive environments like microcontrollers, extra care should be taken to avoid unwanted side effects of the C++ calling conventions like implied copy constructors that could be called upon function invocation etc. These things could easily add up into a considerable amount of time and program memory wasted. Thus, casual inspection of the generated assembler code (using the &amp;lt;tt&amp;gt;-S&amp;lt;/tt&amp;gt; compiler option) seems to be warranted.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Weiterhin unterliegt der Einsatz von C++ je nach Compiler/Lib-Version bestimmten Einschränkungen:&lt;br /&gt;
*Einer kompletten C++ Implementierung fehlt die Unterstützung durch die &amp;lt;tt&amp;gt;libstdc++&amp;lt;/tt&amp;gt;, dadurch fehlen Standardfunktionen, -Klassen und -Templates&lt;br /&gt;
* Die Operatoren &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;delete&amp;lt;/tt&amp;gt; sind nicht implementiert, ihre Verwendung führt zu unauflösbaren externen Referenzen (Linker-Fehler)&lt;br /&gt;
*Nicht alle Header sind C++-sicher und müssen in &amp;lt;tt&amp;gt;extern &amp;quot;C&amp;quot; {...}&amp;lt;/tt&amp;gt; eingeschlossen werden.&lt;br /&gt;
*Exceptions werden nicht unterstützt und müssen via &amp;lt;tt&amp;gt;-fno-exceptions&amp;lt;/tt&amp;gt; abgeschaltet werden, oder der Linker beschwert sich über eine unauflösbare externe Referenz zu &amp;lt;tt&amp;gt;__gxx_personality_sj0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Als Treiber verwendet man wie immer avr-gcc. Standard-Endungen für C++ sind &amp;lt;tt&amp;gt;.c++&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;.cpp&amp;lt;/tt&amp;gt;. Bei anderen Endungen teilt man mit &amp;lt;tt&amp;gt;-x c++&amp;lt;/tt&amp;gt; mit, daß es sich um C++ Dateien handelt, oder ruft &amp;lt;tt&amp;gt;avr-c++&amp;lt;/tt&amp;gt; direkt auf.&lt;br /&gt;
&lt;br /&gt;
Interrupt-Service-Routinen (ISRs) sind C-Funktionen und werden definiert wie gehabt. Siehe auch [[#Interrupts|Interrupts]].&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 #if defined (__cplusplus)&lt;br /&gt;
 extern &amp;quot;C&amp;quot; {&lt;br /&gt;
 #endif {{comment|__cplusplus}}&lt;br /&gt;
 &lt;br /&gt;
 SIGNAL (SIG_NAME)&lt;br /&gt;
 {&lt;br /&gt;
    {{comment|machwas}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 INTERRUPT (SIG_NAME)&lt;br /&gt;
 {&lt;br /&gt;
    {{comment|mach was}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #if defined (__cplusplus)&lt;br /&gt;
 }&lt;br /&gt;
 #endif {{comment|__cplusplus}}&lt;br /&gt;
&amp;lt;tt&amp;gt;__cplusplus&amp;lt;/tt&amp;gt; ist ein Standard [[avr-gcc/Interna#Builtin Defines|GCC-Builtin-Define]].&lt;br /&gt;
&lt;br /&gt;
Globale Konstruktoren werden in [[avr-gcc/Interna#Sections|Section]] &amp;lt;tt&amp;gt;.init6&amp;lt;/tt&amp;gt; ausgeführt, die Destruktoren in &amp;lt;tt&amp;gt;.fini6&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Code-Beispiele=&lt;br /&gt;
Dieser Abschnitt enthält Code-Schnippsel für avr-gcc. Es werden Besonderheiten besprochen, die für avr-gcc zu beachten sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Abschnitt ist ''kein'' [[C-Tutorial|Tutorial zur C-Programmierung]] und ''keine'' Einführung in die Programmiersprache C im allgemeinen. Dafür sei auf einschlägige Tutorials/Bücher verwiesen.&lt;br /&gt;
&lt;br /&gt;
==Zugriff auf Special Function Registers (SFRs)==&lt;br /&gt;
&lt;br /&gt;
===Zugiff auf Bytes und Worte===&lt;br /&gt;
Für den Zugriff auf die SFRs gibt es Defines über den Include&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
Abhängig vom eingestellten Controller werden dann Defines eingebunden, über die auf SFRs wie auf normale Variablen zugegriffen werden kann. Die Namen der Defines sind i.d.R. die gleichen wie im AVR-Manual, also z.b. &amp;lt;tt&amp;gt;SREG&amp;lt;/tt&amp;gt; für das Prozessorstatus-Register SREG:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 ...&lt;br /&gt;
   {{ccomment|SREG lesen}}&lt;br /&gt;
   uint8_t sreg = SREG;&lt;br /&gt;
   ...&lt;br /&gt;
   {{ccomment|SREG schreiben}}&lt;br /&gt;
   SREG = sreg;&lt;br /&gt;
&amp;lt;!--  &lt;br /&gt;
Auf SFRs wird generell über deren Adresse zugegriffen:&lt;br /&gt;
 {{ccomment|Liest den Inhalt von SREG an Adresse 0x5f}}&lt;br /&gt;
 unsigned char sreg = *((unsigned char volatile*) 0x5f);&lt;br /&gt;
Das bedeutet in etwa: &amp;quot;Lies ein flüchtiges (&amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt;) Byte (&amp;lt;tt&amp;gt;unsigned char&amp;lt;/tt&amp;gt;) von Adresse &amp;lt;tt&amp;gt;0x5f&amp;lt;/tt&amp;gt;&amp;quot;. Der Speicherinhalt von SFRs ist flüchtig, denn er kann sich ändern, ohne daß avr-gcc dies mitbekommt. Daher muss bei jedem C-Zugriff auf ein SFR dieses wirklich gelesen/geschrieben werden, was der Qualifier &amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt; sicherstellt. Ansonst geht der Compiler u.U. davon aus, daß der Inhalt bekannt ist und verwendet einen alten, in einem GPR befindlichen Wert.&lt;br /&gt;
&lt;br /&gt;
Um lesbaren, weniger fehleranfälligen und unter AVRs halbwegs portierbaren Code zu erhalten, gibt es Makrodefinitionen im Controller-spezifischen Header &amp;lt;tt&amp;gt;ioxxxx.h&amp;lt;/tt&amp;gt;, der neben anderen Dingen mit &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; includet wird:&lt;br /&gt;
Die Bezeichner der SFRs sind die gleichen wie im Manual.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Für einen Überblick über die eingebundenen Defines kann ein Blick in den Controller-spezifischen Header hilfreich sein. Dieser befindet sich in&lt;br /&gt;
:&amp;lt;tt&amp;gt; &amp;amp;lt;GCC_HOME&amp;amp;gt;/avr/include/avr/io****.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
z.B. &amp;lt;tt&amp;gt;iom32.h&amp;lt;/tt&amp;gt; für einen [[ATmega32]].&lt;br /&gt;
&lt;br /&gt;
Dieser Zugriff geht auch für 16-Bit Register wie &amp;lt;tt&amp;gt;TCNT1&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;ADC&amp;lt;/tt&amp;gt;, für die eine bestimmte Reihenfolge für den Zugriff auf Low- und High-Teil eingehalten werden muss: avr-gcc generiert die Zugriffe in der richtigen Reihenfolge.&lt;br /&gt;
  uint16_t tcnt1 = TCNT1;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Zu beachten ist, daß dieser Zugriff nicht atomar erfolgt. Das Lesen/Schreiben mehrbytiger Werte muss vom Compiler in mehrere Byte-Zugriffe zerlegt werden. Zwischen diesen Zugriffen kann ein [[Interrupt]] auftreten, wenn Interrupts aktiviert sind. Je nach Programm und welche Aufgaben eine [[ISR]] erledigt, kann dies zu Fehlfunktion führen. In dem Fall müssen diese Code-Stücke atomar gemacht werden, damit sie nicht durch einen [[IRQ]] unterbrochen werden können!&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Zugriff auf einzelne Bits===&lt;br /&gt;
Zugriff auf Bits geht wie gewohnt mit den Bitoperationen &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;amp;&amp;lt;/tt&amp;gt; (and),&lt;br /&gt;
&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt; (or),&lt;br /&gt;
&amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt; (xor) und&lt;br /&gt;
&amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt; (not)&lt;br /&gt;
&lt;br /&gt;
Wieder gibt es Defines in den AVR-Headern, mit denen man Masken für den Zugriff erhalten kann, etwa:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* GIMSK / GICR */&lt;br /&gt;
#define INT1    7&lt;br /&gt;
#define INT0    6&lt;br /&gt;
#define IVSEL   1&lt;br /&gt;
#define IVCE    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Masken ergeben sich durch Schieben von &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; an die richtige Position:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_0 und B_1 als Ausgang&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB0) | (1&amp;amp;lt;&amp;amp;lt;PB1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erzeugt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
87 b3           in      r24, 0x17&lt;br /&gt;
83 60           ori     r24, 0x03&lt;br /&gt;
87 bb           out     0x17, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Etwas anders sieht der Code aus, wenn die Bits einzeln gesetzt werden und das Register im bitadressierbaren Bereich liegt (SRAM &amp;lt;tt&amp;gt;0x20&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;0x3f&amp;lt;/tt&amp;gt; resp. I/O &amp;lt;tt&amp;gt;0x0&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;0x1f&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_0 und B_1 als Ausgang&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB0);&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erzeugt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
b8 9a           sbi     0x17, 0&lt;br /&gt;
b9 9a           sbi     0x17, 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um Bits zu löschen, erzeugt man eine Maske, die an der betreffenden Stelle eine &amp;amp;nbsp;0 hat:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_2 als Eingang&lt;br /&gt;
DDRB &amp;amp;= ~(1&amp;amp;lt;&amp;amp;lt;PB2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen| &lt;br /&gt;
Auch hier ist zu beachten, daß es Probleme geben kann, wenn nicht atomarer Code erzeugt wird, weil der AVR-Befehlssatz nicht mehr hergibt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// toggle PORT B_0: wechseln 0 &amp;amp;lt;--&amp;amp;gt; 1 &lt;br /&gt;
PORTB ^= (1&amp;amp;lt;&amp;amp;lt;PB0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
88 b3           in      r24, 0x18&lt;br /&gt;
; Wenn hier ein Interrupt auftritt, in dessen ISR PORTB verändert wird,&lt;br /&gt;
; dann wird die Änderung durch die letzte Instruktion wieder überschrieben!&lt;br /&gt;
91 e0           ldi     r25, 0x01&lt;br /&gt;
; dito&lt;br /&gt;
89 27           eor     r24, r25&lt;br /&gt;
; dito&lt;br /&gt;
88 bb           out     0x18, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
}} &amp;lt;!-- /FarbigerRahmen --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Auch das Lesen einzelner Port-Pins geht über das Maskieren von SFRs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DDRB &amp;amp;= ~(1 &amp;lt;&amp;lt; PB2);    // PortB.2 als INPUT &lt;br /&gt;
&lt;br /&gt;
if (PINB &amp;amp; (1 &amp;lt;&amp;lt; PB2))&lt;br /&gt;
   // PortB.2 ist HIGH&lt;br /&gt;
else&lt;br /&gt;
   // PortB.2 ist LOW&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if (!(PINB &amp;amp; (1 &amp;lt;&amp;lt; PB2)))&lt;br /&gt;
   // PortB.2 ist LOW&lt;br /&gt;
else&lt;br /&gt;
   // PortB.2 ist HIGH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interrupts==&lt;br /&gt;
&lt;br /&gt;
: → ''[http://nongnu.org/avr-libc/user-manual/group__avr__interrupts.html AVR-Libc: Dokumentation zu &amp;lt;tt&amp;gt;&amp;lt;avr/interrupt.h&amp;gt;&amp;lt;/tt&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
Um zu kennzeichnen, daß es sich bei einer Funktion um eine Interrupt Sevice Routine (ISR) handelt, gibt es spezielle Attribute. Diese brauchen nicht explizit hingeschrieben zu werden, ebensowenig wie die genaue Nummer des Interrupt Requests (IRQ). Dafür gibt es Includes aus der AVR Libc und die folgenden Makros.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Eine nichtunterbrechbare Interrupt-Service-Routine}}&lt;br /&gt;
 ISR (TIMER1_COMPA_vect)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|ISR-Code}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Eine unterbrechbare Interrupt-Service-Routine}}&lt;br /&gt;
 ISR (TIMER0_OVF_vect, ISR_NOBLOCK)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|ISR-Code}}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die Funktion mit dem richtigen Prolog/Epilog erzeugt, und es wird ein Eintrag in die Interrupt-Vektortabelle gemacht – bei obigem Beispiel also zwei Einträge.&lt;br /&gt;
&lt;br /&gt;
Mit Ausführung einer ISR deaktiviert die AVR-Hardware die Interrupts, so daß die ISR nicht durch andere Interrupt-Anforderungen unterbrochen wird. Beim Verlassen der ISR werden Interrupts wieder automatisch durch die AVR-Hardware aktiviert. Tritt während der ISR ein IRQ auf, wird diese erst nach Beenden des ISR-Codes ausgeführt. Der Interrupt geht also nicht verloren.  Dies gilt allerding nicht für Level-getriggerte IRQs wie für manche externen Interrupts oder TWI-Interrupts.  &lt;br /&gt;
&lt;br /&gt;
Zwischen zwei ISRs wird zusätzlich mindestens ein Befehl des normalen Programm-Codes abgearbeitet.&lt;br /&gt;
&lt;br /&gt;
Nachschlagen kann man die ISR-Namen im Device-spezifischen Header, die im Installationsverzeichnis liegen:&lt;br /&gt;
:&amp;lt;tt&amp;gt;&amp;amp;lt;GCC_HOME&amp;amp;gt;/avr/include/avr/ioxxxx.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interrupts aktivieren===&lt;br /&gt;
&lt;br /&gt;
Damit eine ISR überhaupt zur Ausführung kommt, müssen drei Bedingungen erfüllt sein&lt;br /&gt;
* Interrupts müssen global aktiviert sein&lt;br /&gt;
* Der entsprechen IRQ muss aktiviert worden sein&lt;br /&gt;
* Das zum IRQ gehörende Ereignis muss eintreten&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
    {{ccomment|enable OutputCompareA Interrupt für Timer1}}&lt;br /&gt;
    TIMSK |= (1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|disable OutputCompareA Interrupt für Timer1}}&lt;br /&gt;
    TIMSK &amp;amp;= ~(1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts aktivieren}}&lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts abschalten}}&lt;br /&gt;
    cli();&lt;br /&gt;
Sperrt man eine Code-Sequenz durch Einschachteln in ein &amp;lt;tt&amp;gt;cli&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sei&amp;lt;/tt&amp;gt; Paar (man macht das Codestück &amp;quot;atomar&amp;quot;, also ununterbrechbar), gehen währenddessen keine Interrupt-Anforderungen verloren. Die entsprechenden IRQ-Flags bleiben gesetzt, und nach dem &amp;lt;tt&amp;gt;sei&amp;lt;/tt&amp;gt; werden die IRQs in der Reihenfolge ihrer Prioritäten abgearbeitet. Ausnahme ist, wenn in einem atomaren Block der selbe IRQ mehrfach auftritt. Der ISR-Code wird dann trotzdem nur einmal ausgeführt.&lt;br /&gt;
&lt;br /&gt;
===default Interrupt===&lt;br /&gt;
&lt;br /&gt;
Für nicht implementierte Interrupts macht avr-gcc in die Vektortabelle einen Eintrag,&lt;br /&gt;
der zu &amp;lt;tt&amp;gt;__bad_interrupt&amp;lt;/tt&amp;gt; (definiert im Startup-Code &amp;lt;tt&amp;gt;crt*.o&amp;lt;/tt&amp;gt;) springt&lt;br /&gt;
und von dort aus weiter zu Adresse&amp;amp;nbsp;0. &lt;br /&gt;
Dadurch läuft der AVR wieder von neuem los, wenn ein Interrupt auftritt, &lt;br /&gt;
zu dem man keine ISR definiert hat &lt;br /&gt;
&amp;amp;#150; allerdings ohne die Hardware zurückzusetzen wie bei einem echten Reset.&lt;br /&gt;
&lt;br /&gt;
Möchte man diesen Fall abfangen, dann geht das über eine globale Funktion &lt;br /&gt;
namens &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ISR (__vector_default)&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit wird von &amp;lt;tt&amp;gt;__bad_interrupt&amp;lt;/tt&amp;gt; aus nicht nach Adresse&amp;amp;nbsp;0 gesprungen,&lt;br /&gt;
sondern weiter zu &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt;, welches durch &amp;lt;tt&amp;gt;ISR()&amp;lt;/tt&amp;gt; den üblichen ISR-Prolog/Epilog bekommt.&lt;br /&gt;
&lt;br /&gt;
So kann man z.B. eine Meldung ausgeben, eine Warnlampe blinken, in einer Endlosschleife landen, oder über den [[Watchdog]] einen richtigen Hardware-Reset auslösen, siehe auch Abschnitt &amp;quot;[[#Reset auslösen|Reset auslösen]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===ISR mit eigenem Prolog/Epilog===&lt;br /&gt;
&lt;br /&gt;
Wenn man in einer ISR komplett eigenes Zeug machen will, &lt;br /&gt;
dann definiert man eine naked Funktion.&lt;br /&gt;
Mit &amp;lt;tt&amp;gt;naked&amp;lt;/tt&amp;gt; befreit man die Routine vom Standard-Prolog/Epilog.&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Dabei ist darauf zu achten, daß die ISR mit &amp;lt;tt&amp;gt;reti&amp;lt;/tt&amp;gt; (return from interrupt) &lt;br /&gt;
zurückkehrt und evtl. verwendete Register und den Status (&amp;lt;tt&amp;gt;SREG&amp;lt;/tt&amp;gt;) sichert.&lt;br /&gt;
&lt;br /&gt;
Komplexer oder nicht optimierter C-Code, der einen Framepointer braucht, funktioniert nicht mehr weil ohne Prolog der Framepointer nicht initialisiert wird. Die geschieht wenn nicht alle Werte in Registern gehalten werden können und vom Compiler auf dem Stack zwischengespeichert werden.&lt;br /&gt;
}}&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 ISR (TIMER0_OVF_vect, ISR_NAKED)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|Port B.6 &amp;amp;#61; 0}}&lt;br /&gt;
    {{ccomment|Diese Instruktion verändert nicht das SREG und kein anderes Register}}&lt;br /&gt;
    {{ccomment|so daß der eigentliche Code nur 1 Befehl lang ist}}&lt;br /&gt;
    __asm__ __volatile (&lt;br /&gt;
       &amp;quot;cbi %0, %1&amp;quot; &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;reti&amp;quot;&lt;br /&gt;
          : &lt;br /&gt;
          : &amp;quot;M&amp;quot; (_SFR_IO_ADDR (PORTB)), &amp;quot;i&amp;quot; (6)&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Siehe auch [[Inline-Assembler in avr-gcc]].&lt;br /&gt;
Die ISR sieht dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
__vector_9:&lt;br /&gt;
   c6 98        cbi   0x18, 6&lt;br /&gt;
   18 95        reti&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wiederum kann man als Funktionsname &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt; nehmen,&lt;br /&gt;
um nicht-implementierte IRQs abzufangen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __attribute__ ((naked, used))&lt;br /&gt;
__vector_default (void)&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SRAM, Flash, EEPROM: Datenablage am Beispiel Strings==&lt;br /&gt;
Die Programmiersprache C kennt selber keine Strings; das einzige, was C bekannt ist, ist der Datentyp &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;, der ein einzelnes Zeichen repräsentiert. &lt;br /&gt;
===Darstellung in C===&lt;br /&gt;
Ein String im Sinne von C ist ein Array von Charactern bzw. ein Zeiger auf den Anfang des Arrays. Die einzelnen Zeichen folgen im Speicher direkt aufeinander und werden in aufsteigenden Adressen gespeichert. Am String-Ende folgt als Abschluss der Character &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;, um das Ende zu kennzeichnen. Dies ist besonders bei der Berechnung des Speicherplatzes für Strings zu berücksichtigen, denn für die 0 muss auch Platz reserviert werden.&lt;br /&gt;
&lt;br /&gt;
===Bestimmen der Stringlänge===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /* Bestimmt die Laenge des Strings ohne die abschliessende '\0' zu zaehlen */&lt;br /&gt;
 unsigned int strlength (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
   unsigned int len = 0;&lt;br /&gt;
   &lt;br /&gt;
   while (*str++)&lt;br /&gt;
      len++;&lt;br /&gt;
   &lt;br /&gt;
   return len;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Stringlänge kann auch mit der Standard-Funktion &amp;lt;tt&amp;gt;strlen&amp;lt;/tt&amp;gt; bestimmt werden, deren Prototyp sich in &amp;lt;tt&amp;gt;string.h&amp;lt;/tt&amp;gt; befindet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
 size_t strlen (const char*);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String im Flash belassen===&lt;br /&gt;
Oftmals werden Strings nur zu Ausgabezwecken verwendet und nicht verändert. Verwendet man Sequenzen der Gestalt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 char *str1 = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 char str2[] = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
dann werden die Strings im SRAM abgelegt. Im Startup-Code werden die Strings vom Flash ins SRAM kopiert und belegen daher sowohl Platz im SRAM als auch im Flash. Wird ein String nicht verändert, braucht er nicht ins SRAM kopiert zu werden. Das spart Platz im knapp bemessenen SRAM. Allerdings muss anders auf den String zugegriffen werden, denn wegen der Harvard-Architektur des AVR-Kerns kann avr-gcc anhand der Adresse nicht unterscheiden, ob diese ins SRAM, ins Flash oder ins EEPROM zeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 const char str3[] PROGMEM = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 size_t strlen_P (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len = 0;&lt;br /&gt;
 &lt;br /&gt;
    while (1)&lt;br /&gt;
    {&lt;br /&gt;
       char c = (char) pgm_read_byte (str);&lt;br /&gt;
       if ('\0' == c)&lt;br /&gt;
          return len;&lt;br /&gt;
       len++;&lt;br /&gt;
       str++; &lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void foo (void)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len;&lt;br /&gt;
    len = strlen_P (str3);&lt;br /&gt;
    len = strlen_P (PSTR (&amp;quot;String im Flash&amp;quot;));&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String ins EEPROM legen===&lt;br /&gt;
Dies geht nach dem gleichen Muster, nach dem Strings ins Flash gelegt werden. Der Zugriff wird vergleichsweise langsam, denn der EEPROM ist langsamer als SRAM bzw. Flash.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 const char str4[] EEMEM = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 size_t strlen_EE (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len = 0;&lt;br /&gt;
 &lt;br /&gt;
    while (1)&lt;br /&gt;
    {&lt;br /&gt;
       char c = (char) eeprom_read_byte (str);&lt;br /&gt;
       if ('\0' == c)&lt;br /&gt;
          return len;&lt;br /&gt;
       len++;&lt;br /&gt;
       str++; &lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Reset auslösen==&lt;br /&gt;
&lt;br /&gt;
Falls ein Reset per Software ausgelöst werden soll, dann geht das am besten über den [[Watchdog]].&lt;br /&gt;
Einfach nur an den Reset-Punkt an Adresse&amp;amp;nbsp;0 zu springen&lt;br /&gt;
initialisiert zwar den Controller von neuem, aber es macht keinen wirkliches RESET mit Zurücksetzen der Hardware und allen I/O-Registern. &lt;br /&gt;
&lt;br /&gt;
Durch den Watchdog kann man ein 'richtiges' RESET-Signal erzeugen lassen, so daß die AVR-Hardware genau so initialisiert ist, wie nach einem externen RESET. So kann man z.B. via [[UART]] ein RESET-Kommando schicken. Allerdings lässt sich der Watchdog nur minimal auf 15ms einstellen:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 ...   &lt;br /&gt;
    cli();                     {{ccomment|Interrupts global abschalten}}&lt;br /&gt;
    wdt_enable (WDTO_15MS);    {{ccomment|Watchdog aufziehen auf 15ms}}&lt;br /&gt;
    while (1);                 {{ccomment|warten, bis er zubeisst...}}&lt;br /&gt;
&lt;br /&gt;
Welches Ereignis einen RESET ausgelöst hat, kann man im Register '''MCUCSR''' (''MCU Control and Status Register'') erfahren. Es gibt 4 mögliche RESET-Quellen:&lt;br /&gt;
* Power-On Reset&lt;br /&gt;
* External Reset&lt;br /&gt;
* Brown-Out Reset&lt;br /&gt;
* Watchdog Reset&lt;br /&gt;
&lt;br /&gt;
Soll der Inhalt von Variablen einen Reset überleben &amp;amp;ndash; eine Variable also nicht initialisiert werden &amp;amp;ndash; dann geht das so:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment| status informiert z.B. darüber, ob wir selber den Watchdog ausgelöst haben }}&lt;br /&gt;
 {{ccomment| oder nicht, oder andere Informationen }}&lt;br /&gt;
 uint8_t status __attribute__ ((__section__ (&amp;quot;.noinit&amp;quot;)));&lt;br /&gt;
 &lt;br /&gt;
 int main (void)&lt;br /&gt;
 {&lt;br /&gt;
     {{ccomment|Wert von MCUSCR merken, möglichst früh im Programm }}&lt;br /&gt;
     uint8_t mcucsr = MCUCSR;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|MCUCSR zurücksetzen }}&lt;br /&gt;
     MCUCSR = 0;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Watchdog-Reset }}&lt;br /&gt;
     if (mcuscr &amp;amp; (1 &amp;lt;&amp;lt; WDRF))&lt;br /&gt;
     {&lt;br /&gt;
         {{ccomment|status auswerten }}&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Power-On Reset: status auf definierten Wert setzen }}&lt;br /&gt;
     if (mcuscr &amp;amp; (1 &amp;lt;&amp;lt; PORF))&lt;br /&gt;
     {&lt;br /&gt;
         status = 0;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|status auswerten }}&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; An Adresse 0 springen&lt;br /&gt;
&lt;br /&gt;
Falls wirklich zu Adresse 0 gesprungen werden soll – was in einem Bootloader erforderlich sein kann – dann geschieht das mittels einer Funktion &amp;lt;tt&amp;gt;reset&amp;lt;/tt&amp;gt; wie folgt:&lt;br /&gt;
 extern void reset (void) __attribute__((noreturn));&lt;br /&gt;
 reset();&lt;br /&gt;
&amp;lt;tt&amp;gt;reset&amp;lt;/tt&amp;gt; wird bein Linken mittels &amp;lt;tt&amp;gt;-Wl,--defsym=reset=0&amp;lt;/tt&amp;gt; auf&amp;amp;nbsp;0&amp;amp;nbsp;gesetzt.&lt;br /&gt;
Weitere Möglichkeit ist, im erzeugten Assembler&amp;amp;nbsp;&amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; als Funktionsnamen zu verwenden:&lt;br /&gt;
 extern void reset (void) __asm__(&amp;quot;0&amp;quot;) __attribute__((__noreturn__));&lt;br /&gt;
 reset();&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
&lt;br /&gt;
Die mit&lt;br /&gt;
 #include &amp;lt;...&amp;gt;&lt;br /&gt;
angegebenen Includes werden von avr-gcc in den &lt;br /&gt;
mit der Option '&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;' anegegenen Pfaden gesucht. &lt;br /&gt;
Dem Compiler bekannt sind die Pfade &lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/avr/include                           Standard               (stdio.h, ...)&lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/avr/include/avr                       AVR-spezifisch         (avr/io.h, ...)&lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/lib/gcc/avr/&amp;lt;GCC_VERSION&amp;gt;/include     Standard, compilerabh. (limits.h, ...)&lt;br /&gt;
&lt;br /&gt;
Gibt man z.B. an &lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
dann wird automatisch in diesem Verzeichnis nach &amp;lt;tt&amp;gt;stdio.h&amp;lt;/tt&amp;gt; gesucht.&lt;br /&gt;
In den Verzeichnissen stehen Standard-Includes, die benötigt werden, wenn man libc-Funktionen &lt;br /&gt;
oder mathematische Funktionen etc. verwendet. &lt;br /&gt;
AVR-spezifische Dinge stehen im Unterverzeichnis &amp;lt;tt&amp;gt;avr&amp;lt;/tt&amp;gt;, etwa:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Als Pfad-Separator wird immer ein '''&amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;''' verwendet, auch auf Windows-Betriebssystemen! Also kein '''&amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;'''&amp;amp;nbsp;!&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Standard==&lt;br /&gt;
&lt;br /&gt;
 ctype.h                   Zeichen-Umwandlungs-Makros und ctype Makros&lt;br /&gt;
 errno.h                   Symbolische Namen für Fehlercodes&lt;br /&gt;
 stdint, inttypes.h        C99 definiert [u]intN_t wenn man genau N [un]signed&lt;br /&gt;
                           Bits braucht&lt;br /&gt;
 math.h                    Mathematische Funktionen: sin, cos, log, gamma, bessel, ...&lt;br /&gt;
 setjmp.h                  libc unterstützt setjmp() und longjmp(), um direkt in eine&lt;br /&gt;
                           andere (nicht-lokale) Funktion zu springen. &lt;br /&gt;
 stdio.h                   Standard I/O-Funktionen (printf, fscanf, ...)&lt;br /&gt;
 stdlib.h                  Deklariert grundlegende ISO C Makros und Funktionen &lt;br /&gt;
                           sowie einige AVR-spezifische Erweiterungen&lt;br /&gt;
 string.h                  Stringoperationen auf NULL-terminierten Strings. (strlen, ...)&lt;br /&gt;
 stdarg.h                  Funktionen mit variabler Argumenanzahl&lt;br /&gt;
 limits.h                  Min- und Max-Werte von Skalaren (UCHAR_MAX, LONG_MIN, ...)&lt;br /&gt;
&lt;br /&gt;
==AVR-spezifisch==&lt;br /&gt;
&lt;br /&gt;
Die AVR-spezifischen Includes finden sich wie gesagt im Unterverzeichnis &amp;lt;tt&amp;gt;avr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Die meisten dort befindlichen Header wird man nie direkt durch Angabe im C-File erhalten,&lt;br /&gt;
sondern durch Angabe von&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
Dadurch werden genau die I/O-Header eingebunden, die zum AVR-Modell passen, also  z.B. &amp;lt;tt&amp;gt;avr/iom8.h&amp;lt;/tt&amp;gt; für [[ATmega8]] etc.  Verantwortlich für die Auswahl des richtigen Sub-Headers ist der Schalter '&amp;lt;tt&amp;gt;-mmcu=xxx&amp;lt;/tt&amp;gt;'.&lt;br /&gt;
&lt;br /&gt;
Obwohl diese Sub-Header nicht explizit angegeben werden müssen, &lt;br /&gt;
kann ein Blick dorthin hilfreich sein, um die Namen von [[SFR|SFRs]] &lt;br /&gt;
oder Signals nachzuschlagen. &lt;br /&gt;
Diese Header werden im folgenden nicht alle einzeln aufgelistet. &lt;br /&gt;
Ihre Namen sind immer &amp;lt;tt&amp;gt;avr/io*.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* für ATmega: &amp;lt;tt&amp;gt;avr/iom*.h&amp;lt;/tt&amp;gt; &lt;br /&gt;
* für ATtiny: &amp;lt;tt&amp;gt;avr/iotn*.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avr/boot.h            Bootloader Support&lt;br /&gt;
avr/eeprom.h          EEPROM-Routinen&lt;br /&gt;
avr/interrupt.h       sei(), cli(), ISR(), ...&lt;br /&gt;
avr/io.h              RAMEND, ***_vect, SFRs: PORTB, DDRB, PINB, SREG, ..., &lt;br /&gt;
avr/pgmspace.h        Zugriff aufs Flash: Byte lesen, PROGMEM, pgm_read_***, ...&lt;br /&gt;
avr/sleep.h           Power-Safe und Sleep-Modes&lt;br /&gt;
avr/wdt.h             Watchdog&lt;br /&gt;
&lt;br /&gt;
util/crc16.h          Prüfsumme CRC16&lt;br /&gt;
util/delay.h          Verzögerungsschleifen für kurze, exakte Verzögerungen &lt;br /&gt;
util/parity.h         Parität&lt;br /&gt;
util/twi.h            I2C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anwendungs-spezifisch==&lt;br /&gt;
Eigene Header, die nur innerhalb eigener Projekte gebraucht werden, includet man mit&lt;br /&gt;
 #include &amp;quot;...&amp;quot;&lt;br /&gt;
Auch hier darf man Unterverzeichnisse angeben oder ins übergeordnete Verzeichnis:&lt;br /&gt;
 #include &amp;quot;../../mein-zeug.h&amp;quot;&lt;br /&gt;
Mit der Option &amp;lt;tt&amp;gt;-I&amp;lt;path&amp;gt;&amp;lt;/tt&amp;gt; kann ein Pfad zu den bekannten Include-Pfaden hinzugefügt werden; im obigen Beispiel etwa &amp;lt;tt&amp;gt;-I../..&amp;lt;/tt&amp;gt; und im Programm dann:&lt;br /&gt;
 #include &amp;quot;mein-zeug.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Optimierungen, Tipps &amp;amp; Tricks =&lt;br /&gt;
:→ ''Hauptartikel: [[avr-gcc/Optimierungen|avr-gcc Optimierungen]]''&lt;br /&gt;
&lt;br /&gt;
=Abkürzungen und Bezeichnungen=&lt;br /&gt;
; [[GCC]]: GNU Compiler Collection&lt;br /&gt;
; gcc: GNU C-Compiler&lt;br /&gt;
; GPR: '''G'''eneral '''P'''urpose '''R'''egister&lt;br /&gt;
; [[ISR]]: [[Interrupt|'''I'''nterrupt]] '''S'''ervice '''R'''outine&lt;br /&gt;
; [[IRQ]]: '''I'''nterrupt '''R'''e'''q'''uest&lt;br /&gt;
; Prolog/Epilog: Code am Anfang/Ende jeder Funktionen/ISR, der dazu dient, verwendete Register zu sichern, den Stack-Frame für lokale [[Variable|Variablen]] anzulegen (falls benötigt), Stackpointer zu setzen, zurück zu springen (&amp;lt;tt&amp;gt;ret&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;reti&amp;lt;/tt&amp;gt;), etc.&lt;br /&gt;
; SFR: '''S'''pecial '''F'''unction '''R'''egister&lt;br /&gt;
; Target: Zielsystem, in unserem Falle avr&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[C-Tutorial]]&lt;br /&gt;
'''Code-Beispiele'''&lt;br /&gt;
* [[Hallo Welt für AVR (LED blinken)]] - ein erstes Beispiel für avr-gcc&lt;br /&gt;
*[[:Kategorie:Quellcode_C|C-Codebeispiele]]&lt;br /&gt;
* [[Fallstricke bei der C-Programmierung]]&lt;br /&gt;
&lt;br /&gt;
'''Details'''&lt;br /&gt;
* [[Inline-Assembler in avr-gcc|Inline-Assembler]]&lt;br /&gt;
* [[avr-gcc/Interna|Interna von avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
'''Installation (Linux)'''&lt;br /&gt;
* [[Linuxdistribution_Avr-live-cd]]&lt;br /&gt;
* [[avr-gcc und avrdude installieren]]&lt;br /&gt;
'''Sonstiges'''&lt;br /&gt;
* [[WinAVR]]&lt;br /&gt;
* [[Speicherverbrauch bestimmen mit avr-gcc]]&lt;br /&gt;
* [[Compiler]]&lt;br /&gt;
* [[Dev-Cpp IDE]]&lt;br /&gt;
* [[AVR]]&lt;br /&gt;
----&lt;br /&gt;
* [[Sourcevergleich]]&lt;br /&gt;
* [[Codevergleich AVR-Compiler]]&lt;br /&gt;
&lt;br /&gt;
=Weblinks=&lt;br /&gt;
==Dokumentation==&lt;br /&gt;
&lt;br /&gt;
;Offline:&lt;br /&gt;
&lt;br /&gt;
Je nach Distribution wird diese mit offline-Dokumentation als pdf, HTML, etc. ausgeliefert, die dann z.B. in Ordern wie den folgenden befindet:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;GCC_HOME&amp;gt;/doc/gcc/&lt;br /&gt;
: &amp;lt;GCC_HOME&amp;gt;/doc/avr-libc/&lt;br /&gt;
: etc.&lt;br /&gt;
&lt;br /&gt;
; Online&lt;br /&gt;
&lt;br /&gt;
* [http://gcc.gnu.org/onlinedocs/cpp.pdf cpp.pdf (470 kByte)] - Dokumentation des C-Präprozessors (en)&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/pages.html AVR Libc: User Manual] - Dokumentation zur [http://www.nongnu.org/avr-libc AVR Libc].&lt;br /&gt;
* [http://sourceware.org/binutils/docs/ Binutils: Documentation] – Dokumentation der Binutils: Assembler, Linker, ...&lt;br /&gt;
* [http://gcc.gnu.org/wiki/avr-gcc avr-gcc im GCC Wiki] – Dokumentation des Application Binary Interface (ABI): Registerverwendung, Calling Conventions, ...&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
! [http://gcc.gnu.org GCC] Version ||colspan=&amp;quot;2&amp;quot;| [http://gcc.gnu.org/onlinedocs Dokumentation] || AVR Options || Release Notes&lt;br /&gt;
|-&lt;br /&gt;
! Aktuelle Entwicklung&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-5/changes.html GCC 5]&lt;br /&gt;
|-&lt;br /&gt;
! 4.9.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.9/changes.html GCC 4.9]&lt;br /&gt;
|-&lt;br /&gt;
! 4.8.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.8/changes.html GCC 4.8]&lt;br /&gt;
|-&lt;br /&gt;
! 4.7.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.7/changes.html GCC 4.7]&lt;br /&gt;
|-&lt;br /&gt;
! 4.6.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.6/changes.html GCC 4.6]&lt;br /&gt;
|-&lt;br /&gt;
! 4.5.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.5/changes.html GCC 4.5]&lt;br /&gt;
|-&lt;br /&gt;
! 4.4.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.4/changes.html GCC 4.4]&lt;br /&gt;
|-&lt;br /&gt;
! 4.3.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.3/changes.html GCC 4.3]&lt;br /&gt;
|-&lt;br /&gt;
! 3.4.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-3.4/changes.html GCC 3.4]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Downloads==&lt;br /&gt;
* [http://sourceforge.net/projects/winavr/ WinAVR-Projekt bei sourceforge.net (en)]&lt;br /&gt;
* [http://cdk4avr.sourceforge.net/ avr-gcc und toolchain als Linux-Paket bei sourceforge.net (en)]&lt;br /&gt;
* [[Linuxdistribution_Avr-live-cd]]&lt;br /&gt;
== Tipps, Installation ==&lt;br /&gt;
*[http://www.nongnu.org/avr-libc/user-manual/install_tools.html ''&amp;quot;Installing the GNU Tool Chain&amp;quot;''] Hilfe zum Build und Installation von GCC, binutils, etc unter Linux&lt;br /&gt;
* Im GCC-Handbuch, siehe [[#Dokumentation|Dokumentation]].&lt;br /&gt;
* [http://www.linuxfocus.org/Deutsch/November2004/article352.shtml www.linuxfocus.org (Artikel)] - Tipps zu Build und Installation von avr-gcc, binutils und avr-libc unter Linux&lt;br /&gt;
* [http://users.rcn.com/rneswold/avr/ Rich Neswold: ''A GNU Development Environment for the AVR Microcontroller'']&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/24166 www.mikrocontroller.net (Foren-Beitrag)] - Installation von GCC und Toolchain unter Mac OS X&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=125603#125603 www.roboternetz.de (Foren-Beitrag)] ''avrgcc + avrdude installieren''&lt;br /&gt;
* [http://roboternetz.de/download/c_tutorial.zip AVR-Studio &amp;amp; C-Tutorial mit Installationsanleitung]&lt;br /&gt;
&lt;br /&gt;
== Sonstiges ==&lt;br /&gt;
* [http://gcc.gnu.org/ Offizielle Homepage von GCC (en)]&lt;br /&gt;
* [http://de.wikipedia.org/wiki/GNU_Compiler_Collection GCC in der deutschen Wikipedia]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial avr-gcc-Tutorial auf mikrocontroller.net]&lt;br /&gt;
* [http://savannah.nongnu.org/projects/avr-libc/ Nützliche GCC Runtime-Libary]&lt;br /&gt;
* [http://www.stromflo.de/dokuwiki/doku.php Atxmega-C-Tutorial]&lt;br /&gt;
&lt;br /&gt;
=Autor=&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 11:27, 7. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Praxis]]&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Inline-Assembler_in_avr-gcc&amp;diff=25254</id>
		<title>Inline-Assembler in avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Inline-Assembler_in_avr-gcc&amp;diff=25254"/>
				<updated>2014-09-13T11:09:54Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Fallstricke */&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;In C versteht man unter '''Inline Assembler''' die Möglichkeit, direkt Assembler-Befehle in den Code einzufügen bzw. die eingefügten Assembler-Befehle selbst. &lt;br /&gt;
&lt;br /&gt;
Neben den einzufügenden Befehlen muss beschrieben werden, welche Nebeneffekte die Befehle auf die Maschine haben und wo/wie Parameter übergeben werden, bzw. wie die Zuordnung von Variablen zu den Registern ist. Diese Beschreibung ist notwendig weil der [[Compiler]] keine Vorstellung davon hat, welche Effekte und Nebenwirkungen die Assembler-Kommandos auf Register, Variablen und Speicher haben, denn der Assembler-Schnippsel ist für den Compiler lediglich eine &amp;quot;Black Box&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
Obgleich das dazu verwendete Schlüsselwort &amp;lt;tt&amp;gt;__asm&amp;lt;/tt&amp;gt; zum ANSI-C-Standard gehört, ist dies in jedem C-Compiler anders implementiert. Das gilt insbesondere für die Schnittstellenbeschreibung Variablen/Register. Dieser Artikel bezieht sich auf den Inline Assembler von [[avr-gcc]]. &lt;br /&gt;
Viele Erklärungen aus diesem Artikel sind auch gültig für Inline-Assembler anderer C-Compiler der  [[gcc]]-Familie. Instruktionen und Registerklassen werden sich aber unterscheiden, weil diese natürlich abhängig sind vom verwendeten Controller bzw. der Controller-Familie.&lt;br /&gt;
&lt;br /&gt;
=Assembler oder Inline-Assembler?=&lt;br /&gt;
;Assembler: Längere und komplexere Code-Stücke sind komfortabler direkt in Assembler auszudrücken. Dazu schreibt man Assembler-Funktionen und ruft diese von C aus auf. Natürlich können auch C-Funktionen von Assembler aus aufgerufen werden. Zudem kann man im Assembler den C-Präprozessor nutzen, was bei Inline-Assembler nur auf C-Ebene geht. Der Build-Prozess wird allerdings komplizierter, da extra asm-Dateien übersetzt werden müssen. Ein typischer Fall ist es, eine komplette ISR in Assembler zu schreiben.&lt;br /&gt;
;Inline-Assembler: Mit Inline-Assembler kann man kleine Assembler-Stückchen direkt in den C-Code einbetten. Es muss dann keine Assembler-Funktion aufgerufen werden. Dies kann von der Registerverwendung her deutlich günstiger sein, da [[gcc]] genau weiß, welche Register gebraucht werden und welche nicht. &lt;br /&gt;
:Eine (Assembler-)Funktion ist hingegen eine Black Box, bei der von der Standard-[[avr-gcc/Interna#Registerverwendung|Registerverwendung]] ausgegangen werden muss, auch wenn weniger Register in der Funktion verwendet werden. Ein Funktionsaufruf bedeutet also meistens einen Laufzeit-Overhead im Vergleich zu einem Inline-Code. &lt;br /&gt;
:Bei mehrfacher Verwendung einer längeren Codesequenz ist eine Funktion jedoch sparsamer im [[Flash]]-Verbrauch. Legt man eine Funktion als C-Funktion an und ihren Body als Inline-Assembler (eine s.g. Stub-Funktion, von engl. ''Stub'' = Stumpf), dann übernimmt gcc das Verwalten von Funktions-Argumenten, return-Wert, etc. und man brauch sich nicht selber um die Aufruf-Konvention zu kümmern. Auch innerhalb einer Funktion kann C mit Assembler gemischt werden.&lt;br /&gt;
:Ein Vorteil von Inline-Assembler ist, daß eine C-Funktion, die Inline-Assembler enthält, vom C-Compiler [[C-Tutorial#Inlining|geinlinet]] werden kann. Dies ist mit einer reinen Assembler-Funktion nicht möglich.&lt;br /&gt;
&lt;br /&gt;
=Begriffe=&lt;br /&gt;
;Assembler-Template: Das Template (''Schablone'') ist ein statischer, konstanter String im Sinne von C. Es enthält die Assembler-Befehle sowie Platzhalter, in deren Stelle später die Operanden treten&lt;br /&gt;
;Constraint: Die Constraints (''Nebenbedingungen'') beschreiben Einschränkungen an die zu verwendeten Register. Dies ist notwendig, da nicht alle Maschinenbefehle auf alle Register anwendbar sind&lt;br /&gt;
;Clobber-List: Das ist eine Liste von Registern, deren Inhalt durch den Inline-Assembler zerstört wird&lt;br /&gt;
&lt;br /&gt;
=Syntax und Semantik=&lt;br /&gt;
Das Schlüsselwort, um eine Inline-Assembler Sequenz einzuleiten, ist &amp;lt;tt&amp;gt;__asm&amp;lt;/tt&amp;gt; (ANSI). Oft ist auch &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;__asm__&amp;lt;/tt&amp;gt; verwendbar. Um zu kennzeichnen, daß die Sequenz keinesfalls wegoptimiert werden darf &amp;amp;ndash; etwa dann, wenn der Assembler keine Wirkung auf C-Variablen hat &amp;amp;ndash; wird dem &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; ein &amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;__volatile&amp;lt;/tt&amp;gt; nachgestellt. Danach folgen in runden Klammern die durch &amp;lt;tt&amp;gt;''':'''&amp;lt;/tt&amp;gt; getrennten Abschnitte des Inline-Assemblers:&lt;br /&gt;
 asm volatile ([[#Assembler-Template|asm-template]] : [[#Operanden und Constraints|output-operand-list]] : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]]);&lt;br /&gt;
&lt;br /&gt;
Abschnitte, die leer sind, können auch weggelassen werden, wenn dahinter kein weiterer Abschnitt folgt:&lt;br /&gt;
 asm volatile (asm-template);&lt;br /&gt;
&lt;br /&gt;
Oder, wenn weder Input- noch Output-Operanden gebraucht werden, aber Register oder Speicher verändert werden:&lt;br /&gt;
 asm volatile (asm-template ::: clobber-list);&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen |&lt;br /&gt;
Aus Compiler-Sicht werden die Assembler-Befehle im Template parallel, also ''gleichzeitig'' ausgeführt! Dies ist zu bedenken, wenn Register sowohl als Input als auch als Output verwendet werden.&lt;br /&gt;
}} &lt;br /&gt;
&lt;br /&gt;
Ab Version 4.5 kennt GCC &amp;lt;tt&amp;gt;asm goto&amp;lt;/tt&amp;gt;, mit dem ausgedrückt werden kann, dass der Codefluß des Assembler-Teils u.U. zu einem Stück C-Code springt:&lt;br /&gt;
 asm goto ([[#Assembler-Template|asm-template]] : {{comment|Leer}} : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]] : [[#asm goto mit C-Labels|C-labels]]);&lt;br /&gt;
&lt;br /&gt;
== Assembler-Template ==&lt;br /&gt;
&lt;br /&gt;
Im Template stehen die durch Zeilenumbrüche getrennten Assembler-Befehle. Das Template kann zudem &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;-Ausdrücke als Platzhalter enthalten, welche durch die Operanden ersetzt werden. Dabei bezieht sich &amp;lt;tt&amp;gt;%0&amp;lt;/tt&amp;gt; auf den ersten Operanden, &amp;lt;tt&amp;gt;%1&amp;lt;/tt&amp;gt; auf den zweiten Operanden, etc. &lt;br /&gt;
Die Operanden selbst werden im zweiten und dritten Abschnitt des Templates als Komma-getrennte Liste angegeben.&lt;br /&gt;
Diese Ersetzung findet jedoch nur dann statt, wenn das asm nicht nur aus einem String besteht:&lt;br /&gt;
 asm (&amp;quot;10% mehr&amp;quot;);    {{comment|&amp;quot;10% mehr&amp;quot;}}&lt;br /&gt;
 asm (&amp;quot;10%% mehr&amp;quot; :); {{comment|&amp;quot;10% mehr&amp;quot;}}&lt;br /&gt;
&lt;br /&gt;
Ein Platzhalter kann zusätzlich einen einbuchstabigen Modifier enthalten, um den Operanden in printf-ähnlicher Manier in einem speziellen Format darzustellen. Wird z.B. ein Wert ab Register &amp;lt;tt&amp;gt;r28&amp;lt;/tt&amp;gt; (dem Y-Register) gehalten, dann wären folgende Ersetzungen denkbar (als erstes Argument):&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r28&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%A0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r28&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%B0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r29&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%C0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r30&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
:&amp;lt;tt&amp;gt;%D0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:&amp;lt;tt&amp;gt;%a0&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;nbsp;&amp;amp;rarr;&amp;amp;nbsp;&amp;amp;nbsp;y&amp;amp;nbsp;&amp;amp;nbsp;&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Im einfachsten Falle enthält das Templater nur einen Befehl:&lt;br /&gt;
 &amp;quot;nop&amp;quot;&lt;br /&gt;
oder sogar garkeinen Befehl oder lediglich einen Kommentar:&lt;br /&gt;
 &amp;quot;; ein Kommentar&amp;quot;&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: asm-Platzhalter und ihre Modifier, Sonderzeichen'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Platzhalter || wird ersetzt durch || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%''n''&amp;lt;/tt&amp;gt; || Wird ersezt durch Argument &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; mit &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; = 0...9&lt;br /&gt;
| &lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%A''n''&amp;lt;/tt&amp;gt; || das erste (untere) Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 0...7)&lt;br /&gt;
|align=&amp;quot;center&amp;quot; rowspan=&amp;quot;4&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%B''n''&amp;lt;/tt&amp;gt; || das zweite Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 8...15)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%C''n''&amp;lt;/tt&amp;gt; || das dritte Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 16...23)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%D''n''&amp;lt;/tt&amp;gt; || das vierte Register des Arguments &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt; (Bits 24...31)&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%a''n''&amp;lt;/tt&amp;gt; || Ausgabe des Arguments als Adress-Register,&amp;lt;br/&amp;gt;also als &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;. Erlaubt zusammen mit Constraint &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%i''n''&amp;lt;/tt&amp;gt; || Ab 4.7. Ausgabe einer RAM-Adresse als I/0-Adresse. Beispiel: &amp;lt;tt&amp;gt;0x30&amp;lt;/tt&amp;gt; wird auf Xmega-Controllern als &amp;lt;tt&amp;gt;0x30&amp;lt;/tt&amp;gt; ausgegeben und auf nicht-Xmega als &amp;lt;tt&amp;gt;0x10&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%r''n''&amp;lt;/tt&amp;gt; || Ab 4.8. Ausgabe eines Registers ohne die Register-Präfix &amp;quot;r&amp;quot;.  Damit kann per Inline-Assembler auf 64-Bit Variablen zugegriffen werden, z.B. kann mit &amp;lt;tt&amp;gt;&amp;quot;clr %r0+7&amp;quot;&amp;lt;/tt&amp;gt; das High-Byte gelöscht werden.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%T''n''%T''m''&amp;lt;/tt&amp;gt; || Ab 4.7. Gibt einen Doppel-Operanden aus wie er zum Beispiel in BLD oder BST benötigt wird, d.h. durch ein Komma getrennte Register- und Bitnummer. Das erste &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt; erhält ein Register und speichert es zwischen bis zum nächsten &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt;, das die konstante Bitnummer ''m'' enthält. Die Ausgabe erfolgt erst mit dem zweiten &amp;lt;tt&amp;gt;%T&amp;lt;/tt&amp;gt;: Beispielsweite kann durch folgende Zeile das High-Bit von ''var'' gelöscht werden:&lt;br /&gt;
 asm (&amp;quot;clt $ bld %T[v]%T[b]&amp;quot; : [v] &amp;quot;+r&amp;quot; (var) : [b] &amp;quot;n&amp;quot; (8*(sizeof var)-1));&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%T''n''%t''m''&amp;lt;/tt&amp;gt; || Ab 4.7. Funktioniert wie &amp;lt;tt&amp;gt;%T''n''%T''m''&amp;lt;/tt&amp;gt;, es wird aber nur das zum Bit&amp;amp;nbsp;''m'' gehörende Register ausgegeben, d.h. weder Komma noch Bitnummer.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%x''n''&amp;lt;/tt&amp;gt; || Ab 4.5. Gibt ein Label ohne Operand-Modifier &amp;lt;tt&amp;gt;gs()&amp;lt;/tt&amp;gt; aus.&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%~&amp;lt;/tt&amp;gt; || wird auf AVR mit Flash bis max. 8kiByte durch ein &amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt; ersetzt, ansonsten bleibt es leer.&amp;lt;br/&amp;gt;Zum Aufbau von Sprungbefehlen, etwa &amp;quot;&amp;lt;tt&amp;gt;%~call foo&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%!&amp;lt;/tt&amp;gt; || Ab 4.4. Wird auf AVR mit Flash ab 128kiByte durch ein &amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt; ersetzt, ansonsten bleibt es leer.&amp;lt;br/&amp;gt;Zum Aufbau von indirekten Sprungbefehlen, etwa &amp;quot;&amp;lt;tt&amp;gt;%!icall&amp;lt;/tt&amp;gt;&amp;quot;&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%=&amp;lt;/tt&amp;gt; || eine für dieses asm-Template und die Übersetzungseinheit eindeutige Zahl.&amp;lt;br/&amp;gt;Zum Aufbau  lokaler Sprungmarken.&lt;br /&gt;
| &lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Sequenz || wird ersetzt durch Sonderzeichen || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;%%&amp;lt;/tt&amp;gt; || das &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt;-Zeichen selbst&lt;br /&gt;
|&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\n&amp;lt;/tt&amp;gt; || ein Zeilenumbruch zum Trennen mehrerer asm-Befehle/Zeilen&lt;br /&gt;
| &lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;$&amp;lt;/tt&amp;gt; || trennt mehrere Befehle in der gleichen Zeile&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\t&amp;lt;/tt&amp;gt; || ein TAB, zur Übersichtlichkeit im erzeugten asm ||&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\&amp;quot;&amp;lt;/tt&amp;gt; || ein &amp;lt;tt&amp;gt;&amp;quot;&amp;lt;/tt&amp;gt; wird eingefügt ||&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;\\&amp;lt;/tt&amp;gt; || das &amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;-Zeichen selbst ||&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Kommentar || Beschreibung || AVR-spezifisch&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;; ''Text''&amp;lt;/tt&amp;gt; || einzeiliger Kommentar bis zum Ende des Templates bzw. nächsten Zeilenumbruch&lt;br /&gt;
|align=&amp;quot;center&amp;quot;| '''X'''&lt;br /&gt;
|-  valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;/* ''Text'' */&amp;lt;/tt&amp;gt; || mehrzeiliger Kommentar wie in C ||&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Operanden und Constraints ==&lt;br /&gt;
&lt;br /&gt;
Ein Operand besteht aus der Angabe des Constraint-Strings (also der Registerklasse und Kennzeichnung, ob es sich um einen Output-Operanden handelt) und dahinter in runden Klammern der C-Ausdruck, der in Register der angegebenen Klasse geladen werden soll. Die Operanden werden mit 0 beginnend von links nach rechts durchnumeriert und über diese Nummer angesprochen, um sie ins Assembler-Schnippsel einzufügen.&lt;br /&gt;
&lt;br /&gt;
Mehrere Input- bzw. Output-Operanden werden durch Komma getrennt.&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: Constraints und ihre Bedeutung'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Constraint || Register || Wertebereich&lt;br /&gt;
|rowspan=&amp;quot;14&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
! Constraint || Konstante || Wertebereich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;a&amp;lt;/tt&amp;gt;||einfache obere Register||&amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r23&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;G&amp;lt;/tt&amp;gt;||Floatingpoint-Konstante ||&amp;lt;tt&amp;gt;0.0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt;||Pointer-Register ||&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;i&amp;lt;/tt&amp;gt;||Konstante, entspricht &amp;lt;tt&amp;gt;&amp;quot;sn&amp;quot;&amp;lt;/tt&amp;gt; ||&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;d&amp;lt;/tt&amp;gt;||obere Register ||&amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;s&amp;lt;/tt&amp;gt;||symbolischer Wert || &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;e&amp;lt;/tt&amp;gt;||Pointer-Register ||&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;n&amp;lt;/tt&amp;gt;||Wert bekannt zur Compilezeit ||&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;l&amp;lt;/tt&amp;gt;||untere Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r15&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;||positive 6-Bit-Konstante ||0...63&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;q&amp;lt;/tt&amp;gt;||Stack-Pointer ||&amp;lt;tt&amp;gt;SPH:SPL&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;J&amp;lt;/tt&amp;gt;||negative 6-Bit Konstante ||&amp;lt;tt&amp;gt;-&amp;lt;/tt&amp;gt;63...0&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;||ein Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt;&lt;br /&gt;
|&amp;lt;tt&amp;gt;M&amp;lt;/tt&amp;gt;||8-Bit Konstante ||0...255&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;t&amp;lt;/tt&amp;gt;||Scratch-Register ||&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot; |&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;w&amp;lt;/tt&amp;gt;||obere Register-Paare ||&amp;lt;tt&amp;gt;r24&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r26&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r28&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r30&amp;lt;/tt&amp;gt;&lt;br /&gt;
!{{Hintergrund1}}| Constraint ||{{Hintergrund1}}| Memory ||{{Hintergrund1}}| Wertebereich&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt;||Pointer-Register X ||&amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r27:r26&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|&amp;lt;tt&amp;gt;m&amp;lt;/tt&amp;gt;|| Memory || &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt;||Pointer-Register Y ||&amp;lt;tt&amp;gt;y&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r29:r28&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot; rowspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt;||Pointer-Register Z ||&amp;lt;tt&amp;gt;z&amp;lt;/tt&amp;gt; (&amp;lt;tt&amp;gt;r31:r30&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;9&amp;lt;/tt&amp;gt;||colspan=&amp;quot;2&amp;quot;|Identisch mit dem angegebenen Operanden&amp;lt;br/&amp;gt;Wird verwendet, wenn ein Operand sowohl als Input&amp;lt;br/&amp;gt;als auch als Output dient, um sich auf diesen&amp;lt;br/&amp;gt;Operanden zu beziehen&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+ '''Tabelle: Constraint Modifier'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Modifier || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;=&amp;lt;/tt&amp;gt; || der Operand ist Output-Operand&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; || diesen Operanden ''nicht'' als Input-Operanden verwenden,&amp;lt;br/&amp;gt;sondern nur als Output-Operand&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;+&amp;lt;/tt&amp;gt; || dieser Operanden ist Input- und Output-Operand&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Ein Input-Operand könnte also so aussehen, wobei &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; eine C-Variable ist. Als Register dient ein (je nach Typ von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; auch mehrere) obere Register, irgendwo von &amp;lt;tt&amp;gt;r16&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;r31&amp;lt;/tt&amp;gt; (Constraint &amp;lt;tt&amp;gt;&amp;quot;d&amp;quot;&amp;lt;/tt&amp;gt;):&lt;br /&gt;
 &amp;quot;d&amp;quot; (foo)&lt;br /&gt;
&lt;br /&gt;
In den Klammern kann ein beliebiger, gültiger C-Ausdruck stehen, der beim folgenden Beispiel in irgendeinem Register landet (Constraint &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot;&amp;lt;/tt&amp;gt;), ohne weitere Einschränkung an das Register:&lt;br /&gt;
 &amp;quot;r&amp;quot; ((foo &amp;gt;= 0) ? foo : -foo)&lt;br /&gt;
&lt;br /&gt;
Um einen Operanden als Output-Operanden zu kennzeichnen, wird dem Constraint ein &amp;lt;tt&amp;gt;&amp;quot;=&amp;quot;&amp;lt;/tt&amp;gt; vorangestellt.&lt;br /&gt;
Soll &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; ein Output-Operand sein, der in den Registern &amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;...&amp;lt;tt&amp;gt;r15&amp;lt;/tt&amp;gt; landen soll (Constraint &amp;lt;tt&amp;gt;&amp;quot;l&amp;quot;&amp;lt;/tt&amp;gt;, sieht es so aus. Dabei muss &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; ein sogenannter Lvalue sein, also ein Wert, dem etwas zugewiesen werden kann:&lt;br /&gt;
 &amp;quot;=l&amp;quot; (foo)&lt;br /&gt;
&lt;br /&gt;
Ist &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; sowohl Input als auch Output, schreibt man &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Output- und als Input-Operand hin. In der Input-Constraint bezieht man sich dann auf die Operanden-Nummer von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt;. Hier ein komplettes Beispiel, das die Nibbles von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; tauscht. Weil &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; auf alle Register anwendbar ist, kann als Registerklasse &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot;&amp;lt;/tt&amp;gt; genommen werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char foo;&lt;br /&gt;
...&lt;br /&gt;
asm (&amp;quot;swap %0&amp;quot; : &amp;quot;=r&amp;quot; (foo) : &amp;quot;0&amp;quot; (foo));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Input-Operand soll im gleichen Register liegen wie &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; als Output-Operand. Daher wird als Constraint &amp;lt;tt&amp;gt;&amp;quot;0&amp;quot;&amp;lt;/tt&amp;gt; angegeben, d.h. es wird ins gleiche Register geladen wie der Operand Numero&amp;amp;nbsp;0 &amp;lt;tt&amp;gt;&amp;quot;r&amp;quot; (foo)&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Benannte Constraints ===&lt;br /&gt;
&lt;br /&gt;
Um das Assembler-Schnippsel besser lesbar zu halten, kann man Constraints einen Namen geben:&lt;br /&gt;
 asm (&amp;quot;swap %[bar]&amp;quot; : [bar] &amp;quot;+r&amp;quot; (foo));&lt;br /&gt;
Damit ist der Assembler auch unabhängig von der Reihenfolge der Operanden. Das macht die Anpassung, wenn ein neuer Operand hinzukommt, wesentlich einfacher und den Schnippsel zudem besser lesbar. &lt;br /&gt;
&lt;br /&gt;
Hier wird &amp;lt;tt&amp;gt;bar&amp;lt;/tt&amp;gt; als Alias für die C-Variable &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; benutzt; es könnte aber auch jeder andere gültige C-Bezeichner sein, also insbesondere auch &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=== Instruktionen und Constraints ===&lt;br /&gt;
&lt;br /&gt;
Die folgende Tabelle enhält eine Auflistung von AVR-Instruktionen und dazu passende Argumente bzw. Constraints. Nicht alle Shorthands sind in der Tabelle enthalten, so ist &amp;quot;&amp;lt;tt&amp;gt;clr Rn&amp;lt;/tt&amp;gt;&amp;quot; nur eine Abkürzung für &amp;quot;&amp;lt;tt&amp;gt;eor Rn, Rn&amp;lt;/tt&amp;gt;&amp;quot;, ähnliches gilt für den Zoo von Instruktionen rund um das SREG wie  branch, bit set, bit clear, etc., die im Endeffekt auf nur vier Instruktionen abbilden. Instruktionen wie &amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt;, die keine Argumente brauchen, sind ebenfalls nicht in der Tabelle enthalten. Gleiches gilt für den Krypto-Befehl &amp;lt;tt&amp;gt;des&amp;lt;/tt&amp;gt;, für die keine Constraint verfügbar ist.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;quot;load&amp;quot;&amp;lt;/tt&amp;gt; ist ein &amp;lt;tt&amp;gt;&amp;quot;load from SRAM&amp;quot;&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;quot;store&amp;quot;&amp;lt;/tt&amp;gt; ist &amp;lt;tt&amp;gt;&amp;quot;store to SRAM&amp;quot;&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+'''Tabelle: Übersicht AVR-Instruktionen und passende Constraints'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Mnemonic || Constraint ||Bedeutung ||rowspan=&amp;quot;35&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
!Mnemonic || Constraint ||Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;adc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || add with carry&lt;br /&gt;
| &amp;lt;tt&amp;gt;add&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || add&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;adiw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;w,I&amp;lt;/tt&amp;gt; || add immediate to word&lt;br /&gt;
| &amp;lt;tt&amp;gt;and&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || and&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;andi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || and with immediate &lt;br /&gt;
| &amp;lt;tt&amp;gt;asr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || arithmetic shift right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;bclr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;   || bit clear in SREG&lt;br /&gt;
| &amp;lt;tt&amp;gt;bld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt;  || bit load from T&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;brbc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,label&amp;lt;/tt&amp;gt; || branch if bit in SREG clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;brbs&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,label&amp;lt;/tt&amp;gt; || branch if bit in SREG set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;bset&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I&amp;lt;/tt&amp;gt;  || bit set in SREG&lt;br /&gt;
| &amp;lt;tt&amp;gt;bst&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || bit store from T&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cbi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || clear bit in I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;com&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || complement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cp&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || compare&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || compare with carry&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || compare against immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;cpse&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;|| compare, skip if equal&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;dec&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;[e]lpm&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,z&amp;lt;/tt&amp;gt;|| load from program memory&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;eor&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || exclusive-or&lt;br /&gt;
| &amp;lt;tt&amp;gt;fmul*&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;a,a&amp;lt;/tt&amp;gt; || fractional multiply&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt;  || input from I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;inc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;lac&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;lat&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and toggle&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;las&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || load and set&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,e&amp;lt;/tt&amp;gt;   || load indirect&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,e+&amp;lt;/tt&amp;gt;  || load indirect, post-increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,-e&amp;lt;/tt&amp;gt;  || load indirect, pre-decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;ldd&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,b+I&amp;lt;/tt&amp;gt; || load indirect with displacement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ldi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || load immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;lds&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,label&amp;lt;/tt&amp;gt; || load direct from SRAM&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;t,z&amp;lt;/tt&amp;gt;  || load from program memory&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&lt;br /&gt;
| &amp;lt;tt&amp;gt;lsr&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || logical shift right&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mov&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || move&lt;br /&gt;
| &amp;lt;tt&amp;gt;movw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt; || move word&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mul&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || multiply unsigned&lt;br /&gt;
| &amp;lt;tt&amp;gt;muls&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,d&amp;lt;/tt&amp;gt;  || multiply signed &lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;mulsu&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;a,a&amp;lt;/tt&amp;gt;  || multiply signed/unsigned &lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;neg&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || negate&lt;br /&gt;
| &amp;lt;tt&amp;gt;or&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;   || or&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ori&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt;  || or with immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,r&amp;lt;/tt&amp;gt;  || output to I/O&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;pop&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || pop from Stack&lt;br /&gt;
| &amp;lt;tt&amp;gt;push&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || push to Stack&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;ror&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;    || rotate right&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;| &amp;amp;nbsp;&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || subtract with carry&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbci&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || subtract with carry immediate&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbic&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || skip if bit in I/O clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbis&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt; || skip if bit in I/O set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;I,I&amp;lt;/tt&amp;gt;  || set Bit in I/O&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbiw&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;w,I&amp;lt;/tt&amp;gt; || subtract immediate from word&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbrc&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || skip if bit in register clear&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbrs&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,I&amp;lt;/tt&amp;gt; || skip if bit in register set&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;e,r&amp;lt;/tt&amp;gt;  || store indirect&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;e+,r&amp;lt;/tt&amp;gt;  || store indirect, post-increment&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;-e,r&amp;lt;/tt&amp;gt;  || store indirect, pre-decrement&lt;br /&gt;
| &amp;lt;tt&amp;gt;std&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;b,r&amp;lt;/tt&amp;gt; || store indirect with displacement&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sts&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;label,r&amp;lt;/tt&amp;gt; || store direct&lt;br /&gt;
| &amp;lt;tt&amp;gt;sub&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r,r&amp;lt;/tt&amp;gt;  || subtract&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;subi&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;d,M&amp;lt;/tt&amp;gt; || subtract immediate&lt;br /&gt;
| &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;r&amp;lt;/tt&amp;gt;   || swap nibbles&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;xch&amp;lt;/tt&amp;gt;||&amp;lt;tt&amp;gt;z,r&amp;lt;/tt&amp;gt; || exchange&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
&amp;lt;sup&amp;gt;1&amp;lt;/sup&amp;gt;&amp;amp;nbsp;Je nach Derivat werden die folgenden &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;-Ausprägungen unterstützt oder nicht:&lt;br /&gt;
* &amp;lt;tt&amp;gt;lpm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;lpm r,z&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;lpm r,z+&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;elpm&amp;lt;/tt&amp;gt;&lt;br /&gt;
* &amp;lt;tt&amp;gt;elpm r,z&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;elpm r,z+&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Hier noch ein paar der gebräuchlichsten Shorthands und deren Abbildung auf &amp;quot;Basis&amp;quot;-Instruktionen:&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
|+'''Tabelle: Shorthands'''&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
!Shorthand || gleichbedeutend mit || Bedeutung ||rowspan=&amp;quot;5&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
!Shorthand || gleichbedeutend mit || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;rol r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;adc   r,r&amp;lt;/tt&amp;gt;   || rotate left&lt;br /&gt;
| &amp;lt;tt&amp;gt;cbr r,M&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;andi  r, ~M&amp;lt;/tt&amp;gt; || clear bits in reg&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;clr r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;eor  r,r&amp;lt;/tt&amp;gt;   || clear reg to zero &lt;br /&gt;
| &amp;lt;tt&amp;gt;lsl r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;add  r,r&amp;lt;/tt&amp;gt;   || logical shift left&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;sbr d,M&amp;lt;/tt&amp;gt; || &amp;lt;tt&amp;gt;ori  d, M&amp;lt;/tt&amp;gt; || set bits in reg&lt;br /&gt;
| &amp;lt;tt&amp;gt;ser d&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;ldi  d, 0xff&amp;lt;/tt&amp;gt; || set all bits in reg&lt;br /&gt;
|-&lt;br /&gt;
| &amp;lt;tt&amp;gt;tst r&amp;lt;/tt&amp;gt;   || &amp;lt;tt&amp;gt;and  r,r&amp;lt;/tt&amp;gt;   || test against zero&lt;br /&gt;
|colspan=&amp;quot;3&amp;quot;|&amp;amp;nbsp;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
==Clobbers==&lt;br /&gt;
&lt;br /&gt;
In der Komma-getrennten Clobber-Liste kann man angeben, welche Register durch den Inline-Assembler ihren Wert ändern. Ändern z.B. &amp;lt;tt&amp;gt;r2&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;r3&amp;lt;/tt&amp;gt; ihre Werte, dann ist die Clobber-Liste&lt;br /&gt;
 &amp;quot;r2&amp;quot;, &amp;quot;r3&amp;quot;&lt;br /&gt;
&lt;br /&gt;
Wird schreibend auf das RAM zugegriffen, dann muss man das auch mitteilen, damit RAM-Inhalte, die sich evtl. in Registern befinden, nach dem Inline-Assembler neu gelesen werden. Der Clobber dafür ist:&lt;br /&gt;
 &amp;quot;memory&amp;quot;&lt;br /&gt;
&lt;br /&gt;
'''Beispiel:'''&lt;br /&gt;
&lt;br /&gt;
Es soll ein Inline-Assembler geschrieben werden, das den Inhalt zweier aufeinanderfolgender Speicherstellen austauscht. Die Adresse soll in &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; stehen. Sie ist Input-Operand und muss in Register X, Y oder Z stehen, um den &amp;lt;tt&amp;gt;ld&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;st&amp;lt;/tt&amp;gt;-Befehl anwenden zu können. Die passende Constraint ist also &amp;lt;tt&amp;gt;&amp;quot;e&amp;quot;&amp;lt;/tt&amp;gt;. Nach der Sequenz liegt &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; unverändert vor.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;ld r2,  %a0+&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;ld r3,  %a0&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;st %a0,  r2&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;st -%a0, r3&amp;quot;&lt;br /&gt;
         : /* keine Output-Operanden */&lt;br /&gt;
         : &amp;quot;e&amp;quot; (addr)&lt;br /&gt;
         : &amp;quot;r2&amp;quot;, &amp;quot;r3&amp;quot;, &amp;quot;memory&amp;quot;&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt; &lt;br /&gt;
avr-gcc entscheidet sich dazu, das Z-Register für &amp;lt;tt&amp;gt;addr&amp;lt;/tt&amp;gt; zu verwenden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ld r2,  Z+&lt;br /&gt;
	ld r3,  Z&lt;br /&gt;
	st Z,  r2&lt;br /&gt;
	st -Z, r3&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Günstiger ist es jedoch, dem Compiler auch die Entscheidung zu überlassen, welche(s) Register als Hilfsregister verwendet werden sollen. Ein Register kann &amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; sein, für das zweite  legen wir eine lokale 8-Bit-Variable &amp;lt;tt&amp;gt;hilf&amp;lt;/tt&amp;gt; an:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   {&lt;br /&gt;
      char hilf;&lt;br /&gt;
	&lt;br /&gt;
      asm volatile (&lt;br /&gt;
         &amp;quot;ld __tmp_reg__,  %a1+&amp;quot;           &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;ld %0,           %a1&amp;quot;            &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;st %a1,          __tmp_reg__&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
         &amp;quot;st -%a1,         %0&amp;quot;&lt;br /&gt;
            : &amp;quot;=&amp;amp;r&amp;quot; (hilf)&lt;br /&gt;
            : &amp;quot;e&amp;quot;   (addr)&lt;br /&gt;
            : &amp;quot;memory&amp;quot;&lt;br /&gt;
      );&lt;br /&gt;
   }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; (also &amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;) brauch nicht in die Clobber-Liste aufgenommen zu werden. Um das zweite benötigte Register (hier &amp;lt;tt&amp;gt;r24&amp;lt;/tt&amp;gt;, in dem &amp;lt;tt&amp;gt;hilf&amp;lt;/tt&amp;gt; lebt) kümmert sich avr-gcc und sichert es, falls nötig&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       	ld	r0, Z+&lt;br /&gt;
       	ld	r24, Z&lt;br /&gt;
       	st	Z, r0&lt;br /&gt;
       	st	-Z, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen |&lt;br /&gt;
Falls das Register &amp;lt;tt&amp;gt;r1&amp;lt;/tt&amp;gt; verändert wird &amp;amp;ndash; was z.B. geschieht, wenn man Multiplikationsbefehle verwendet &amp;amp;ndash; dann muss am Ende des Templates das Register wieder auf&amp;amp;nbsp;0 gesetzt werden, denn bei avr-gcc enthält dieses Register immer den Wert&amp;amp;nbsp;0.&lt;br /&gt;
Das Register in die Clobber-Liste aufzunehen bleibt wirkungslos. Hat man es zerstört,&lt;br /&gt;
dann schreibt man ans Ende des Templates ein&lt;br /&gt;
 clr __zero_reg__&lt;br /&gt;
und stellt es dadurch wieder her.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
== asm goto mit C-Labels == &lt;br /&gt;
&lt;br /&gt;
Ab Version 4.5 kennt GCC &amp;lt;tt&amp;gt;asm goto&amp;lt;/tt&amp;gt;, mit dem ausgedrückt werden kann, dass der Codefluß des Assembler-Teils u.U. zu einem Stück C-Code springt:&lt;br /&gt;
&lt;br /&gt;
 asm goto ([[#Assembler-Template|asm-template]] : {{comment|Leer}} : [[#Operanden und Constraints|input-operand-list]] : [[#Clobbers|clobber-list]] : [[#asm goto mit C-Labels|C-labels]]);&lt;br /&gt;
&lt;br /&gt;
Die Codefluß-Analyse des Compilers muss wissen, daß die angegebenen C-Code Sequenzen verwendet werden, damit sie  nicht wegoptimiert werden.  Solch ein Inline-Assembler mit &amp;lt;tt&amp;gt;goto&amp;lt;/tt&amp;gt; darf keine Output-Operanden haben, denn der Compiler hat keine Möglichkeit, Code für die entsprechenden Output-Reloads zu erzeugen.&lt;br /&gt;
&lt;br /&gt;
;Beispiel:&lt;br /&gt;
&lt;br /&gt;
 extern void __attribute__((noreturn))&lt;br /&gt;
 panic (void);&lt;br /&gt;
 &lt;br /&gt;
 char panic_if_x (char x)&lt;br /&gt;
 {&lt;br /&gt;
     asm goto (&amp;quot;cpse %0, __zero_reg__&amp;quot; &amp;quot;\n\t&amp;quot;&lt;br /&gt;
               &amp;quot;%~jmp %x1&amp;quot;             &amp;quot;\n\t&amp;quot;&lt;br /&gt;
               &amp;quot;%~jmp %x2&amp;quot;&lt;br /&gt;
               :: &amp;quot;r&amp;quot; (x) :: proceed, do_panic);&lt;br /&gt;
     __builtin_unreachable();&lt;br /&gt;
     &lt;br /&gt;
     if (0)&lt;br /&gt;
     {&lt;br /&gt;
     do_panic:&lt;br /&gt;
         panic();&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     if (0)&lt;br /&gt;
     {&lt;br /&gt;
     proceed:&lt;br /&gt;
         x++;&lt;br /&gt;
     }&lt;br /&gt;
     &lt;br /&gt;
     return x;&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Im Beispiel wird der Inline-Assembler nur über die Marken &amp;lt;tt&amp;gt;do_panic&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;proceed&amp;lt;/tt&amp;gt; verlassen, weshalb der Code direkt danach unerreichbar ist.  Dies wird der Codefluß-Analyse per &amp;lt;tt&amp;gt;__builtin_unreachable()&amp;lt;/tt&amp;gt; mitgeteilt.  Es wird folgender Code erzeugt:&lt;br /&gt;
&lt;br /&gt;
 panic_if_x:&lt;br /&gt;
 {{comment|#APP}}&lt;br /&gt;
 	cpse r24,__zero_reg__&lt;br /&gt;
 	rjmp .L2&lt;br /&gt;
 	rjmp .L3&lt;br /&gt;
 {{comment|#NOAPP}}&lt;br /&gt;
 .L3:&lt;br /&gt;
 	rcall panic&lt;br /&gt;
 .L2:&lt;br /&gt;
 	subi r24,lo8(-(1))&lt;br /&gt;
 	ret&lt;br /&gt;
&lt;br /&gt;
=Vordefinierte Bezeichner und Makros=&lt;br /&gt;
Je nach Assembler, für den avr-gcc Code erzeugt, gibt es unterschiedliche vordefinierte Funktionen/Makros, die von Inline-Assembler aus verwendbar sind.&lt;br /&gt;
&lt;br /&gt;
== GNU-Assembler ==&lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}} &lt;br /&gt;
|+ '''Vordefinierte Makros und&amp;lt;br/&amp;gt;Relocatable Expression Modifiers'''&amp;lt;br/&amp;gt;&amp;amp;nbsp;&lt;br /&gt;
|- {{Hintergrund1}}&lt;br /&gt;
! Bezeichner || Bedeutung&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SP_L__&amp;lt;/tt&amp;gt; || unteres Byte des Stack-Pointers, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SP_H__&amp;lt;/tt&amp;gt; || oberes Byte des Stack-Pointers, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__SREG__&amp;lt;/tt&amp;gt; || Status-Register, für &amp;lt;tt&amp;gt;in&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;out&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__tmp_reg__&amp;lt;/tt&amp;gt; || ein Register zur temporären Verwendung (&amp;lt;tt&amp;gt;r0&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;__zero_reg__&amp;lt;/tt&amp;gt; || ein Register, das 0 enthält (&amp;lt;tt&amp;gt;r1&amp;lt;/tt&amp;gt;)&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;lo8(''const'')&amp;lt;/tt&amp;gt; || Bits 0...7 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;hi8(''const'')&amp;lt;/tt&amp;gt; || Bits 8...15 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;hlo8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;hh8(''const'')&amp;lt;/tt&amp;gt; || Bits 16...23 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|-&lt;br /&gt;
|&amp;lt;tt&amp;gt;hhi8(''const'')&amp;lt;/tt&amp;gt; || Bits 24...31 der Konstanten &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;pm(''const'')&amp;lt;/tt&amp;gt; || Konstante &amp;lt;tt&amp;gt;''const''&amp;lt;/tt&amp;gt; durch 2 geteilt,&amp;lt;br/&amp;gt;zur Berechnung von Word-Adressen für &amp;lt;tt&amp;gt;icall&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;ijmp&amp;lt;/tt&amp;gt;.&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;pm_lo8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;pm_hi8(''const'')&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;&amp;lt;tt&amp;gt;pm_hh8(''const'')&amp;lt;/tt&amp;gt;&lt;br /&gt;
| Abkürzung für &amp;lt;tt&amp;gt;lo8(pm(''const''))&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;Abkürzung für &amp;lt;tt&amp;gt;hi8(pm(''const''))&amp;lt;/tt&amp;gt;&amp;lt;br/&amp;gt;Abkürzung für &amp;lt;tt&amp;gt;hh8(pm(''const''))&amp;lt;/tt&amp;gt;&lt;br /&gt;
|- valign=&amp;quot;top&amp;quot;&lt;br /&gt;
|&amp;lt;tt&amp;gt;gs(''label'')&amp;lt;/tt&amp;gt; || Word-Adresse von &amp;lt;tt&amp;gt;''label''&amp;lt;/tt&amp;gt;. Für Devices mit mehr als 128k Flash wird die Adresse eines Jump-Pads eingetragen. Der Linker erzeugt ein Jump-Pad, das einen direkten Sprung zu &amp;lt;tt&amp;gt;label&amp;lt;/tt&amp;gt; erhält. &amp;lt;tt&amp;gt;gs(label)&amp;lt;/tt&amp;gt; wird durch diese Adresse ersetzt.&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
=Beispiele=&lt;br /&gt;
&lt;br /&gt;
==nop==&lt;br /&gt;
Mit den bisherigen Vorkenntnissen ist zu &amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt; nicht viel zu sagen:&lt;br /&gt;
 asm volatile (&amp;quot;nop&amp;quot;);&lt;br /&gt;
Oder als C-Makro:&lt;br /&gt;
 #define nop() \&lt;br /&gt;
    asm volatile (&amp;quot;nop&amp;quot;)&lt;br /&gt;
&lt;br /&gt;
&amp;lt;tt&amp;gt;nop&amp;lt;/tt&amp;gt; hat weder Input- noch Output-Operanden, und Register/RAM ändern sich natürlich nicht. Bei der Makro-Definition ist lediglich darauf zu achten, daß das Makro nicht mit einem&amp;amp;nbsp;&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; endet, damit man den C-Code wie gewohnt mit&amp;amp;nbsp;&amp;lt;tt&amp;gt;;&amp;lt;/tt&amp;gt; schreiben kann:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
if (x)&lt;br /&gt;
   nop();&lt;br /&gt;
else&lt;br /&gt;
   ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==swap Nibbles==&lt;br /&gt;
Ein einfaches Beispiel für &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; haben wir bereits oben kennen gelernt. Der Inline-Assembler dreht die Nibbles von &amp;lt;tt&amp;gt;foo&amp;lt;/tt&amp;gt; um:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
unsigned char foo;&lt;br /&gt;
...&lt;br /&gt;
asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (foo));&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wünschenswert wäre eher, &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt; wie eine normale C-Funktion verwenden zu können und hinzuschreiben:&lt;br /&gt;
 a = swap(b);&lt;br /&gt;
ohne daß &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; seinen Wert ändert. Soll &amp;lt;tt&amp;gt;b&amp;lt;/tt&amp;gt; geswappt werden, dann via&lt;br /&gt;
 b = swap(b);&lt;br /&gt;
zudem soll das Argument ein Ausdruck sein können:&lt;br /&gt;
 if (b == swap (b+1))&lt;br /&gt;
    ...&lt;br /&gt;
&lt;br /&gt;
Dazu verwenden wir eine lokale Variable &amp;lt;tt&amp;gt;_x_&amp;lt;/tt&amp;gt;, in die der ursprüngliche Wert &amp;lt;tt&amp;gt;x&amp;lt;/tt&amp;gt; gesichert wird:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#define swap(x)                                            \&lt;br /&gt;
 ({                                                        \&lt;br /&gt;
    unsigned char _x_ = (unsigned char) x;                 \&lt;br /&gt;
    asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (_x_));                          \&lt;br /&gt;
    _x_;                                                   \&lt;br /&gt;
  })&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
alternativ könnten wir eine inline-Funktion definieren:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static inline unsigned char swap (unsigned char x)&lt;br /&gt;
{&lt;br /&gt;
    asm (&amp;quot;swap %0&amp;quot; : &amp;quot;+r&amp;quot; (x));&lt;br /&gt;
    return x;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==swap Bytes==&lt;br /&gt;
Werden Zahlen zwischen verschiedenen Plattformen übertragen, kann es sein, daß diese unterschiedlich dargestellt werden: Das low-Byte kann in sich im unteren Byte befinden (AVR), es kann aber auch im oberen Byte sein. Ist das so, dann müssen die Werte beim Senden/Empfang umgewandelt werden, indem die Bytes getauscht werden. Liegt der 16-Bit-Wert in &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; und soll der konvertierte Wert nach &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; gespeichert werden, dann könnte man auf die Idee kommen, so etwas zu schreiben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm (&lt;br /&gt;
      &amp;quot;mov %A0, %B1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;mov %B0, %A1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (x_out)&lt;br /&gt;
         : &amp;quot;r&amp;quot;  (x_in)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Daraus könnte folgender Code entstehen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
     mov    r24, r25&lt;br /&gt;
     mov    r25, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Das ist offenbar Käse! Was ist passiert? &lt;br /&gt;
&lt;br /&gt;
avr-gcc hat sich dazu entschieden, &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; in &amp;lt;tt&amp;gt;r25:r24&amp;lt;/tt&amp;gt; anzulegen. Auch &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; wird in diesen Registern angelegt. Das ist erst mal in Ordnung, wenn &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt; nach dem Inline nicht mehr gebraucht wird. &lt;br /&gt;
&lt;br /&gt;
Allerdings wird das Inline nicht en bloc &amp;amp;mdash; also nicht zeitparallel &amp;amp;mdash; ausgeführt, sondern sequenziell. Bei ''gleichzeitiger'' Ausführung der beiden &amp;lt;tt&amp;gt;mov&amp;lt;/tt&amp;gt;-Instruktionen wäre auch nichts dagegen zu sagen! Ein &amp;lt;tt&amp;gt;swap&amp;lt;/tt&amp;gt;-Kommando z.B. tauscht die Nibbles ''gleichzeitig'', und der Input-Operand kann im gleichen Register leben wie der Output-Operand, wenn der Input nicht weiter verwendet wird. &lt;br /&gt;
&lt;br /&gt;
Mit den beiden Bytes geht es aber nicht. Wir müssen daher kennzeichnen, daß sich &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; in einem Register befindet, das ''nur'' als Output dient, was durch das &amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; in der Output-Constraint erreicht wird:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm (&lt;br /&gt;
      &amp;quot;mov %A0, %B1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;mov %B0, %A1&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (x_out)&lt;br /&gt;
         : &amp;quot;r&amp;quot;   (x_in)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit erfolgt eine korrekte Registerzuordnung. &amp;lt;tt&amp;gt;x_out&amp;lt;/tt&amp;gt; steht jetzt in &amp;lt;tt&amp;gt;r19:r18&amp;lt;/tt&amp;gt; und überschneidet nich nicht mehr mit &amp;lt;tt&amp;gt;x_in&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
       	mov	r18, r25&lt;br /&gt;
       	mov	r19, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Alternativ können wir wie bei [[#swap Nibbles|swap Nibbles]] eine lokale Variable verwenden, und alles als (inline-)Funktion machen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== Zugriff auf SFRs ==&lt;br /&gt;
Um auf SFRs zuzugreifen, können im asm-Template keine Defines aus &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; verwendet werden, weil der Präprozessor nicht mehr über den erzeugten Assembler-Code läuft (er läuft vor dem Compilieren). Um nicht die hex-Codes des SFRs angeben zu müssen, kann man dem Inline die Adressen als Konstanten übergeben. Weil die Adressen RAM-Adressen sind, müssen sie in das &amp;lt;tt&amp;gt;_SFR_IO_ADDR&amp;lt;/tt&amp;gt; Makro verpackt werden, um den Offset für den I/O-Bereich abzuziehen. &amp;lt;tt&amp;gt;tcnt1&amp;lt;/tt&amp;gt; wird auf den Inhalt von &amp;lt;tt&amp;gt;TCNT1&amp;lt;/tt&amp;gt; gesetzt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
   ... &lt;br /&gt;
   uint16_t tcnt1;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;in %A0, %1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;in %B0, %1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (tcnt1)&lt;br /&gt;
         : &amp;quot;M&amp;quot; (_SFR_IO_ADDR (TCNT1))&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
wird umgesetzt zu&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	in r24, 44&lt;br /&gt;
	in r25, 44+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Ab avr-gcc 4.7 kann auch der Operand-Modofier &amp;lt;tt&amp;gt;%i&amp;lt;/tt&amp;gt; verwendet werden, um eine RAM-Adresse, wie sie von &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; definiert werden, als I/O-Adresse auszugeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   uint16_t tcnt1;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;in %A0, %i1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;in %B0, %i1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (tcnt1)&lt;br /&gt;
         : &amp;quot;n&amp;quot; (&amp;amp; TCNT1)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Das nur als Beispiel. Von C aus geht das natürlich auch mit&lt;br /&gt;
 uint16_t tcnt1 = TCNT1;&lt;br /&gt;
&lt;br /&gt;
== Zugriff aufs SRAM ==&lt;br /&gt;
Auf bekannte globale Symbole kann man direkt von Assembler aus zugreifen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   extern int einInt;&lt;br /&gt;
&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, einInt&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, einInt+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24, einInt&lt;br /&gt;
	lds r25, einInt+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
alternativ ginge&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, %A1&amp;quot;   &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, %B1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;m&amp;quot; (einInt)&lt;br /&gt;
   );&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls die Adresse eines Objekts zur Compilezeit bekannt ist, kann man auch die Adresse von C aus übergeben:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
struct foo_t {&lt;br /&gt;
   int a[2], b[2];&lt;br /&gt;
} foo;&lt;br /&gt;
&lt;br /&gt;
...&lt;br /&gt;
{&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;lds %A0, %1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lds %B0, %1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;i&amp;quot; (&amp;amp; foo.b[1])&lt;br /&gt;
   );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24, einStruct+6&lt;br /&gt;
	lds r25, einStruct+6+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Falls die Adresse zur Compilezeit nicht bekannt ist, muss sie natürlich in einem Adress- oder Basisregister übergeben werden:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void blah (struct foo_t * pfoo)&lt;br /&gt;
{&lt;br /&gt;
   asm volatile (&lt;br /&gt;
      &amp;quot;ld  %A0, %a1&amp;quot;    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;ldd %B0, %a1+1&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (...)&lt;br /&gt;
         : &amp;quot;b&amp;quot; (&amp;amp; pfoo-&amp;gt;b[1])&lt;br /&gt;
   );&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	ld  r24, Z&lt;br /&gt;
	ldd r25, Z+1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Auch hier muss der Output-Operand mit einem&amp;amp;nbsp;&amp;lt;tt&amp;gt;&amp;amp;&amp;lt;/tt&amp;gt; gekennzeichnet werden, damit er nicht ins gleiche Register geladen wird wie die Adresse.&lt;br /&gt;
&lt;br /&gt;
= Labels und Schleifen =&lt;br /&gt;
Für Labels in Sprüngen und Schleifen können keine festen Bezeichner verwendet werden, weil ein Label, der via Makro oder inline-Funktion in den Code eingefügt wird, nicht mehrfach vorkommen darf. Dazu kann man sich durch Einfügen von &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; Labels zusammenbauen, etwa &amp;lt;tt&amp;gt;L_a%=&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;L_b%=&amp;lt;/tt&amp;gt;, etc. Das &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; wird durch eine für die Übersetzungseinheit und den Code-Schnippsel eindeutige Zahl ersetzt. Die obigen Sequenzen könnten also z.B. umgesetzt werden als &amp;lt;tt&amp;gt;L_a14&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;L_b14&amp;lt;/tt&amp;gt;, wenn sie im gleichen Schnippsel stehen.&lt;br /&gt;
&lt;br /&gt;
Etwas bequemer ist die Verwendung einer Ziffer als Label. Beim Sprung gibt man direkt hinter der Ziffer an, in welche Richtung das Label gesucht wird. Ist das Label &amp;lt;tt&amp;gt;''n''&amp;lt;/tt&amp;gt;, dann sucht und springt&lt;br /&gt;
*&amp;lt;tt&amp;gt;''n''b&amp;lt;/tt&amp;gt; zurück (backward)&lt;br /&gt;
*&amp;lt;tt&amp;gt;''n''f&amp;lt;/tt&amp;gt; nach vorne (forward)&lt;br /&gt;
&lt;br /&gt;
Es wird zum nächsten auffindbaren Label in der angegebenen Richtung gesprungen.&lt;br /&gt;
&lt;br /&gt;
==Bits zählen==&lt;br /&gt;
&lt;br /&gt;
Dieses Assembler-Schnippsel zählt die Anzahl der gesetzten Bits in einem Byte &amp;lt;tt&amp;gt;eingabe&amp;lt;/tt&amp;gt;. Die Eingabe wird nach rechts ins Carry geschoben, und das Carry zum Ergebnis dazu addiert.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
static inline unsigned char count_bits (unsigned char eingabe)&lt;br /&gt;
{                                              &lt;br /&gt;
   unsigned char count;&lt;br /&gt;
&lt;br /&gt;
   asm ( &lt;br /&gt;
      &amp;quot;clr %0&amp;quot;                &amp;quot;\n&amp;quot;&lt;br /&gt;
      &amp;quot;0:&amp;quot;                    &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;lsr %1&amp;quot;                &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;adc %0, __zero_reg__&amp;quot;  &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;tst %1&amp;quot;                &amp;quot;\n\t&amp;quot;&lt;br /&gt;
      &amp;quot;brne 0b&amp;quot;&lt;br /&gt;
         : &amp;quot;=&amp;amp;r&amp;quot; (count), &amp;quot;+r&amp;quot; (eingabe)&lt;br /&gt;
   );&lt;br /&gt;
&lt;br /&gt;
   return count;&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit kann man sich ein Parity bauen:&lt;br /&gt;
 #define parity(x) (count_bits(x) &amp;amp; 1)&lt;br /&gt;
und hätte eine schlankere (aber etwas langsamere) Parity-Implementierung als in &amp;lt;tt&amp;gt;avr/parity.h&amp;lt;/tt&amp;gt;. Ein &lt;br /&gt;
 if (parity(foo))&lt;br /&gt;
    ...&lt;br /&gt;
wird in Assembler dann zu (&amp;lt;tt&amp;gt;r24 = eingabe&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;r25 = count&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	lds r24,foo&lt;br /&gt;
/* #APP */&lt;br /&gt;
	clr r25&lt;br /&gt;
0:&lt;br /&gt;
	lsr r24&lt;br /&gt;
	adc r25, __zero_reg__&lt;br /&gt;
	tst r24&lt;br /&gt;
	brne 0b&lt;br /&gt;
/* #NOAPP */&lt;br /&gt;
	sbrs r25,0&lt;br /&gt;
	rjmp .L1&lt;br /&gt;
        ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=Fallstricke=&lt;br /&gt;
* Um die Sonderzeichen &amp;lt;tt&amp;gt;&amp;quot;%~&amp;quot;&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;&amp;quot;%=&amp;quot;&amp;lt;/tt&amp;gt; benutzen zu können, muss bei parameterlosen Inline Assembler dem Template ein Doppelpunkt folgen:&lt;br /&gt;
:&amp;lt;pre&amp;gt;asm volatile (&amp;quot;%~call some_function&amp;quot; :);&amp;lt;/pre&amp;gt;&lt;br /&gt;
* Steht das &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; an oberster Ebene — also außerhalb einer Funktion — ist weiter zu beachten:&lt;br /&gt;
** Jedes &amp;lt;tt&amp;gt;%&amp;lt;/tt&amp;gt; wird als solches ausgegeben, und es sind keine Operanden erlaubt.&lt;br /&gt;
** Falls die Reihenfolge von &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; und Funktionen beibehalten werden soll, muß mit &amp;lt;tt&amp;gt;-fno-toplevel-reorder&amp;lt;/tt&amp;gt; compiliert werden.&lt;br /&gt;
&lt;br /&gt;
=Quellen=&lt;br /&gt;
&lt;br /&gt;
; Dokumentation&lt;br /&gt;
&lt;br /&gt;
* AVR-LibC: [http://nongnu.org/avr-libc/user-manual/inline_asm.html ''Inline Assembler Cookbook'']&lt;br /&gt;
* GCC Wiki: [http://gcc.gnu.org/wiki/avr-gcc ''avr-gcc'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Extended-Asm.html ''Assembler Instructions with C Expression Operands'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Constraints.html ''Constraints for &amp;lt;tt&amp;gt;asm&amp;lt;/tt&amp;gt; Operands'']&lt;br /&gt;
* GCC: [http://gcc.gnu.org/onlinedocs/gcc/Explicit-Reg-Vars.html ''Variables in Specified Registers'']&lt;br /&gt;
* GCC Internals: [http://gcc.gnu.org/onlinedocs/gccint/Constraints.html ''Operand Constraints'']&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
;GCC-Quellen:&lt;br /&gt;
&lt;br /&gt;
* [http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/avr.md?content-type=text%2Fplain&amp;amp;view=co ./gcc/config/avr/avr.md]&lt;br /&gt;
* [http://gcc.gnu.org/viewcvs/trunk/gcc/config/avr/constraints.md?content-type=text%2Fplain&amp;amp;view=co ./gcc/config/avr/constraints.md]&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[AVR Assembler Einführung]]&lt;br /&gt;
* [[:Kategorie:Quellcode Assembler_AVR|Quellcode Assembler]]&lt;br /&gt;
* [[Sourcevergleich#GCC (Assembler einfügen)]]&lt;br /&gt;
* [[avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Software]]&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Quellcode_Assembler_AVR]]&lt;br /&gt;
[[Kategorie:Quellcode C]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Avr-gcc&amp;diff=25253</id>
		<title>Avr-gcc</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Avr-gcc&amp;diff=25253"/>
				<updated>2014-09-13T08:58:07Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Dokumentation */ typo&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''avr-gcc''' ist ein freier C-[[Compiler]], mit dem C-Programme zu ausführbaren Programmen übersetzen werden können, die auf [[Microcontroller]]n der [[AVR]]-Familie lauffähig sind. &lt;br /&gt;
An Sprachen versteht avr-gcc sowohl C als auch [[#C%2b%2b|C++]]. &lt;br /&gt;
Neben Standard-C bzw. ANSI-C versteht avr-gcc auch GNU-C, das etwas mehr Möglichkeiten und kleinere Spracherweiterungen bietet.&lt;br /&gt;
&lt;br /&gt;
avr-gcc kann auch dazu verwendet werden, um C/C++ Programme nach Assembler zu übersetzen oder um Bibliotheken zu erstellen, die später in unterschiedlichen Projekten verwendet werden können.&lt;br /&gt;
&lt;br /&gt;
Wie bei allen aus der UNIX-Welt kommenden Programmen ist das Kommando-Interface von avr-gcc die Shell bzw. die Kommandozeile, über die Optionen, Parameter, Einstellungen und die Namen der zu übersetzenden Dateien angegeben werden. &lt;br /&gt;
&lt;br /&gt;
=How to Read=&lt;br /&gt;
&lt;br /&gt;
Dieser Artikel bespricht avr-gcc Version 3.x. Er ist kein C-Tutorial und kein AVR-Handbuch &amp;amp;ndash; das würde den Umfang des Artikels bei weitem sprengen. &lt;br /&gt;
&lt;br /&gt;
Der Artikel ist ein Handbuch zu avr-gcc. Er bespricht zum Beispiel, wie avr-gcc angenwendet wird und Besonderheiten von avr-gcc-C, die nicht zum Sprachumfang von C gehören.&lt;br /&gt;
Dazu zählen die Definition von [[#Interrupts|Interrupt]] Service Routinen ([[ISR|ISRs]]) &lt;br /&gt;
oder wie man Daten ins [[EEPROM]] legt.&lt;br /&gt;
&lt;br /&gt;
Es wird also besprochen, ''wie'' eine ISR zu definieren ist, aber nicht,&lt;br /&gt;
''warum'' das  gegebenenfalls notwendig oder nicht notwendig ist. &lt;br /&gt;
''Warum'' etwas gemacht wird, ist abhängig von der gestellten Aufgabe,&lt;br /&gt;
etwa ''&amp;quot;Initialisiere den [[UART]] zur Benutzung mit 9600 Baud&amp;quot;''.&lt;br /&gt;
Dafür enthält dieser Artikel zusammen mit dem AVR-Handbuch das Rüstzeug, &lt;br /&gt;
bietet aber keine Lösungen für konkrete Aufgaben.&lt;br /&gt;
&lt;br /&gt;
Neben diesem Artikel gibt es den Unterartikel [[avr-gcc/Interna|Interna von avr-gcc]] wo Dinge wie die Registerverwendung, Attribute, Builtins und Sections von avr-gcc dargestellt werden. Zudem findet sich dort ein Überblick über die Arbeitsweise von gcc mit den Schritten&lt;br /&gt;
* Precompilieren&lt;br /&gt;
* Compilieren&lt;br /&gt;
* Assemblieren&lt;br /&gt;
* Linken&lt;br /&gt;
Ein weiterer Unterartikel widmet sich dem Thema [[Inline-Assembler in avr-gcc]].&lt;br /&gt;
&lt;br /&gt;
In den [[:Kategorie:Quellcode C|C-Codebeispielen]]&lt;br /&gt;
befindet sich das ausführlichere Beispiel &amp;quot;[[Hallo Welt für AVR (LED blinken)]]&amp;quot;,&lt;br /&gt;
das nur eine [[Diode#Lumineszenzdiode|LED]] blinkt und zeigt, &lt;br /&gt;
wie ein kleines Projekt mit avr-gcc compiliert werden kann.&lt;br /&gt;
&lt;br /&gt;
Es gibt ein [[C-Tutorial]], das jedoch noch unvollständig und teilweise feherhaft ist (Stand 02/2006). Darüber hinaus gibt es ein [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial C-Tutorial bei www.mikrocontroller.net].&lt;br /&gt;
&lt;br /&gt;
=Benutzer-Schnittstelle=&lt;br /&gt;
&lt;br /&gt;
Die Benutzer-Schnittstelle von avr-gcc ist &amp;amp;ndash; wie für alle Programme, die aus der UNIX-Welt kommen &amp;amp;ndash; die Kommandozeile einer Shell, Console bzw. Eingabeaufforderung. &lt;br /&gt;
&lt;br /&gt;
Im einfachsten Fall sieht ein Aufruf von avr-gcc also so aus:&lt;br /&gt;
 &amp;gt; avr-gcc&lt;br /&gt;
Dabei das '&amp;lt;tt&amp;gt;&amp;gt;&amp;lt;/tt&amp;gt;' nicht mittippen, und ein ENTER am Ende der Zeile drücken.&lt;br /&gt;
Die Antwort bei korrekter Installation ist dann&lt;br /&gt;
 avr-gcc: no input files&lt;br /&gt;
Was bedeutet: das Programm avr-gcc wurde vom Betriebssystem gefunden und konnte/durfte gestartet werden. Dann gibt avr-gcc eine Fehlermeldung aus und beendet die Ausführung, weil er keine Eingabedatei(en) bekommen hat &amp;amp;#150; was ja auch stimmt. Soweit ist also alles in Butter.&lt;br /&gt;
&lt;br /&gt;
Um eine C-Datei &amp;lt;tt&amp;gt;foo.c&amp;lt;/tt&amp;gt; mir avr-gcc optimiert zu einem lauffähigen elf-Programm &amp;lt;tt&amp;gt;foo.elf&amp;lt;/tt&amp;gt; für einen [[ATmega32]] zu compileren, würde man angeben&lt;br /&gt;
 &amp;gt; avr-gcc -Os -mmcu=atmega32 foo.c -o foo.elf&lt;br /&gt;
Hat man seine Quellen auf zwei oder mehre Dateien verteilt, geht es analog:&lt;br /&gt;
 &amp;gt; avr-gcc -Os -mmcu=atmega32 foo.c foo2.c -o foo.elf&lt;br /&gt;
&lt;br /&gt;
Will man nur eine Objekt-Datei erstellen (nur compilieren, nicht linken), dann geht das wie folgt. Das kann günstig sein bei grösseren Projekten, wenn man das Projekt neu erzeugen will, aber nur in einer Quelldatei was geändert hat. Oder wenn das Objekt in einer Bibliothek landen soll.&lt;br /&gt;
 &amp;gt; avr-gcc -Os -c -mmcu=atmega32 foo.c -o foo.o&lt;br /&gt;
&lt;br /&gt;
Die ausführbare Gesamtdatei &amp;lt;tt&amp;gt;foo_all.elf&amp;lt;/tt&amp;gt; erhält man dann, indem alle Objekte zusammenlinkt:&lt;br /&gt;
 &amp;gt; avr-gcc -mmcu=atmega32 foo.o foo2.o foo3.o -o foo_all.elf&lt;br /&gt;
&lt;br /&gt;
Um die ausführbare Datei in das oft verwendete Intex-HEX-Format umzuwandeln (einmal fürs Programm, einmal für ein Abbild des [[EEPROM]]s) gibt man an:&lt;br /&gt;
 &amp;gt; avr-objcopy -O ihex -j .text -j .data                         foo_all.elf  foo_all.hex&lt;br /&gt;
 &amp;gt; avr-objcopy -O ihex -j .eeprom --change-section-lma .eeprom=1 foo_all.elf  foo_all_eeprom.hex&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
[[GCC]] war immer Kommandozeilen-orientiert und wird es auch immer bleiben, denn das hat gute Gründe:&lt;br /&gt;
* ein Compiler ist ein Compiler (und keine grafische Bedienschnittstelle)&lt;br /&gt;
* die Plattformabhängigkeit wird auf ein Minimum reduziert&lt;br /&gt;
* es gibt die Möglichkeit, avr-gcc per Skript oder [[make]] zu starten&lt;br /&gt;
* avr-gcc kann durchaus in eine Umgebung integriert werden: in einen Editor oder in eine GUI wie neuere Versionen von AVR-Studio erfolgreich beweisen, etc. Der avr-gcc-Aufruf kann sogar von einem Server-Socket oder einer Web-Application heraus erfolgen, welche ein C-Programm empfängt, es von avr-gcc übersetzen lässt, und das Resultat zurückschickt oder sonst was damit anstellt.&lt;br /&gt;
* Lizenzgründe: eine Umgebung, die avr-gcc integriert, kann durchaus proprietär oder nicht quelloffen sein und muss nicht der [[Freie Software|GPL]] unterliegen. Wieder ist AVR-Studio ein Beispiel.&lt;br /&gt;
&lt;br /&gt;
= Unterstützte AVR-Derivate=&lt;br /&gt;
&lt;br /&gt;
:→ ''[http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html GCC Manual: AVR Options]&lt;br /&gt;
&lt;br /&gt;
Diese Liste der unterstützten Devices kann man anzeigen lassen mit&lt;br /&gt;
 &amp;gt; avr-gcc --target-help&lt;br /&gt;
bzw. ab Version 4.7 mit&lt;br /&gt;
 &amp;gt; avr-gcc --help=target&lt;br /&gt;
&lt;br /&gt;
Siehe auch &amp;quot;AVR Options&amp;quot; in der GCC [[#Dokumentation|Dokumentation]].&lt;br /&gt;
&lt;br /&gt;
=Kommandozeilen-Optionen=&lt;br /&gt;
Die Codegenerierung bei avr-gcc wird über Kommandozeilen-Optionen gesteuert. Diese legen fest, für welchen Controller Code zu erzeugen ist, wie stark optimiert wird, ob Debug-Informationen erzeugt werden, etc. Die Optionen teilen sich in zwei Gruppen: Optionen, die für alle GCC-Ports verfürgbar sind und maschinenspezifische Optionen, die nur für AVR verfügbar sind.&lt;br /&gt;
&lt;br /&gt;
Aus der Masse an GCC-Optionen kann hier nur ein kleiner Auszug der wichtigsten und am häufigsten verwendeten Optionen vorgestellt werden. Eine Auflistung aller GCC-Optionen mit Kurzbeschreibung umfasst knapp 1000 Zeilen &amp;amp;#150; ohne undokumentierte Optionen, versteht sich.&lt;br /&gt;
&lt;br /&gt;
==Allgemeine Optionen für GCC==&lt;br /&gt;
; &amp;lt;tt&amp;gt;--help&amp;lt;/tt&amp;gt;: Anzeige der wichtigsten Optionen&lt;br /&gt;
; &amp;lt;tt&amp;gt;--help -v&amp;lt;/tt&amp;gt;: Überschüttet einen mit Optionen&lt;br /&gt;
; &amp;lt;tt&amp;gt;--target-help&amp;lt;br/&amp;gt;--help=target&amp;lt;/tt&amp;gt;: Anzeige der wichtigsten maschinenspezifischen Optionen und der unterstützten AVR-Derivate&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O0&amp;lt;/tt&amp;gt;: keine Optimierung - sinnvoll zum debuggen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O1&amp;lt;/tt&amp;gt;: Optimierung&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Os&amp;lt;/tt&amp;gt;: optimiert für Code-Größe – meist beste Wahl für µCs&lt;br /&gt;
; &amp;lt;tt&amp;gt;-O2&amp;lt;/tt&amp;gt;: stärkere Optimierung für bessere Laufzeit&lt;br /&gt;
; &amp;lt;tt&amp;gt;-g&amp;lt;/tt&amp;gt;: erzeugt Debug-Informationen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-gdwarf-3 -gstrict-dwarf&amp;lt;/tt&amp;gt;: erzeugt Debug-Informationen nachdem DWARF-3 Standard und ohne GNU-spezifische Erweiterungen.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-c&amp;lt;/tt&amp;gt;: (pre)compilert und assembliert nur bis zum Objekt (&amp;lt;tt&amp;gt;*.o&amp;lt;/tt&amp;gt;), kein Link-Lauf&lt;br /&gt;
; &amp;lt;tt&amp;gt;-S&amp;lt;/tt&amp;gt;: (pre)compilert nur und erzeugt Assembler-Ausgabe (&amp;lt;tt&amp;gt;*.s&amp;lt;/tt&amp;gt;)&lt;br /&gt;
; &amp;lt;tt&amp;gt;-E&amp;lt;/tt&amp;gt;: nur Precompilat (&amp;lt;tt&amp;gt;*.i&amp;lt;/tt&amp;gt; bzw. &amp;lt;tt&amp;gt;*.ii&amp;lt;/tt&amp;gt;) erzeugen, kein Compilieren, kein Assemblieren, kein Linken&lt;br /&gt;
; &amp;lt;tt&amp;gt;-o &amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: legt den Name der Ausgabedatei fest&lt;br /&gt;
; &amp;lt;tt&amp;gt;-v&amp;lt;/tt&amp;gt;: zeigt Versionsinformationen an und ist geschwätzig (verbose): Anzeige der aufgerufenen tools&lt;br /&gt;
; &amp;lt;tt&amp;gt;-I&amp;lt;path&amp;gt;&amp;lt;/tt&amp;gt;: Angabe eines weiteren Include-Pfads, in dem Dateien mit &amp;lt;tt&amp;gt;#include &amp;lt;...&amp;gt;&amp;lt;/tt&amp;gt; gesucht werden&lt;br /&gt;
; &amp;lt;tt&amp;gt;-E -dM &amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Anzeige aller Defines&lt;br /&gt;
; &amp;lt;tt&amp;gt;-MM&amp;lt;/tt&amp;gt;: Für die angegebenen Eingabe-Dateien wird eine Ausgabe erzeugt, die als [[make|Makefile]]-Fragment dienen kann und die Anhängigkeiten (dependencies) der Objekte von den Quellen/Headern beschreibt.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-D&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;: Definiert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-D&amp;lt;name&amp;gt;=&amp;lt;wert&amp;gt;&amp;lt;/tt&amp;gt;: Definiert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt; zu &amp;lt;tt&amp;gt;&amp;lt;wert&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-U&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;: Undefiniert Makro &amp;lt;tt&amp;gt;&amp;lt;name&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-save-temps&amp;lt;/tt&amp;gt;: Temporäre Dateien (&amp;lt;tt&amp;gt;*.i&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;*.s&amp;lt;/tt&amp;gt;) werden nicht gelöscht.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wa,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;: übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Assembler (&amp;lt;tt&amp;gt;avr-as&amp;lt;/tt&amp;gt;)&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wa,-a=&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Assembler erzeugt ein Listing mit Name &amp;lt;tt&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wp,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;:  übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Preprozessor&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wl,&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt;:  übergibt Komma-getrennte Liste &amp;lt;tt&amp;gt;&amp;lt;options&amp;gt;&amp;lt;/tt&amp;gt; an den Linker (&amp;lt;tt&amp;gt;avr-ld&amp;lt;/tt&amp;gt;)&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wl,-Map=&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;: Linker erzeugt ein Map-File mit Name &amp;lt;tt&amp;gt;&amp;lt;filename&amp;gt;&amp;lt;/tt&amp;gt;&lt;br /&gt;
:;&amp;lt;tt&amp;gt;-Wl,--section-start=&amp;lt;section&amp;gt;=&amp;lt;address&amp;gt;&amp;lt;/tt&amp;gt;: Linker legt die [[avr-gcc/Interna#Sections|Section]] &amp;lt;tt&amp;gt;&amp;lt;section&amp;gt;&amp;lt;/tt&amp;gt; ab Adresse &amp;lt;tt&amp;gt;&amp;lt;address&amp;gt;&amp;lt;/tt&amp;gt;, z.B: &amp;lt;tt&amp;gt;.eeprom=0x810001&amp;lt;/tt&amp;gt;&lt;br /&gt;
; &amp;lt;tt&amp;gt;-Wall&amp;lt;/tt&amp;gt;: gibt mehr Warnungen, aber immer noch nicht alle&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=gnu99&amp;lt;/tt&amp;gt;: Sagt dem Compiler, dass er C99 mit GNU-C Erweiterungen akzeptieren soll.  Das ist zum Beispiel der Fall, wenn man Embedded-C Code mit &amp;lt;tt&amp;gt;__flash&amp;lt;/tt&amp;gt; verwenden will.&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c89&amp;lt;br/&amp;gt;-ansi&amp;lt;/tt&amp;gt;: bricht mit einer Fehlermeldung ab, wenn kein ANSI-C (ISO C89) verwendet wurde&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c99&amp;lt;/tt&amp;gt;: C99 mit einigen Erweiterungen, die nicht dem C99-Standard widersprechen&lt;br /&gt;
; &amp;lt;tt&amp;gt;-std=c99 -pedantic&amp;lt;/tt&amp;gt;: Bricht mit einer Fehlermeldung ab, wenn kein ISO C99 verwendet wird&lt;br /&gt;
&lt;br /&gt;
==Maschinenspezifische Optionen für avr-gcc==&lt;br /&gt;
&lt;br /&gt;
Maschinenabhängige Optionen beginnen immer mit '''-m'''&lt;br /&gt;
;-mmcu=xxx: Festlegen des Targets (Zielsystem/Controller), für das Code generiert werden soll. Je nach Target muss avr-gcc unterschiedliche Instruktionen verwenden und andere Startup-Dateien (&amp;lt;tt&amp;gt;crtxxx.o&amp;lt;/tt&amp;gt;) einbinden. avr-gcc setzt spezielle Defines, um auch in der Quelle zwischen den Targets unterscheiden zu können, falls das notwendig sein sollte: &lt;br /&gt;
:{| border=&amp;quot;0&amp;quot; cellpadding=&amp;quot;0&amp;quot; cellspacing=&amp;quot;0&amp;quot;&lt;br /&gt;
|&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#ifdef __AVR_AT90S2313__&lt;br /&gt;
/* Code fuer AT90S2313 */&lt;br /&gt;
#elif defined (__AVR_ATmega8__) || defined (__AVR_ATmega32__)&lt;br /&gt;
/* Code fuer Mega8 und Mega32 */ &lt;br /&gt;
#else&lt;br /&gt;
#error Das ist noch nicht implementiert für diesen Controller!&lt;br /&gt;
#endif&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
: Zwar gibt es für alle AVR-Derivate die &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt;, aber die AVR-Familien unterscheiden sich in ihrer Hardware; z.B. darin, wie I/O-Register heissen oder wie Hardware zu initialisieren ist. Diese Abhängigkeit kann man in unterschiedlichen Codestücken aufteilen und wie oben gezeigt bedingt übersetzen. Dadurch hat man Funktionalitäten wie &amp;lt;tt&amp;gt;uart_init&amp;lt;/tt&amp;gt; auf unterschiedlichen Controllern und wahrt den Überblick, weil nicht für jede Controller-Familie eine extra Datei notwendig ist.&lt;br /&gt;
&lt;br /&gt;
: Built-in Makros wie &amp;lt;tt&amp;gt;__AVR_ATmega8__&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;__AVR_ARCH__&amp;lt;/tt&amp;gt; sind ab Version 4.7 im Kapitel &amp;quot;AVR Options&amp;quot; in der GCC [[#Dokumentation|Dokumentation]] erklärt, siehe z.B. [http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html &amp;quot;AVR Built-in Macros&amp;quot;].&lt;br /&gt;
&lt;br /&gt;
; -mint8: Datentyp &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; ist nur 8 Bit breit anstatt 16 Bit. Datentypen mit 64 Bit sind nicht verfügbar.  8-Bit &amp;lt;tt&amp;gt;int&amp;lt;/tt&amp;gt; ist nicht C-Standard konform und wird nicht von der AVR Libc unterstützt (ausser in &amp;lt;tt&amp;gt;stdint.h&amp;lt;/tt&amp;gt;).&lt;br /&gt;
; -mno-interrupts: Ändert den Stackpointer ohne Interrupts zu deaktivieren&lt;br /&gt;
; -mcall-prologues: Funktions-Prolog und -Epilog werden als Unterroutinen umgesetzt, um die Codegröße zu verkleinern&lt;br /&gt;
; -mtiny-stack: Nur die unteren 8 Bit des Stackpointers werden verändert&lt;br /&gt;
&lt;br /&gt;
=C++=&lt;br /&gt;
&lt;br /&gt;
:''&amp;quot;C++ is a complex language and an evolving one, and its standard definition (the ISO C++ standard) was only recently completed. As a result, your C++ compiler may occasionally surprise you, even when its behavior is correct.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Zudem sollte der Einsatz von C++ aus Effizienzgründen sehr kritisch betrachtet werden:&lt;br /&gt;
:''&amp;quot;When programming C++ in space- and runtime-sensitive environments like microcontrollers, extra care should be taken to avoid unwanted side effects of the C++ calling conventions like implied copy constructors that could be called upon function invocation etc. These things could easily add up into a considerable amount of time and program memory wasted. Thus, casual inspection of the generated assembler code (using the &amp;lt;tt&amp;gt;-S&amp;lt;/tt&amp;gt; compiler option) seems to be warranted.&amp;quot;''&lt;br /&gt;
&lt;br /&gt;
Weiterhin unterliegt der Einsatz von C++ je nach Compiler/Lib-Version bestimmten Einschränkungen:&lt;br /&gt;
*Einer kompletten C++ Implementierung fehlt die Unterstützung durch die &amp;lt;tt&amp;gt;libstdc++&amp;lt;/tt&amp;gt;, dadurch fehlen Standardfunktionen, -Klassen und -Templates&lt;br /&gt;
* Die Operatoren &amp;lt;tt&amp;gt;new&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;delete&amp;lt;/tt&amp;gt; sind nicht implementiert, ihre Verwendung führt zu unauflösbaren externen Referenzen (Linker-Fehler)&lt;br /&gt;
*Nicht alle Header sind C++-sicher und müssen in &amp;lt;tt&amp;gt;extern &amp;quot;C&amp;quot; {...}&amp;lt;/tt&amp;gt; eingeschlossen werden.&lt;br /&gt;
*Exceptions werden nicht unterstützt und müssen via &amp;lt;tt&amp;gt;-fno-exceptions&amp;lt;/tt&amp;gt; abgeschaltet werden, oder der Linker beschwert sich über eine unauflösbare externe Referenz zu &amp;lt;tt&amp;gt;__gxx_personality_sj0&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
Als Treiber verwendet man wie immer avr-gcc. Standard-Endungen für C++ sind &amp;lt;tt&amp;gt;.c++&amp;lt;/tt&amp;gt; und &amp;lt;tt&amp;gt;.cpp&amp;lt;/tt&amp;gt;. Bei anderen Endungen teilt man mit &amp;lt;tt&amp;gt;-x c++&amp;lt;/tt&amp;gt; mit, daß es sich um C++ Dateien handelt, oder ruft &amp;lt;tt&amp;gt;avr-c++&amp;lt;/tt&amp;gt; direkt auf.&lt;br /&gt;
&lt;br /&gt;
Interrupt-Service-Routinen (ISRs) sind C-Funktionen und werden definiert wie gehabt. Siehe auch [[#Interrupts|Interrupts]].&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 #if defined (__cplusplus)&lt;br /&gt;
 extern &amp;quot;C&amp;quot; {&lt;br /&gt;
 #endif {{comment|__cplusplus}}&lt;br /&gt;
 &lt;br /&gt;
 SIGNAL (SIG_NAME)&lt;br /&gt;
 {&lt;br /&gt;
    {{comment|machwas}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 INTERRUPT (SIG_NAME)&lt;br /&gt;
 {&lt;br /&gt;
    {{comment|mach was}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 #if defined (__cplusplus)&lt;br /&gt;
 }&lt;br /&gt;
 #endif {{comment|__cplusplus}}&lt;br /&gt;
&amp;lt;tt&amp;gt;__cplusplus&amp;lt;/tt&amp;gt; ist ein Standard [[avr-gcc/Interna#Builtin Defines|GCC-Builtin-Define]].&lt;br /&gt;
&lt;br /&gt;
Globale Konstruktoren werden in [[avr-gcc/Interna#Sections|Section]] &amp;lt;tt&amp;gt;.init6&amp;lt;/tt&amp;gt; ausgeführt, die Destruktoren in &amp;lt;tt&amp;gt;.fini6&amp;lt;/tt&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
=Code-Beispiele=&lt;br /&gt;
Dieser Abschnitt enthält Code-Schnippsel für avr-gcc. Es werden Besonderheiten besprochen, die für avr-gcc zu beachten sind. &lt;br /&gt;
&lt;br /&gt;
Dieser Abschnitt ist ''kein'' [[C-Tutorial|Tutorial zur C-Programmierung]] und ''keine'' Einführung in die Programmiersprache C im allgemeinen. Dafür sei auf einschlägige Tutorials/Bücher verwiesen.&lt;br /&gt;
&lt;br /&gt;
==Zugriff auf Special Function Registers (SFRs)==&lt;br /&gt;
&lt;br /&gt;
===Zugiff auf Bytes und Worte===&lt;br /&gt;
Für den Zugriff auf die SFRs gibt es Defines über den Include&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
Abhängig vom eingestellten Controller werden dann Defines eingebunden, über die auf SFRs wie auf normale Variablen zugegriffen werden kann. Die Namen der Defines sind i.d.R. die gleichen wie im AVR-Manual, also z.b. &amp;lt;tt&amp;gt;SREG&amp;lt;/tt&amp;gt; für das Prozessorstatus-Register SREG:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 ...&lt;br /&gt;
   {{ccomment|SREG lesen}}&lt;br /&gt;
   uint8_t sreg = SREG;&lt;br /&gt;
   ...&lt;br /&gt;
   {{ccomment|SREG schreiben}}&lt;br /&gt;
   SREG = sreg;&lt;br /&gt;
&amp;lt;!--  &lt;br /&gt;
Auf SFRs wird generell über deren Adresse zugegriffen:&lt;br /&gt;
 {{ccomment|Liest den Inhalt von SREG an Adresse 0x5f}}&lt;br /&gt;
 unsigned char sreg = *((unsigned char volatile*) 0x5f);&lt;br /&gt;
Das bedeutet in etwa: &amp;quot;Lies ein flüchtiges (&amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt;) Byte (&amp;lt;tt&amp;gt;unsigned char&amp;lt;/tt&amp;gt;) von Adresse &amp;lt;tt&amp;gt;0x5f&amp;lt;/tt&amp;gt;&amp;quot;. Der Speicherinhalt von SFRs ist flüchtig, denn er kann sich ändern, ohne daß avr-gcc dies mitbekommt. Daher muss bei jedem C-Zugriff auf ein SFR dieses wirklich gelesen/geschrieben werden, was der Qualifier &amp;lt;tt&amp;gt;volatile&amp;lt;/tt&amp;gt; sicherstellt. Ansonst geht der Compiler u.U. davon aus, daß der Inhalt bekannt ist und verwendet einen alten, in einem GPR befindlichen Wert.&lt;br /&gt;
&lt;br /&gt;
Um lesbaren, weniger fehleranfälligen und unter AVRs halbwegs portierbaren Code zu erhalten, gibt es Makrodefinitionen im Controller-spezifischen Header &amp;lt;tt&amp;gt;ioxxxx.h&amp;lt;/tt&amp;gt;, der neben anderen Dingen mit &amp;lt;tt&amp;gt;avr/io.h&amp;lt;/tt&amp;gt; includet wird:&lt;br /&gt;
Die Bezeichner der SFRs sind die gleichen wie im Manual.&lt;br /&gt;
--&amp;gt;&lt;br /&gt;
Für einen Überblick über die eingebundenen Defines kann ein Blick in den Controller-spezifischen Header hilfreich sein. Dieser befindet sich in&lt;br /&gt;
:&amp;lt;tt&amp;gt; &amp;amp;lt;GCC_HOME&amp;amp;gt;/avr/include/avr/io****.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
z.B. &amp;lt;tt&amp;gt;iom32.h&amp;lt;/tt&amp;gt; für einen [[ATmega32]].&lt;br /&gt;
&lt;br /&gt;
Dieser Zugriff geht auch für 16-Bit Register wie &amp;lt;tt&amp;gt;TCNT1&amp;lt;/tt&amp;gt; oder &amp;lt;tt&amp;gt;ADC&amp;lt;/tt&amp;gt;, für die eine bestimmte Reihenfolge für den Zugriff auf Low- und High-Teil eingehalten werden muss: avr-gcc generiert die Zugriffe in der richtigen Reihenfolge.&lt;br /&gt;
  uint16_t tcnt1 = TCNT1;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Zu beachten ist, daß dieser Zugriff nicht atomar erfolgt. Das Lesen/Schreiben mehrbytiger Werte muss vom Compiler in mehrere Byte-Zugriffe zerlegt werden. Zwischen diesen Zugriffen kann ein [[Interrupt]] auftreten, wenn Interrupts aktiviert sind. Je nach Programm und welche Aufgaben eine [[ISR]] erledigt, kann dies zu Fehlfunktion führen. In dem Fall müssen diese Code-Stücke atomar gemacht werden, damit sie nicht durch einen [[IRQ]] unterbrochen werden können!&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
===Zugriff auf einzelne Bits===&lt;br /&gt;
Zugriff auf Bits geht wie gewohnt mit den Bitoperationen &lt;br /&gt;
&amp;lt;tt&amp;gt;&amp;amp;amp;&amp;lt;/tt&amp;gt; (and),&lt;br /&gt;
&amp;lt;tt&amp;gt;|&amp;lt;/tt&amp;gt; (or),&lt;br /&gt;
&amp;lt;tt&amp;gt;^&amp;lt;/tt&amp;gt; (xor) und&lt;br /&gt;
&amp;lt;tt&amp;gt;~&amp;lt;/tt&amp;gt; (not)&lt;br /&gt;
&lt;br /&gt;
Wieder gibt es Defines in den AVR-Headern, mit denen man Masken für den Zugriff erhalten kann, etwa:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
/* GIMSK / GICR */&lt;br /&gt;
#define INT1    7&lt;br /&gt;
#define INT0    6&lt;br /&gt;
#define IVSEL   1&lt;br /&gt;
#define IVCE    0&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Masken ergeben sich durch Schieben von &amp;lt;tt&amp;gt;1&amp;lt;/tt&amp;gt; an die richtige Position:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_0 und B_1 als Ausgang&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB0) | (1&amp;amp;lt;&amp;amp;lt;PB1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erzeugt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
87 b3           in      r24, 0x17&lt;br /&gt;
83 60           ori     r24, 0x03&lt;br /&gt;
87 bb           out     0x17, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Etwas anders sieht der Code aus, wenn die Bits einzeln gesetzt werden und das Register im bitadressierbaren Bereich liegt (SRAM &amp;lt;tt&amp;gt;0x20&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;0x3f&amp;lt;/tt&amp;gt; resp. I/O &amp;lt;tt&amp;gt;0x0&amp;lt;/tt&amp;gt; bis &amp;lt;tt&amp;gt;0x1f&amp;lt;/tt&amp;gt;):&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_0 und B_1 als Ausgang&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB0);&lt;br /&gt;
DDRB |= (1&amp;amp;lt;&amp;amp;lt;PB1);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
erzeugt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
b8 9a           sbi     0x17, 0&lt;br /&gt;
b9 9a           sbi     0x17, 1&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Um Bits zu löschen, erzeugt man eine Maske, die an der betreffenden Stelle eine &amp;amp;nbsp;0 hat:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// Ports B_2 als Eingang&lt;br /&gt;
DDRB &amp;amp;= ~(1&amp;amp;lt;&amp;amp;lt;PB2);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
{{FarbigerRahmen| &lt;br /&gt;
Auch hier ist zu beachten, daß es Probleme geben kann, wenn nicht atomarer Code erzeugt wird, weil der AVR-Befehlssatz nicht mehr hergibt:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
// toggle PORT B_0: wechseln 0 &amp;amp;lt;--&amp;amp;gt; 1 &lt;br /&gt;
PORTB ^= (1&amp;amp;lt;&amp;amp;lt;PB0);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
ergibt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
88 b3           in      r24, 0x18&lt;br /&gt;
; Wenn hier ein Interrupt auftritt, in dessen ISR PORTB verändert wird,&lt;br /&gt;
; dann wird die Änderung durch die letzte Instruktion wieder überschrieben!&lt;br /&gt;
91 e0           ldi     r25, 0x01&lt;br /&gt;
; dito&lt;br /&gt;
89 27           eor     r24, r25&lt;br /&gt;
; dito&lt;br /&gt;
88 bb           out     0x18, r24&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
}} &amp;lt;!-- /FarbigerRahmen --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Auch das Lesen einzelner Port-Pins geht über das Maskieren von SFRs:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
DDRB &amp;amp;= ~(1 &amp;lt;&amp;lt; PB2);    // PortB.2 als INPUT &lt;br /&gt;
&lt;br /&gt;
if (PINB &amp;amp; (1 &amp;lt;&amp;lt; PB2))&lt;br /&gt;
   // PortB.2 ist HIGH&lt;br /&gt;
else&lt;br /&gt;
   // PortB.2 ist LOW&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
if (!(PINB &amp;amp; (1 &amp;lt;&amp;lt; PB2)))&lt;br /&gt;
   // PortB.2 ist LOW&lt;br /&gt;
else&lt;br /&gt;
   // PortB.2 ist HIGH&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Interrupts==&lt;br /&gt;
&lt;br /&gt;
: → ''[http://nongnu.org/avr-libc/user-manual/group__avr__interrupts.html AVR-Libc: Dokumentation zu &amp;lt;tt&amp;gt;&amp;lt;avr/interrupt.h&amp;gt;&amp;lt;/tt&amp;gt;].&lt;br /&gt;
&lt;br /&gt;
Um zu kennzeichnen, daß es sich bei einer Funktion um eine Interrupt Sevice Routine (ISR) handelt, gibt es spezielle Attribute. Diese brauchen nicht explizit hingeschrieben zu werden, ebensowenig wie die genaue Nummer des Interrupt Requests (IRQ). Dafür gibt es Includes aus der AVR Libc und die folgenden Makros.&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Eine nichtunterbrechbare Interrupt-Service-Routine}}&lt;br /&gt;
 ISR (TIMER1_COMPA_vect)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|ISR-Code}}&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment|Eine unterbrechbare Interrupt-Service-Routine}}&lt;br /&gt;
 ISR (TIMER0_OVF_vect, ISR_NOBLOCK)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|ISR-Code}}&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Dadurch wird die Funktion mit dem richtigen Prolog/Epilog erzeugt, und es wird ein Eintrag in die Interrupt-Vektortabelle gemacht – bei obigem Beispiel also zwei Einträge.&lt;br /&gt;
&lt;br /&gt;
Mit Ausführung einer ISR deaktiviert die AVR-Hardware die Interrupts, so daß die ISR nicht durch andere Interrupt-Anforderungen unterbrochen wird. Beim Verlassen der ISR werden Interrupts wieder automatisch durch die AVR-Hardware aktiviert. Tritt während der ISR ein IRQ auf, wird diese erst nach Beenden des ISR-Codes ausgeführt. Der Interrupt geht also nicht verloren.  Dies gilt allerding nicht für Level-getriggerte IRQs wie für manche externen Interrupts oder TWI-Interrupts.  &lt;br /&gt;
&lt;br /&gt;
Zwischen zwei ISRs wird zusätzlich mindestens ein Befehl des normalen Programm-Codes abgearbeitet.&lt;br /&gt;
&lt;br /&gt;
Nachschlagen kann man die ISR-Namen im Device-spezifischen Header, die im Installationsverzeichnis liegen:&lt;br /&gt;
:&amp;lt;tt&amp;gt;&amp;amp;lt;GCC_HOME&amp;amp;gt;/avr/include/avr/ioxxxx.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===Interrupts aktivieren===&lt;br /&gt;
&lt;br /&gt;
Damit eine ISR überhaupt zur Ausführung kommt, müssen drei Bedingungen erfüllt sein&lt;br /&gt;
* Interrupts müssen global aktiviert sein&lt;br /&gt;
* Der entsprechen IRQ muss aktiviert worden sein&lt;br /&gt;
* Das zum IRQ gehörende Ereignis muss eintreten&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
    ...&lt;br /&gt;
    {{ccomment|enable OutputCompareA Interrupt für Timer1}}&lt;br /&gt;
    TIMSK |= (1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|disable OutputCompareA Interrupt für Timer1}}&lt;br /&gt;
    TIMSK &amp;amp;= ~(1 &amp;lt;&amp;lt; OCIE1A);&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts aktivieren}}&lt;br /&gt;
    sei();&lt;br /&gt;
 &lt;br /&gt;
    {{ccomment|Interrupts abschalten}}&lt;br /&gt;
    cli();&lt;br /&gt;
Sperrt man eine Code-Sequenz durch Einschachteln in ein &amp;lt;tt&amp;gt;cli&amp;lt;/tt&amp;gt;/&amp;lt;tt&amp;gt;sei&amp;lt;/tt&amp;gt; Paar (man macht das Codestück &amp;quot;atomar&amp;quot;, also ununterbrechbar), gehen währenddessen keine Interrupt-Anforderungen verloren. Die entsprechenden IRQ-Flags bleiben gesetzt, und nach dem &amp;lt;tt&amp;gt;sei&amp;lt;/tt&amp;gt; werden die IRQs in der Reihenfolge ihrer Prioritäten abgearbeitet. Ausnahme ist, wenn in einem atomaren Block der selbe IRQ mehrfach auftritt. Der ISR-Code wird dann trotzdem nur einmal ausgeführt.&lt;br /&gt;
&lt;br /&gt;
===default Interrupt===&lt;br /&gt;
&lt;br /&gt;
Für nicht implementierte Interrupts macht avr-gcc in die Vektortabelle einen Eintrag,&lt;br /&gt;
der zu &amp;lt;tt&amp;gt;__bad_interrupt&amp;lt;/tt&amp;gt; (definiert im Startup-Code &amp;lt;tt&amp;gt;crt*.o&amp;lt;/tt&amp;gt;) springt&lt;br /&gt;
und von dort aus weiter zu Adresse&amp;amp;nbsp;0. &lt;br /&gt;
Dadurch läuft der AVR wieder von neuem los, wenn ein Interrupt auftritt, &lt;br /&gt;
zu dem man keine ISR definiert hat &lt;br /&gt;
&amp;amp;#150; allerdings ohne die Hardware zurückzusetzen wie bei einem echten Reset.&lt;br /&gt;
&lt;br /&gt;
Möchte man diesen Fall abfangen, dann geht das über eine globale Funktion &lt;br /&gt;
namens &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt;:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
#include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
&lt;br /&gt;
ISR (__vector_default)&lt;br /&gt;
  ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
Damit wird von &amp;lt;tt&amp;gt;__bad_interrupt&amp;lt;/tt&amp;gt; aus nicht nach Adresse&amp;amp;nbsp;0 gesprungen,&lt;br /&gt;
sondern weiter zu &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt;, welches durch &amp;lt;tt&amp;gt;ISR()&amp;lt;/tt&amp;gt; den üblichen ISR-Prolog/Epilog bekommt.&lt;br /&gt;
&lt;br /&gt;
So kann man z.B. eine Meldung ausgeben, eine Warnlampe blinken, in einer Endlosschleife landen, oder über den [[Watchdog]] einen richtigen Hardware-Reset auslösen, siehe auch Abschnitt &amp;quot;[[#Reset auslösen|Reset auslösen]]&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
===ISR mit eigenem Prolog/Epilog===&lt;br /&gt;
&lt;br /&gt;
Wenn man in einer ISR komplett eigenes Zeug machen will, &lt;br /&gt;
dann definiert man eine naked Funktion.&lt;br /&gt;
Mit &amp;lt;tt&amp;gt;naked&amp;lt;/tt&amp;gt; befreit man die Routine vom Standard-Prolog/Epilog.&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Dabei ist darauf zu achten, daß die ISR mit &amp;lt;tt&amp;gt;reti&amp;lt;/tt&amp;gt; (return from interrupt) &lt;br /&gt;
zurückkehrt und evtl. verwendete Register und den Status (&amp;lt;tt&amp;gt;SREG&amp;lt;/tt&amp;gt;) sichert.&lt;br /&gt;
}}&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 ISR (TIMER0_OVF_vect, ISR_NAKED)&lt;br /&gt;
 {&lt;br /&gt;
    {{ccomment|Port B.6 &amp;amp;#61; 0}}&lt;br /&gt;
    {{ccomment|Diese Instruktion verändert nicht das SREG und kein anderes Register}}&lt;br /&gt;
    {{ccomment|so daß der eigentliche Code nur 1 Befehl lang ist}}&lt;br /&gt;
    __asm__ __volatile (&lt;br /&gt;
       &amp;quot;cbi %0, %1&amp;quot; &amp;quot;\n\t&amp;quot;&lt;br /&gt;
       &amp;quot;reti&amp;quot;&lt;br /&gt;
          : &lt;br /&gt;
          : &amp;quot;M&amp;quot; (_SFR_IO_ADDR (PORTB)), &amp;quot;i&amp;quot; (6)&lt;br /&gt;
    );&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
Siehe auch [[Inline-Assembler in avr-gcc]].&lt;br /&gt;
Die ISR sieht dann so aus:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
__vector_9:&lt;br /&gt;
   c6 98        cbi   0x18, 6&lt;br /&gt;
   18 95        reti&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Wiederum kann man als Funktionsname &amp;lt;tt&amp;gt;__vector_default&amp;lt;/tt&amp;gt; nehmen,&lt;br /&gt;
um nicht-implementierte IRQs abzufangen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
void __attribute__ ((naked)) &lt;br /&gt;
__vector_default (void)&lt;br /&gt;
 ...&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==SRAM, Flash, EEPROM: Datenablage am Beispiel Strings==&lt;br /&gt;
Die Programmiersprache C kennt selber keine Strings; das einzige, was C bekannt ist, ist der Datentyp &amp;lt;tt&amp;gt;char&amp;lt;/tt&amp;gt;, der ein einzelnes Zeichen repräsentiert. &lt;br /&gt;
===Darstellung in C===&lt;br /&gt;
Ein String im Sinne von C ist ein Array von Charactern bzw. ein Zeiger auf den Anfang des Arrays. Die einzelnen Zeichen folgen im Speicher direkt aufeinander und werden in aufsteigenden Adressen gespeichert. Am String-Ende folgt als Abschluss der Character &amp;lt;tt&amp;gt;'\0'&amp;lt;/tt&amp;gt;, um das Ende zu kennzeichnen. Dies ist besonders bei der Berechnung des Speicherplatzes für Strings zu berücksichtigen, denn für die 0 muss auch Platz reserviert werden.&lt;br /&gt;
&lt;br /&gt;
===Bestimmen der Stringlänge===&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 /* Bestimmt die Laenge des Strings ohne die abschliessende '\0' zu zaehlen */&lt;br /&gt;
 unsigned int strlength (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
   unsigned int len = 0;&lt;br /&gt;
   &lt;br /&gt;
   while (*str++)&lt;br /&gt;
      len++;&lt;br /&gt;
   &lt;br /&gt;
   return len;&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Die Stringlänge kann auch mit der Standard-Funktion &amp;lt;tt&amp;gt;strlen&amp;lt;/tt&amp;gt; bestimmt werden, deren Prototyp sich in &amp;lt;tt&amp;gt;string.h&amp;lt;/tt&amp;gt; befindet:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;string.h&amp;gt;&lt;br /&gt;
 size_t strlen (const char*);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String im Flash belassen===&lt;br /&gt;
Oftmals werden Strings nur zu Ausgabezwecken verwendet und nicht verändert. Verwendet man Sequenzen der Gestalt&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 char *str1 = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 char str2[] = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
dann werden die Strings im SRAM abgelegt. Im Startup-Code werden die Strings vom Flash ins SRAM kopiert und belegen daher sowohl Platz im SRAM als auch im Flash. Wird ein String nicht verändert, braucht er nicht ins SRAM kopiert zu werden. Das spart Platz im knapp bemessenen SRAM. Allerdings muss anders auf den String zugegriffen werden, denn wegen der Harvard-Architektur des AVR-Kerns kann avr-gcc anhand der Adresse nicht unterscheiden, ob diese ins SRAM, ins Flash oder ins EEPROM zeigt.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/pgmspace.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 const char str3[] PROGMEM = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 size_t strlen_P (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len = 0;&lt;br /&gt;
 &lt;br /&gt;
    while (1)&lt;br /&gt;
    {&lt;br /&gt;
       char c = (char) pgm_read_byte (str);&lt;br /&gt;
       if ('\0' == c)&lt;br /&gt;
          return len;&lt;br /&gt;
       len++;&lt;br /&gt;
       str++; &lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
 &lt;br /&gt;
 void foo (void)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len;&lt;br /&gt;
    len = strlen_P (str3);&lt;br /&gt;
    len = strlen_P (PSTR (&amp;quot;String im Flash&amp;quot;));&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
===String ins EEPROM legen===&lt;br /&gt;
Dies geht nach dem gleichen Muster, nach dem Strings ins Flash gelegt werden. Der Zugriff wird vergleichsweise langsam, denn der EEPROM ist langsamer als SRAM bzw. Flash.&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/eeprom.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 const char str4[] EEMEM = &amp;quot;Hallo Welt!&amp;quot;;&lt;br /&gt;
 &lt;br /&gt;
 size_t strlen_EE (const char *str)&lt;br /&gt;
 {&lt;br /&gt;
    size_t len = 0;&lt;br /&gt;
 &lt;br /&gt;
    while (1)&lt;br /&gt;
    {&lt;br /&gt;
       char c = (char) eeprom_read_byte (str);&lt;br /&gt;
       if ('\0' == c)&lt;br /&gt;
          return len;&lt;br /&gt;
       len++;&lt;br /&gt;
       str++; &lt;br /&gt;
    }&lt;br /&gt;
 }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Reset auslösen==&lt;br /&gt;
&lt;br /&gt;
Falls ein Reset per Software ausgelöst werden soll, dann geht das am besten über den [[Watchdog]].&lt;br /&gt;
Einfach nur an den Reset-Punkt an Adresse&amp;amp;nbsp;0 zu springen&lt;br /&gt;
initialisiert zwar den Controller von neuem, aber es macht keinen wirkliches RESET mit Zurücksetzen der Hardware und allen I/O-Registern. &lt;br /&gt;
&lt;br /&gt;
Durch den Watchdog kann man ein 'richtiges' RESET-Signal erzeugen lassen, so daß die AVR-Hardware genau so initialisiert ist, wie nach einem externen RESET. So kann man z.B. via [[UART]] ein RESET-Kommando schicken. Allerdings lässt sich der Watchdog nur minimal auf 15ms einstellen:&lt;br /&gt;
&lt;br /&gt;
 #include &amp;lt;avr/wdt.h&amp;gt;&lt;br /&gt;
 #include &amp;lt;avr/interrupt.h&amp;gt;&lt;br /&gt;
 ...   &lt;br /&gt;
    cli();                     {{ccomment|Interrupts global abschalten}}&lt;br /&gt;
    wdt_enable (WDTO_15MS);    {{ccomment|Watchdog aufziehen auf 15ms}}&lt;br /&gt;
    while (1);                 {{ccomment|warten, bis er zubeisst...}}&lt;br /&gt;
&lt;br /&gt;
Welches Ereignis einen RESET ausgelöst hat, kann man im Register '''MCUCSR''' (''MCU Control and Status Register'') erfahren. Es gibt 4 mögliche RESET-Quellen:&lt;br /&gt;
* Power-On Reset&lt;br /&gt;
* External Reset&lt;br /&gt;
* Brown-Out Reset&lt;br /&gt;
* Watchdog Reset&lt;br /&gt;
&lt;br /&gt;
Soll der Inhalt von Variablen einen Reset überleben &amp;amp;ndash; eine Variable also nicht initialisiert werden &amp;amp;ndash; dann geht das so:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
 &lt;br /&gt;
 {{ccomment| status informiert z.B. darüber, ob wir selber den Watchdog ausgelöst haben }}&lt;br /&gt;
 {{ccomment| oder nicht, oder andere Informationen }}&lt;br /&gt;
 uint8_t status __attribute__ ((__section__ (&amp;quot;.noinit&amp;quot;)));&lt;br /&gt;
 &lt;br /&gt;
 int main (void)&lt;br /&gt;
 {&lt;br /&gt;
     {{ccomment|Wert von MCUSCR merken, möglichst früh im Programm }}&lt;br /&gt;
     uint8_t mcucsr = MCUCSR;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|MCUCSR zurücksetzen }}&lt;br /&gt;
     MCUCSR = 0;&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Watchdog-Reset }}&lt;br /&gt;
     if (mcuscr &amp;amp; (1 &amp;lt;&amp;lt; WDRF))&lt;br /&gt;
     {&lt;br /&gt;
         {{ccomment|status auswerten }}&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|Power-On Reset: status auf definierten Wert setzen }}&lt;br /&gt;
     if (mcuscr &amp;amp; (1 &amp;lt;&amp;lt; PORF))&lt;br /&gt;
     {&lt;br /&gt;
         status = 0;&lt;br /&gt;
     }&lt;br /&gt;
 &lt;br /&gt;
     {{ccomment|status auswerten }}&lt;br /&gt;
     ...&lt;br /&gt;
 }&lt;br /&gt;
&lt;br /&gt;
; An Adresse 0 springen&lt;br /&gt;
&lt;br /&gt;
Falls wirklich zu Adresse 0 gesprungen werden soll – was in einem Bootloader erforderlich sein kann – dann geschieht das mittels einer Funktion &amp;lt;tt&amp;gt;reset&amp;lt;/tt&amp;gt; wie folgt:&lt;br /&gt;
 extern void reset (void) __attribute__((noreturn));&lt;br /&gt;
 reset();&lt;br /&gt;
&amp;lt;tt&amp;gt;reset&amp;lt;/tt&amp;gt; wird bein Linken mittels &amp;lt;tt&amp;gt;-Wl,--defsym=reset=0&amp;lt;/tt&amp;gt; auf&amp;amp;nbsp;0&amp;amp;nbsp;gesetzt.&lt;br /&gt;
Weitere Möglichkeit ist, im erzeugten Assembler&amp;amp;nbsp;&amp;lt;tt&amp;gt;0&amp;lt;/tt&amp;gt; als Funktionsnamen zu verwenden:&lt;br /&gt;
 extern void reset (void) __asm__(&amp;quot;0&amp;quot;) __attribute__((__noreturn__));&lt;br /&gt;
 reset();&lt;br /&gt;
&lt;br /&gt;
=Includes=&lt;br /&gt;
&lt;br /&gt;
Die mit&lt;br /&gt;
 #include &amp;lt;...&amp;gt;&lt;br /&gt;
angegebenen Includes werden von avr-gcc in den &lt;br /&gt;
mit der Option '&amp;lt;tt&amp;gt;-I&amp;lt;/tt&amp;gt;' anegegenen Pfaden gesucht. &lt;br /&gt;
Dem Compiler bekannt sind die Pfade &lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/avr/include                           Standard               (stdio.h, ...)&lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/avr/include/avr                       AVR-spezifisch         (avr/io.h, ...)&lt;br /&gt;
 &amp;lt;GCC_HOME&amp;gt;/lib/gcc/avr/&amp;lt;GCC_VERSION&amp;gt;/include     Standard, compilerabh. (limits.h, ...)&lt;br /&gt;
&lt;br /&gt;
Gibt man z.B. an &lt;br /&gt;
 #include &amp;lt;stdio.h&amp;gt;&lt;br /&gt;
dann wird automatisch in diesem Verzeichnis nach &amp;lt;tt&amp;gt;stdio.h&amp;lt;/tt&amp;gt; gesucht.&lt;br /&gt;
In den Verzeichnissen stehen Standard-Includes, die benötigt werden, wenn man libc-Funktionen &lt;br /&gt;
oder mathematische Funktionen etc. verwendet. &lt;br /&gt;
AVR-spezifische Dinge stehen im Unterverzeichnis &amp;lt;tt&amp;gt;avr&amp;lt;/tt&amp;gt;, etwa:&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
{{FarbigerRahmen|&lt;br /&gt;
Als Pfad-Separator wird immer ein '''&amp;lt;tt&amp;gt;/&amp;lt;/tt&amp;gt;''' verwendet, auch auf Windows-Betriebssystemen! Also kein '''&amp;lt;tt&amp;gt;\&amp;lt;/tt&amp;gt;'''&amp;amp;nbsp;!&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
==Standard==&lt;br /&gt;
&lt;br /&gt;
 ctype.h                   Zeichen-Umwandlungs-Makros und ctype Makros&lt;br /&gt;
 errno.h                   Symbolische Namen für Fehlercodes&lt;br /&gt;
 stdint, inttypes.h        C99 definiert [u]intN_t wenn man genau N [un]signed&lt;br /&gt;
                           Bits braucht&lt;br /&gt;
 math.h                    Mathematische Funktionen: sin, cos, log, gamma, bessel, ...&lt;br /&gt;
 setjmp.h                  libc unterstützt setjmp() und longjmp(), um direkt in eine&lt;br /&gt;
                           andere (nicht-lokale) Funktion zu springen. &lt;br /&gt;
 stdio.h                   Standard I/O-Funktionen (printf, fscanf, ...)&lt;br /&gt;
 stdlib.h                  Deklariert grundlegende ISO C Makros und Funktionen &lt;br /&gt;
                           sowie einige AVR-spezifische Erweiterungen&lt;br /&gt;
 string.h                  Stringoperationen auf NULL-terminierten Strings. (strlen, ...)&lt;br /&gt;
 stdarg.h                  Funktionen mit variabler Argumenanzahl&lt;br /&gt;
 limits.h                  Min- und Max-Werte von Skalaren (UCHAR_MAX, LONG_MIN, ...)&lt;br /&gt;
&lt;br /&gt;
==AVR-spezifisch==&lt;br /&gt;
&lt;br /&gt;
Die AVR-spezifischen Includes finden sich wie gesagt im Unterverzeichnis &amp;lt;tt&amp;gt;avr&amp;lt;/tt&amp;gt;.&lt;br /&gt;
Die meisten dort befindlichen Header wird man nie direkt durch Angabe im C-File erhalten,&lt;br /&gt;
sondern durch Angabe von&lt;br /&gt;
 #include &amp;lt;avr/io.h&amp;gt;&lt;br /&gt;
Dadurch werden genau die I/O-Header eingebunden, die zum AVR-Modell passen, also  z.B. &amp;lt;tt&amp;gt;avr/iom8.h&amp;lt;/tt&amp;gt; für [[ATmega8]] etc.  Verantwortlich für die Auswahl des richtigen Sub-Headers ist der Schalter '&amp;lt;tt&amp;gt;-mmcu=xxx&amp;lt;/tt&amp;gt;'.&lt;br /&gt;
&lt;br /&gt;
Obwohl diese Sub-Header nicht explizit angegeben werden müssen, &lt;br /&gt;
kann ein Blick dorthin hilfreich sein, um die Namen von [[SFR|SFRs]] &lt;br /&gt;
oder Signals nachzuschlagen. &lt;br /&gt;
Diese Header werden im folgenden nicht alle einzeln aufgelistet. &lt;br /&gt;
Ihre Namen sind immer &amp;lt;tt&amp;gt;avr/io*.h&amp;lt;/tt&amp;gt;.&lt;br /&gt;
* für ATmega: &amp;lt;tt&amp;gt;avr/iom*.h&amp;lt;/tt&amp;gt; &lt;br /&gt;
* für ATtiny: &amp;lt;tt&amp;gt;avr/iotn*.h&amp;lt;/tt&amp;gt;&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
avr/boot.h            Bootloader Support&lt;br /&gt;
avr/eeprom.h          EEPROM-Routinen&lt;br /&gt;
avr/interrupt.h       sei(), cli(), ISR(), ...&lt;br /&gt;
avr/io.h              RAMEND, ***_vect, SFRs: PORTB, DDRB, PINB, SREG, ..., &lt;br /&gt;
avr/pgmspace.h        Zugriff aufs Flash: Byte lesen, PROGMEM, pgm_read_***, ...&lt;br /&gt;
avr/sleep.h           Power-Safe und Sleep-Modes&lt;br /&gt;
avr/wdt.h             Watchdog&lt;br /&gt;
&lt;br /&gt;
util/crc16.h          Prüfsumme CRC16&lt;br /&gt;
util/delay.h          Verzögerungsschleifen für kurze, exakte Verzögerungen &lt;br /&gt;
util/parity.h         Parität&lt;br /&gt;
util/twi.h            I2C&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
==Anwendungs-spezifisch==&lt;br /&gt;
Eigene Header, die nur innerhalb eigener Projekte gebraucht werden, includet man mit&lt;br /&gt;
 #include &amp;quot;...&amp;quot;&lt;br /&gt;
Auch hier darf man Unterverzeichnisse angeben oder ins übergeordnete Verzeichnis:&lt;br /&gt;
 #include &amp;quot;../../mein-zeug.h&amp;quot;&lt;br /&gt;
Mit der Option &amp;lt;tt&amp;gt;-I&amp;lt;path&amp;gt;&amp;lt;/tt&amp;gt; kann ein Pfad zu den bekannten Include-Pfaden hinzugefügt werden; im obigen Beispiel etwa &amp;lt;tt&amp;gt;-I../..&amp;lt;/tt&amp;gt; und im Programm dann:&lt;br /&gt;
 #include &amp;quot;mein-zeug.h&amp;quot;&lt;br /&gt;
&lt;br /&gt;
= Optimierungen, Tipps &amp;amp; Tricks =&lt;br /&gt;
:→ ''Hauptartikel: [[avr-gcc/Optimierungen|avr-gcc Optimierungen]]''&lt;br /&gt;
&lt;br /&gt;
=Abkürzungen und Bezeichnungen=&lt;br /&gt;
; [[GCC]]: GNU Compiler Collection&lt;br /&gt;
; gcc: GNU C-Compiler&lt;br /&gt;
; GPR: '''G'''eneral '''P'''urpose '''R'''egister&lt;br /&gt;
; [[ISR]]: [[Interrupt|'''I'''nterrupt]] '''S'''ervice '''R'''outine&lt;br /&gt;
; [[IRQ]]: '''I'''nterrupt '''R'''e'''q'''uest&lt;br /&gt;
; Prolog/Epilog: Code am Anfang/Ende jeder Funktionen/ISR, der dazu dient, verwendete Register zu sichern, den Stack-Frame für lokale [[Variable|Variablen]] anzulegen (falls benötigt), Stackpointer zu setzen, zurück zu springen (&amp;lt;tt&amp;gt;ret&amp;lt;/tt&amp;gt;, &amp;lt;tt&amp;gt;reti&amp;lt;/tt&amp;gt;), etc.&lt;br /&gt;
; SFR: '''S'''pecial '''F'''unction '''R'''egister&lt;br /&gt;
; Target: Zielsystem, in unserem Falle avr&lt;br /&gt;
&lt;br /&gt;
=Siehe auch=&lt;br /&gt;
* [[C-Tutorial]]&lt;br /&gt;
'''Code-Beispiele'''&lt;br /&gt;
* [[Hallo Welt für AVR (LED blinken)]] - ein erstes Beispiel für avr-gcc&lt;br /&gt;
*[[:Kategorie:Quellcode_C|C-Codebeispiele]]&lt;br /&gt;
* [[Fallstricke bei der C-Programmierung]]&lt;br /&gt;
&lt;br /&gt;
'''Details'''&lt;br /&gt;
* [[Inline-Assembler in avr-gcc|Inline-Assembler]]&lt;br /&gt;
* [[avr-gcc/Interna|Interna von avr-gcc]]&lt;br /&gt;
&lt;br /&gt;
'''Installation (Linux)'''&lt;br /&gt;
* [[Linuxdistribution_Avr-live-cd]]&lt;br /&gt;
* [[avr-gcc und avrdude installieren]]&lt;br /&gt;
'''Sonstiges'''&lt;br /&gt;
* [[WinAVR]]&lt;br /&gt;
* [[Speicherverbrauch bestimmen mit avr-gcc]]&lt;br /&gt;
* [[Compiler]]&lt;br /&gt;
* [[Dev-Cpp IDE]]&lt;br /&gt;
* [[AVR]]&lt;br /&gt;
----&lt;br /&gt;
* [[Sourcevergleich]]&lt;br /&gt;
* [[Codevergleich AVR-Compiler]]&lt;br /&gt;
&lt;br /&gt;
=Weblinks=&lt;br /&gt;
==Dokumentation==&lt;br /&gt;
&lt;br /&gt;
;Offline:&lt;br /&gt;
&lt;br /&gt;
Je nach Distribution wird diese mit offline-Dokumentation als pdf, HTML, etc. ausgeliefert, die dann z.B. in Ordern wie den folgenden befindet:&lt;br /&gt;
&lt;br /&gt;
: &amp;lt;GCC_HOME&amp;gt;/doc/gcc/&lt;br /&gt;
: &amp;lt;GCC_HOME&amp;gt;/doc/avr-libc/&lt;br /&gt;
: etc.&lt;br /&gt;
&lt;br /&gt;
; Online&lt;br /&gt;
&lt;br /&gt;
* [http://gcc.gnu.org/onlinedocs/cpp.pdf cpp.pdf (470 kByte)] - Dokumentation des C-Präprozessors (en)&lt;br /&gt;
* [http://www.nongnu.org/avr-libc/user-manual/pages.html AVR Libc: User Manual] - Dokumentation zur [http://www.nongnu.org/avr-libc AVR Libc].&lt;br /&gt;
* [http://sourceware.org/binutils/docs/ Binutils: Documentation] – Dokumentation der Binutils: Assembler, Linker, ...&lt;br /&gt;
* [http://gcc.gnu.org/wiki/avr-gcc avr-gcc im GCC Wiki] – Dokumentation des Application Binary Interface (ABI): Registerverwendung, Calling Conventions, ...&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
! [http://gcc.gnu.org GCC] Version ||colspan=&amp;quot;2&amp;quot;| [http://gcc.gnu.org/onlinedocs Dokumentation] || AVR Options || Release Notes&lt;br /&gt;
|-&lt;br /&gt;
! Aktuelle Entwicklung&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-5/changes.html GCC 5]&lt;br /&gt;
|-&lt;br /&gt;
! 4.9.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.9.1/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.9/changes.html GCC 4.9]&lt;br /&gt;
|-&lt;br /&gt;
! 4.8.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.8.3/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.8/changes.html GCC 4.8]&lt;br /&gt;
|-&lt;br /&gt;
! 4.7.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.7.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.7/changes.html GCC 4.7]&lt;br /&gt;
|-&lt;br /&gt;
! 4.6.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.6.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.6/changes.html GCC 4.6]&lt;br /&gt;
|-&lt;br /&gt;
! 4.5.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.5.4/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.5/changes.html GCC 4.5]&lt;br /&gt;
|-&lt;br /&gt;
! 4.4.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.4.7/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.4/changes.html GCC 4.4]&lt;br /&gt;
|-&lt;br /&gt;
! 4.3.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-4.3.5/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-4.3/changes.html GCC 4.3]&lt;br /&gt;
|-&lt;br /&gt;
! 3.4.x&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/ HTML]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc.pdf pdf]&lt;br /&gt;
| [http://gcc.gnu.org/onlinedocs/gcc-3.4.6/gcc/AVR-Options.html online]&lt;br /&gt;
| [http://gcc.gnu.org/gcc-3.4/changes.html GCC 3.4]&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
== Downloads==&lt;br /&gt;
* [http://sourceforge.net/projects/winavr/ WinAVR-Projekt bei sourceforge.net (en)]&lt;br /&gt;
* [http://cdk4avr.sourceforge.net/ avr-gcc und toolchain als Linux-Paket bei sourceforge.net (en)]&lt;br /&gt;
* [[Linuxdistribution_Avr-live-cd]]&lt;br /&gt;
== Tipps, Installation ==&lt;br /&gt;
*[http://www.nongnu.org/avr-libc/user-manual/install_tools.html ''&amp;quot;Installing the GNU Tool Chain&amp;quot;''] Hilfe zum Build und Installation von GCC, binutils, etc unter Linux&lt;br /&gt;
* Im GCC-Handbuch, siehe [[#Dokumentation|Dokumentation]].&lt;br /&gt;
* [http://www.linuxfocus.org/Deutsch/November2004/article352.shtml www.linuxfocus.org (Artikel)] - Tipps zu Build und Installation von avr-gcc, binutils und avr-libc unter Linux&lt;br /&gt;
* [http://users.rcn.com/rneswold/avr/ Rich Neswold: ''A GNU Development Environment for the AVR Microcontroller'']&lt;br /&gt;
* [http://www.mikrocontroller.net/topic/24166 www.mikrocontroller.net (Foren-Beitrag)] - Installation von GCC und Toolchain unter Mac OS X&lt;br /&gt;
* [http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=125603#125603 www.roboternetz.de (Foren-Beitrag)] ''avrgcc + avrdude installieren''&lt;br /&gt;
* [http://roboternetz.de/download/c_tutorial.zip AVR-Studio &amp;amp; C-Tutorial mit Installationsanleitung]&lt;br /&gt;
&lt;br /&gt;
== Sonstiges ==&lt;br /&gt;
* [http://gcc.gnu.org/ Offizielle Homepage von GCC (en)]&lt;br /&gt;
* [http://de.wikipedia.org/wiki/GNU_Compiler_Collection GCC in der deutschen Wikipedia]&lt;br /&gt;
* [http://www.mikrocontroller.net/articles/AVR-GCC-Tutorial avr-gcc-Tutorial auf mikrocontroller.net]&lt;br /&gt;
* [http://savannah.nongnu.org/projects/avr-libc/ Nützliche GCC Runtime-Libary]&lt;br /&gt;
* [http://www.stromflo.de/dokuwiki/doku.php Atxmega-C-Tutorial]&lt;br /&gt;
&lt;br /&gt;
=Autor=&lt;br /&gt;
&lt;br /&gt;
--[[Benutzer:SprinterSB|SprinterSB]] 11:27, 7. Dez 2005 (CET)&lt;br /&gt;
&lt;br /&gt;
[[Kategorie:Grundlagen]]&lt;br /&gt;
[[Kategorie:Microcontroller]]&lt;br /&gt;
[[Kategorie:Praxis]]&lt;br /&gt;
[[Kategorie:Quellcode C|!]]&lt;br /&gt;
[[Kategorie:Software]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25252</id>
		<title>Regelungstechnik</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25252"/>
				<updated>2014-09-13T08:50:00Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Dimensionierung des Reglers */ wikify tabelle&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Regelungen''' sind ein Bestandteil unseres Lebens und das nicht nur seit Erfindung der Dampfmaschine. &lt;br /&gt;
&lt;br /&gt;
Allein schon der aufrechte Gang funktioniert nur mit Regelung. Dabei wirken die Sinne als Sensoren, das Gehirn als Regler und die Muskeln als Aktuatoren. Weitere Regelungen in unserem Körper sind z.B. die Konstanthaltung der Körpertemperatur, der Blutdruck, die Anpassung der Pupille auf Helligkeitsänderungen usw.&lt;br /&gt;
&lt;br /&gt;
Im technischen Zeitalter ist der erste geschichtlich bedeutende Regler der Fliehkraftregler von James Watt, der für die Drehzahlregelung seiner Dampfmaschine eingesetzt wurde. Seitdem ist die Regelungstechnik aus keinem Technikbereich mehr wegzudenken. Die Regelungstechnik begegnet uns im täglichen Leben auf Schritt und Tritt: Der Temperaturregler der Zentralheizung, der Temperaturregler des Kühlschranks, der Regler für die Belichtungsautomatik im Fotoapparat, das ABS-System im Auto und die Netzspannungs- und Frequenzregelung des europäischen Versorgungsnetzes sind nur einige wenige Beispiele aus diesem Bereich. &lt;br /&gt;
&lt;br /&gt;
''Autor Waste''&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Regelung'' ist zu unterscheiden von dem im allgemeinen Sprachgebrauch oft synonym gebrauchten Begriff der ''Steuerung''. Das Steuern ist ein rein vorwärts gerichteter Prozess ohne Rückkopplung. Die Ausgangsgröße wird dabei nicht überwacht und kann sich durch Störungen von außen verändern. Ein Beispiel ist die Steuerung eines Motors mit einer einstellbaren Spannung. Durch Laständerungen wird sich die Drehzahl des Motors ändern. Soll nun die Drehzahl konstant gehalten werden, bedarf es einer Rückkopplung um über die Spannung die Drehzahl anzupassen. Diese Rückkopplung ist das Kennzeichen einer Regelung.&lt;br /&gt;
&lt;br /&gt;
Das Regeln ist ein Vorgang, bei dem die Ausgangsgröße, im Beispiel die Drehzahl, fortlaufend überwacht wird und bei Abweichung über die Stellgröße, im Beispiel die Spannung, korrigiert wird. Der sich dabei ergebende Wirkungsablauf findet in einem geschlossenen Kreis, dem Regelkreis, statt.&lt;br /&gt;
&lt;br /&gt;
==Der Regelkreis==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis1.png|right|thumb|300px|Ein Regelkreis (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip einer Regelung ist das fortlaufende: '''Messen – Vergleichen – Stellen'''&lt;br /&gt;
&lt;br /&gt;
;Messen: Die Regelgröße wird direkt oder mittels Sensoren gemessen.&lt;br /&gt;
;Vergleichen: Der Wert der Regelgröße wird mit dem Sollwert verglichen. Die Differenz ist die ''Regelabweichung''.&lt;br /&gt;
;Stellen: Aus der Regelabweichung wird unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke die ''Stellgröße'' bestimmt.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis2.png|thumb|350px|Wirkunsweise einer Regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis dient dazu, eine vorgegebene physikalische Größe, die ''Regelgröße'', auf einen gewünschten Wert (Sollwert) zu bringen und dort zu halten, unabhängig von eventuell auftretenden Störungen.&lt;br /&gt;
Um die Regelungsaufgabe zu erfüllen, muss der Augenblickswert der Regelgröße – der Istwert – gemessen und mit dem Sollwert verglichen werden. Bei auftretenden Abweichungen muss in geeigneter Art und Weise nachgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Um nun diese Aufgabe technisch zu lösen, gibt es die Regelungstechnik. Sie baut im wesentlichen auf die mathematische Beschreibung und Modellbildung des Systems Regelkreis. Zur Modellierung, Beschreibung und Simulation werden Blockschaltbilder mit diskreten Signalgliedern verwendet.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis3.png|thumb|350px|Beispiel einer Geschwindigkeits&amp;amp;shy;regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein typisches Beispiel für einen Regelkreis – eine Geschwindigkeits&amp;amp;shy;regelung – wird im nebenstehenden Bild gezeigt. Die Sollgeschwindigkeit ist 80 km/h. Durch eine äußere Störung, in dem Fall eine Steigung, verlangsamt sich das Fahrzeug auf 70 km/h. Die Abweichung wird durch das Tachometer erfasst. Als Korrekturmaßnahme wird mehr Gas gegeben, um wieder auf die Sollgeschwindigkeit von 80 km/h zu kommen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Begriffe ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis4.png|right]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis besteht entsprechend des vereinfachten Blockschaltbildes, wie es oft in der Regelungstechnik verwendet wird, aus den Hauptteilen ''Regler'' und ''Regelstrecke'':&lt;br /&gt;
&lt;br /&gt;
;Regler: Ist der Teil des Regelkreises, der unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke aus der Regelabweichung die Korrekturmaßnahmen zum Ausregeln ergreift.&lt;br /&gt;
&lt;br /&gt;
;Regelstrecke: Ist der Teil des Regelkreises, der vom Regler ausgeregelt werden soll.&lt;br /&gt;
&lt;br /&gt;
;Führungsgröße (Sollwert) w: Vorgegebener Wert, auf dem die Regelgröße durch die Regelung gehalten werden soll. Sie ist eine von der Regelung nicht beeinflusste Größe und wird von außen zugeführt.&lt;br /&gt;
&lt;br /&gt;
;Regelgröße (Istwert) x: Ist die Ausgangsgröße der Regelstrecke, die zum Zweck des Regelns erfasst und zum Vergleich rückgeführt wird. In vielen Fällen ist in der Rückführung noch eine Messeinrichtung (Sensor) gezeichnet, die den Istwert erfasst, hier der Einfachheit halber weggelassen.&lt;br /&gt;
&lt;br /&gt;
;Regelabweichung e: Differenz zwischen Führungsgröße und Regelgröße '''e = w – x''', bildet die eigentliche Eingangsgröße des Reglers.&lt;br /&gt;
&lt;br /&gt;
;Stellgröße y: Ausgangsgröße der Regeleinrichtung und zugleich Eingangsgröße der Strecke. Sie überträgt die steuernde Wirkung des Reglers auf die Strecke.&lt;br /&gt;
&lt;br /&gt;
;Störgröße z: Eine von außen wirkende Größe, die eine Änderung des Istwertes der Regelgröße bewirkt und einen Regelvorgang auslöst.&lt;br /&gt;
&lt;br /&gt;
==Die Regelstrecke==&lt;br /&gt;
Die Regelstrecke stellt den zu regelnden Teil bzw. den zu regelnden Prozess dar und umfasst normalerweise eine Reihe von einzelnen Gliedern. Die Glieder werden entsprechend ihrem Zeitverhalten charakterisiert. Um das Zeitverhalten herauszufinden, legt man an den Eingang ein Testsignal an und zeichnet die Antwort auf. Im einfachsten Fall wird der Eingang mit einer sprunghaften Änderung beaufschlagt. Die Antwort auf die sprunghafte Änderung der Eingangsgröße wird Sprungantwort genannt und gibt Aufschluss über die Art der Regelstrecke und kann eventuell bereits genutzt werden, um die Parameter der Regelstrecke zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Für den Aufbau eines gut funktionierenden Regelkreises und die Auslegung von Reglern ist es eine Voraussetzung zu wissen, wie die Regelstrecke reagiert. Ohne ein genaues Wissen um das dynamische Verhalten der Regelstrecke ist es nicht möglich geeignete Regler auszuwählen und diese zu parametrieren.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten dynamischen Grundelemente zur Charakterisierung der Regelstrecke sind nachfolgend aufgelistet. Jedes Element wird mit einem Block dargestellt und darin durch ein Symbol oder der stilisierten Sprungantwort gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Proportionalglied (P-Glied)===&lt;br /&gt;
[[File:pglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art einer Regelstrecke.&lt;br /&gt;
;Beispiele: Hebel, Getriebe, Verstärker, Spannungsteiler, Sensoren bei denen das Zeitverhalten vernachlässigt werden kann&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Integrator (I-Glied)===&lt;br /&gt;
[[File:iglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Strecke ohne Ausgleich, ist häufig in Regelstrecken vorhanden.&lt;br /&gt;
;Beispiele: Beschleunigung → Geschwindigkeit → Weg, Strom → Kondensatorspannung&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 0.Ordnung (Totzeitglied)===&lt;br /&gt;
[[File:ttglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Entsteht durch Laufzeiten von Material oder Signalen. Je größer die Verzögerungszeit einer Regelstrecke ist, um so schwieriger ist sie zu regeln. &lt;br /&gt;
;Beispiele: Förderband, Rechenzeit, A/D-Wandler&lt;br /&gt;
&lt;br /&gt;
Nicht zu verwechseln mit der Totzeit, die durch das asynchrone Auftreten eines Ereignisses auf einen Zyklus entsteht. Vom Verzögerungsglied 0.Ordnung unterscheidet sich diese dadurch, daß sie mit einer gleichverteilten Wahrscheinlichkeit zwischen &amp;quot;gar nicht&amp;quot;  und dem gesamten Umfang auftritt. Diese Totzeit ist mechanisch mit einem Spiel vergleichbar das &amp;quot;gar nicht&amp;quot; bis zum vollen Umfang zu einem Fehler beiträgt. &lt;br /&gt;
;Beispiele: Erkennen eines Signals an einem Mikroprozessor&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 1.Ordnung (PT1-Glied)===&lt;br /&gt;
[[File:pt1glied.gif]]&lt;br /&gt;
&lt;br /&gt;
Viele einfache Regelstrecken haben ein solches Verhalten bzw. können näherungsweise damit beschrieben werden. Ist ein P-Glied mit nicht vernachlässigbarem Zeitverhalten.&lt;br /&gt;
;Beispiele: Gleichstrommotor (Spannung → Drehzahl), näherungsweise; Widerstand-Kondensator-Schaltung (RC-Glied)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 2.Ordnung (PT2-Glied)===&lt;br /&gt;
Man unterscheidet schwingungsfähige und nicht schwingungsfähige PT2-Glieder. Zur Charakterisierung gibt es die Parameter Dämpfung D und Eckfrequenz w&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; oder die Zeitkonstanten T&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und T&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Für Dämpfung D&amp;lt;1 ist es schwingungsfähig.&lt;br /&gt;
&lt;br /&gt;
'''Schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2aglied.gif]]&lt;br /&gt;
;Beispiele: Mechanischer Schwinger (Feder-Masse-System), elektrischer Schwingkreis (RLC-Kreis)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nicht schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2bglied.gif]]&lt;br /&gt;
;Beispiele: Zwei hintereinander geschaltete PT1-Glieder, Gleichstrommotor (Spannung → Drehzahl) mit berücksichtigter Induktivität&lt;br /&gt;
&lt;br /&gt;
==Der Regler==&lt;br /&gt;
Der Regler hat die Aufgabe, die Regelgröße zu messen, sie mit dem Sollwert zu vergleichen und bei Abweichungen die Stellgröße so zu verändern, dass Soll- und Istwert der Regelgröße wieder übereinstimmen bzw. die Differenz minimal wird.&lt;br /&gt;
&lt;br /&gt;
Die Wahl eines bestimmten Reglertyps richtet sich nach dem geforderten Zeitverhalten und der geforderten Regelgenauigkeit der Regelstrecke. Nachfolgend finden Sie eine Zusammenfassung der wichtigsten klassischen Reglertypen:&lt;br /&gt;
&lt;br /&gt;
===P-Regler===&lt;br /&gt;
Der proportionalwirkende Regler multipliziert die Regelabweichung mit seinem Verstärkungsfaktor '''Kp''' und gibt das Ergebnis unverzögert weiter. Er unterscheidet sich prinzipiell nicht vom dynamischen Element P-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der P-geregelte Kreis ist einfach und mittelschnell im Vergleich zu anderen Regelungen. Das Problem ist die bleibende Regelabweichung!&lt;br /&gt;
&lt;br /&gt;
[[File:pregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software P-Regler:'''&lt;br /&gt;
 y = Kp * e&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===I-Regler===&lt;br /&gt;
Der integralwirkende Regler summiert die Regelabweichung über der Zeit auf und multipliziert die Summe (d.h. das Integral) mit dem Faktor '''Ki'''. Je länger eine Regelabweichung ansteht, desto größer wird die Stellgröße des I-Reglers. Er unterscheidet sich prinzipiell nicht vom dynamischen Element I-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der I-geregelte Kreis ist langsam im Vergleich zu anderen Regelungen. Er hat aber den Vorteil, dass die Abweichung vollständig eliminiert wird.&lt;br /&gt;
&lt;br /&gt;
[[File:iregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software I-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
'''esum''' ist die Summe aller bisherigen Abweichungen '''e'''. Der Parameter des Software I-Reglers ist abhängig von der Rechenschrittweite '''Ta''' (Abtastzeit). Je öfter gerechnet wird, desto öfter wird auch hinzugezählt (aufintegriert). Eine kleine Abtastzeit erfordert also einen kleineren Faktor, dies wird durch die Multiplikation mit '''Ta''' verwirklicht.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PI-Regler===&lt;br /&gt;
Der PI-Regler ist die Kombination aus P- und I-Regler und kombiniert den Vorteil des P-Reglers, nämlich schnelle Reaktion, mit dem Vorteil des I-Reglers, der exakten Ausregelung.  Der PI-geregelte Kreis ist also genau und mittelschnell.&lt;br /&gt;
&lt;br /&gt;
[[File:piregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PI-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PD-Regler===&lt;br /&gt;
Der proportional-differential wirkende Regler kombiniert den P-Regler mit einem D-Anteil. &lt;br /&gt;
Der D-Anteil bewertet die Änderung einer Regelabweichung (er differenziert) und berechnet so deren Änderungsgeschwindigkeit. Diese wird mit dem Faktor '''Kd''' multipliziert und zum P-Anteil hinzuaddiert. Der PD-Regler reagiert damit schon auf Ankündigungen von Veränderungen, das bewirkt sozusagen ein Vorhalten beim Regeln.&lt;br /&gt;
&lt;br /&gt;
Der PD-geregelte Kreis ist sehr schnell im Vergleich zu anderen Regelungen, und manche Regelkreise (solche mit zweifacher Integration) sind ohne D-Anteil überhaupt nicht stabilisierbar. Das Problem der proportionalen Regler, die bleibende Regelabweichung, ist beim PD-Regler allerdings weiterhin vorhanden!&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil aller Regler mit D-Anteil kann die Unruhe im Kreis sein. Ist das Sensorsignal verrauscht, so wird dieses Rauschen durch die Differenziation weiter verstärkt und wieder in den Kreis hineingegeben. Dadurch wird der Aktuator stärker belastet. Macht der Regler insbesondere sehr hohe Ausschläge als Folge von schnellen Änderungen des Sollwertes, dann kann es sein, dass das Stellglied oder der Aktuator diese nicht umsetzen kann - die Wirkung des D-Anteils würde dann durch die Begrenzung verpuffen, und das Einschwingverhalten wäre nicht wie berechnet, sondern meist langsamer. Dies gilt aber nur für große Sprünge. Bei den normalen kleinen Regelvorgängen zum Ausgleich von Störeinflüssen wirkt der D-Anteil wie beabsichtigt.&lt;br /&gt;
&lt;br /&gt;
[[File:pdregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PD-Regler:'''&lt;br /&gt;
 y = Kp * e + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
Mit der neuesten Regelabweichung '''e''' und der vorhergehenden '''ealt''' wird der D-Anteil berechnet. Die Differenziation erfolgt damit angenähert durch Bildung des Differenzquotienten (e - ealt)/Ta.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PID-Regler===&lt;br /&gt;
Der PID Regler ist der universellste der klassischen Regler und vereinigt die guten Eigenschaften der anderen Regler. Zur Beschreibung der Eigenschaften des P-, I- und D-Anteils siehe die anderen Reglertypen. Der PID-geregelte Kreis ist genau und sehr schnell. In den meisten Anwendungen kommt deshalb der PID-Regler zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
[[File:pidregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PID-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Alternative PID-Reglerstruktur:'''&lt;br /&gt;
&lt;br /&gt;
Es gibt 2 Darstellungsmöglichkeiten, die inhaltlich identisch sind. In der analogen Regeltechnik ist noch die Darstellung mit der Nachstellzeit '''Tn''' und der Vorhaltezeit '''Tv''' üblich. Die Umrechnung zwischen den beiden Strukturen ist mit den angegebenen Formeln möglich.&lt;br /&gt;
&lt;br /&gt;
[[Bild:PIDstruktur.gif]]&lt;br /&gt;
&lt;br /&gt;
==Vergleich der Reglertypen==&lt;br /&gt;
In der folgenden Abbildung ist der Vergleich von P-, I-, PI-, PD- und PID-Regler in einem Regelkreis mit PT2-Glied als Regelstrecke dargestellt. Es ist deutlich zu sehen, dass die Regler ohne I-Anteil (P und PD) eine bleibende Regelabweichung aufweisen. Erst die Regler mit I-Anteil können auf den Endwert von 1 ausregeln. Beim reinen I-Regler geht das so langsam, dass es gar nicht mehr auf dem Diagramm zu sehen ist. Der Hauptzweck eines I-Anteils ist also die Vermeidung bleibender Regelabweichungen. Daher ist ein&lt;br /&gt;
I-Anteil normalerweise nicht nötig, wenn die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
Ausnahme: Es wird ein doppelter I-Anteil zur Vermeidung von Schleppfehlern benötigt.&lt;br /&gt;
&lt;br /&gt;
Die schnellsten Regler sind die mit einem D-Anteil (PD und PID). Der D-Anteil kommt deshalb hauptsächlich zum Einsatz, wenn schnelle Dynamik gefragt ist oder die Strecke selbst schon instabil ist. Voraussetzung für die Schnelligkeit ist allerdings, dass keine Begrenzung im Stellglied oder Aktuator auftritt. In der Praxis ist eine Begrenzung meistens nicht zu vermeiden, deshalb gilt die Sprungantwort in der Praxis nur für kleine Sprünge.&lt;br /&gt;
&lt;br /&gt;
Die Regler ohne D-Anteil, aber mit P-Anteil (P und PI) sind mittelschnell. Für einfache Regelaufgaben reicht auch oft schon ein reiner P-Regler aus, wenn die bleibende Regelabweichung vernachlässigt werden kann oder weil die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
&lt;br /&gt;
[[File:reglervergleich.gif]]&lt;br /&gt;
&lt;br /&gt;
Aus diesem Vergleich wird klar, warum der PID-Regler so beliebt ist, er vereinigt die Vorzüge aller anderen Regler.&lt;br /&gt;
&lt;br /&gt;
==Digitaler Regler==&lt;br /&gt;
Durch die Einführung leistungsfähiger und preiswerter Mikroprozessoren hat sich der digitale Regler mehr und mehr durchgesetzt. Im Gegensatz zum analogen Regler werden die Signale nicht mehr analog mit Operationsverstärker verarbeitet, sondern mit einem Mikroprozessor errechnet. Bevor das Signal vom Mikroprozessor bearbeitet werden kann, muss zunächst das Eingangssignal (Istwert) mit einem Analog-Digital-Umsetzer (ADU) digitalisiert werden, d.h. in einen Zahlenwert umgewandelt werden. Das vom digitalen Regler errechnete Ausgangssignal (Stellgröße) wird wiederum zur Ansteuerung des Stellglieds mit einem Digital-Analog-Umsetzer (DAU) in ein analoges Signal gewandelt. Funktionell unterscheiden sich analoger und digitaler Regler jedoch nicht wesentlich, es müssen nur die Schnittstellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
[[File:digreg.gif|right|framed|Digitaler Regler (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Da die Wandlungen und das Regelprogramm eine gewisse Zeit beanspruchen, vergeht pro Durchlauf die sogenannte Takt- oder Abtastzeit. Diese Zeit wirkt sich im Regelkreis wie ein Totzeitglied mit der halben Abtastzeit als Totzeit aus. Das verursacht eine zusätzliche Phasenverschiebung, was sich ungünstig auf die Stabilität des Regelkreises auswirken kann. Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der digitale Regler kann dann wie ein analoger dimensioniert werden. Ist die Abtastzeit größer, kann sie nicht mehr vernachlässigt werden, dann muss sie auch beim Reglerentwurf berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
'''Vorteile digitaler Regler:'''&lt;br /&gt;
* Die Verarbeitung erfolgt driftfrei.&lt;br /&gt;
* Es lassen sich nichtlineare Kennlinien, intelligentes Verhalten oder adaptive Regelung leichter realisieren.&lt;br /&gt;
* Der Regler kann bei Bedarf per Software neu konfiguriert und parametriert werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Digitale Realisierung am Beispiel des PID-Algorithmus'''&lt;br /&gt;
&lt;br /&gt;
Ausgehend von der Differentialgleichung für kontinuierliche Systeme wird die Differenzengleichung für zeitdiskrete Systeme erstellt. Daraus folgt dann der Stellungsalgorithmus in allgemeiner Form.&lt;br /&gt;
&lt;br /&gt;
Ta = Abtastzeit; k = Nummer der Abtastung&lt;br /&gt;
&lt;br /&gt;
Kp = Proportionalbeiwert; Ki = Integrierbeiwert; Kd = Differenzierbeiwert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- http://www.roboternetz.de/wiki/uploads/Main/pidformel.gif --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differentialgleichung für den kontinuierlichen PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y(t) \;=\;  Kp \!\cdot\! e(t) &lt;br /&gt;
          + Ki \int_0^t e(\tau) \, d\tau &lt;br /&gt;
          + Kd \, \frac{de(t)}{dt}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differenzengleichung für den zeitdiskreten PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  Kp \!\cdot\! e_k&lt;br /&gt;
          + Ki \!\cdot\! Ta \sum_{i=0}^k e_i&lt;br /&gt;
          + \frac{Kd}{Ta}\, ( e_k - e_{k-1} )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''PID Stellungs-Algorithmus:&lt;br /&gt;
:''' &amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  y_{k-1} &lt;br /&gt;
          + q_0 \!\cdot\! e_k&lt;br /&gt;
          + q_1 \!\cdot\! e_{k-1}&lt;br /&gt;
          + q_2 \!\cdot\! e_{k-2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den Parametern:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
q_0 \,=\, Kp + Ki \!\cdot\! Ta + \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_1 \,=\, -Kp  - 2 \, \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_2 \,=\, \frac{Kd}{Ta}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Umsetzung in Code nach der Differenzengleichung:'''&lt;br /&gt;
&lt;br /&gt;
Im Code wurden einige Variablen umbenannt, da die Indexschreibweise nicht möglich ist.&lt;br /&gt;
&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, esum ist die Summenbildung&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird man die Ausdrücke Ki*Ta und Kd/Ta vorab berechnen und mit Ersatzvariablen in die Reglergleichung einsetzen. Der Verständlichkeit halber wurde es hier im Code belassen. Des weiteren kann eine Begrenzung von esum notwendig werden, um einen Variablenüberlauf oder Windup-Effekt zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Der nachfolgende Code wird im Rhythmus der Abtastzeit Ta immer wieder aufgerufen.&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 esum = esum + e;				//Integration I-Anteil&lt;br /&gt;
 y = Kp*e + Ki*Ta*esum + Kd/Ta*(e – ealt);	//Reglergleichung&lt;br /&gt;
 ealt = e;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''Alternative Umsetzung in Code nach dem Stellungsalgorithmus:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, yalt entspricht y&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, ealt2 entspricht e&amp;lt;sub&amp;gt;k-2&amp;lt;/sub&amp;gt;&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 y = yalt + q0*e + q1*ealt + q2*ealt2;		//Reglergleichung&lt;br /&gt;
 ealt2 = ealt;&lt;br /&gt;
 ealt = e;&lt;br /&gt;
 yalt = y;&lt;br /&gt;
&lt;br /&gt;
==Dimensionierung des Reglers==&lt;br /&gt;
Die Auswahl des Reglertyps ist heutzutage bei den digitalen Reglern nicht mehr so kritisch, da der Mehraufwand in Software für einen PID-Regler gegenüber einfacheren Typen kaum zu Buche schlägt. Im Prinzip ist man deshalb mit einem PID-Regler fast immer auf der richtigen Seite, mit einer Ausnahme, bei einer Strecke mit reiner Totzeit. Die folgende Tabelle gibt eine Hilfestellung zur Auswahl des Reglers. &lt;br /&gt;
&lt;br /&gt;
:{| {{Blauetabelle}}&lt;br /&gt;
 |+ '''Geeignete Reglertypen für die unterschiedlichen Regelstrecken'''&lt;br /&gt;
 !rowspan=2 | Strecke&lt;br /&gt;
 !colspan=4 | Regler&lt;br /&gt;
 |-&lt;br /&gt;
 ! P || PD || PI || PID&lt;br /&gt;
 |-&lt;br /&gt;
 |reine Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |-&lt;br /&gt;
 |1.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |2.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |höhere Ordnung&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |I-Glied und Verzögerung&lt;br /&gt;
 |geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Nachdem man einen geeigneten Reglertyp ausgewählt hat, stellt sich noch die Frage, wie man die Reglerparameter Kp, Ki, und Kd optimiert. Im Laufe der Zeit wurden viele Methoden zur Dimensionierung der Reglerparameter entwickelt, aber es können hier nicht alle aufgelistet werden. Diese Aufzählung beschränkt sich auf die einfacheren und gängigen Methoden der Parametrierung.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung durch Probieren (Empirisches Einstellen)===&lt;br /&gt;
&lt;br /&gt;
====Methode 1====&lt;br /&gt;
&lt;br /&gt;
Diese Methode ist geeignet um einfache Systeme zu dimensionieren, insbesondere wenn man bereits Erfahrung mit ähnlichen Regelkreisen hat. Man fängt mit einer unkritischen Einstellung (Kp klein, Ki = 0, Kd = 0) an und erhöht langsam die Verstärkung Kp, bis die Dämpfung schlecht wird. Falls eine Schwingneigung auftritt, muss die Verstärkung wieder etwas zurück genommen werden. Dann nimmt man allmählich den Integralanteil hinzu, erhöht ihn in Schritten und probiert solange herum, bis das Ergebnis einigermaßen passt. Bei Bedarf kann noch ein D-Anteil (PID-Struktur) probiert werden. Wenn dabei die Regelung stabiler wird, kann noch mal Kp und Ki erhöht werden, bis man endgültig zufrieden ist. &lt;br /&gt;
&lt;br /&gt;
====Methode 2====&lt;br /&gt;
Alle Anteile erstmal auf 0. Dann erhöht man Kp so lange bis das System deutlich schwingt. Danach wird der Kd so lange erhöht bis das System nicht mehr schwingt. Anschliessend kann noch ein kleiner Ki Anteil hinzugegeben werden.&lt;br /&gt;
&lt;br /&gt;
Es dürfte klar sein, dass so eine Optimierung im Blindflug nicht immer das Optimum ergibt, aber es ist eine gängige praktische Methode zur Ermittlung der Reglerparameter. Besser sieht es aus, wenn in einer Simulation empirisch optimiert wird. Zusätzliche Informationen über die Stabilität erlauben hierbei eine gezieltere Optimierung. Zudem ist das Probieren im Simulator gefahrlos möglich, was in der Realität nicht immer der Fall ist. Geeignete Programme zur Simulation sind [[Regelungstechnik#Hilfsprogramme_zur_Analyse_und_Optimierung| hier]] vorgestellt. Allerdings muss für eine Simulation die Regelstrecke bekannt sein. Ist das nicht der Fall, so bleibt nur das einfache Probieren oder das Einstellen nach der Schwingungsmethode wie im folgenden beschrieben.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung nach Einstellregeln===&lt;br /&gt;
&lt;br /&gt;
Die Dimensionierung nach Rezept ist eine praktische Methode ohne viel Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die bekanntesten Einstellregeln sind von Ziegler/Nichols und von Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer Einstelltabellen, auf die hier aber verzichtet wird, das würde den Rahmen dieses Artikels sprengen. An der Vielzahl kann man schon ersehen, dass es kein universell gültiges Rezept gibt und mit diesen Tabellen nicht unbedingt das Optimum erreicht wird, eine Nachoptimierung kann nötig sein.&lt;br /&gt;
&lt;br /&gt;
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.&lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Schwingungsmethode:'''&lt;br /&gt;
&lt;br /&gt;
Bei der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter so verstellt, dass die Stabilitätsgrenze erreicht wird und der Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische Schwingungen ausführt. Aus der so gefundenen Einstellung können die Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden anrichtet und die überhaupt instabil gemacht werden können. Die Vorgehensweise ist folgende:&lt;br /&gt;
# Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0&lt;br /&gt;
# Die Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen ausführt.&lt;br /&gt;
# Der dabei eingestellte Wert Kp wird als Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; bezeichnet. &lt;br /&gt;
# Die Periodendauer der sich einstellenden Dauerschwingung T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; wird gemessen.&lt;br /&gt;
# Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 ! Regler || Kp || Tn || Tv&lt;br /&gt;
 |-&lt;br /&gt;
 ! P&lt;br /&gt;
 | 0.5·Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; || ||&lt;br /&gt;
 |-&lt;br /&gt;
 ! PI&lt;br /&gt;
 | 0.45·Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; || 0.85·T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; ||&lt;br /&gt;
 |-&lt;br /&gt;
 ! PID&lt;br /&gt;
 | 0.6·Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; || 0.5·T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; || 0.12·T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 ! Ki = Kp/Tn&lt;br /&gt;
 |-&lt;br /&gt;
 ! Kd = Kp·Tv&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken angewendet werden kann, die auch zum Schwingen gebracht werden können. &lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Sprungantwort:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Diese Methode der Parameterbestimmung beruht auf der Aufnahme der Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die nicht zum Schwingen gebracht werden können. Der Regelkreis muss allerdings geöffnet werden.&lt;br /&gt;
Vorgehensweise: Es wird die Sprungantwort aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu und die Ausgleichszeit Tg ermittelt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tu_Tg.gif]]&lt;br /&gt;
&lt;br /&gt;
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |+ '''Einstellregeln nach&amp;lt;br/&amp;gt;Ziegler/Nichols'''&lt;br /&gt;
 ! Regler || Kp || Tn || Tv&lt;br /&gt;
 |-&lt;br /&gt;
 ! P&lt;br /&gt;
 | 1/Ks·Tg/Tu || || &lt;br /&gt;
 |-&lt;br /&gt;
 ! PI&lt;br /&gt;
 | 0.9/Ks·Tg/Tu || 3.3·Tu ||&lt;br /&gt;
 |-&lt;br /&gt;
 ! PID&lt;br /&gt;
 | 1.2/Ks·Tg/Tu || 2·Tu || 0.5·Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |+ '''Einstellregeln nach&amp;lt;br/&amp;gt;Chien/Hrones/Reswick'''&lt;br /&gt;
 ! Regler || Kp || Tn || Tv&lt;br /&gt;
 |-&lt;br /&gt;
 ! P&lt;br /&gt;
 | 0.3/Ks·Tg/Tu || ||&lt;br /&gt;
 |-&lt;br /&gt;
 ! PI&lt;br /&gt;
 | 0.35/Ks·Tg/Tu || 1.2·Tg ||&lt;br /&gt;
 |-&lt;br /&gt;
 ! PID&lt;br /&gt;
 | 0.6/Ks·Tg/Tu || Tg || 0.5·Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 ! Ki = Kp/Tn&lt;br /&gt;
 |-&lt;br /&gt;
 ! Kd = Kp·Tv&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| cellpadding=4 width=420&lt;br /&gt;
 |Die Parameter Tn und Tv sind aus der analogen Regelungstechnik und sind dort sehr geläufig. Die Umrechnung in die Parameter Ki und Kd erfolgt mit nebenstehenden Formeln, siehe auch [[Regelungstechnik#PID-Regler| PID-Regler]].&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit dem Bodediagramm===&lt;br /&gt;
&lt;br /&gt;
Ein Bode-Diagramm ist die grafische Darstellung des Frequenzganges. Es werden der Betrag der Übertragungsfunktion (Amplitudengang) und der Verlauf des Phasenwinkels (Phasengang) als Funktion der Frequenz aufgetragen. Die Frequenzachse und die Amplitudenachse werden logarithmisch dargestellt. Die logarithmische Darstellung hat den Vorteil, dass eine Multiplikation auf eine einfache Addition zurückgeführt wird. Somit wird eine Hintereinanderschaltung von Systemen im Blockschaltbild zu einer einfachen Addition im Bodediagramm.&lt;br /&gt;
&lt;br /&gt;
Das Zeitverhalten des rückgekoppelten Regelkreises hängt entscheidend vom Verlauf&lt;br /&gt;
des Frequenzganges der offenen Regelschleife in der Umgebung des Durchtretens durch&lt;br /&gt;
die 0dB-Achse ab. In der Regelungstechnik wird daher der offene Regelkreis im Bode-Diagramm aufgetragen. Das erlaubt einen schnellen Überblick über Stabilität und möglichen Reserven zur Optimierung. Ein Kriterium für die Stabilität der Schleife ist der Phasenrand und der Amplitudenrand. Der Phasenrand ist der Abstand (Phasenreserve) zur -180°-Linie bei der Durchtrittsfrequenz. Die Durchtrittsfrequenz ist diejenige Frequenz, bei der der Amplitudengang durch die 0dB-Linie geht. Siehe auch folgendes Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Phasenrand.gif]]&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |'''Regel:''' Eine geschlossene Regelschleife arbeitet genau dann stabil, wenn der Phasenrand positiv ist.&lt;br /&gt;
 |}&lt;br /&gt;
Wird diese Bedingung verletzt, so wird in diesem Frequenzbereich die im Rückführzweig der Regelung eingebrachte Gegenkopplung zu einer Mitkopplung und das System kann schwingen.&lt;br /&gt;
&lt;br /&gt;
'''Beim Reglerentwurf sind folgende Punkte zu beachten:'''&lt;br /&gt;
* Der Phasenrand muss positiv sein. Der geschlossene Regelkreis kann sonst instabil sein. &lt;br /&gt;
* Je größer der Phasenrand ist, desto größer ist die Stabilitätsreserve des Regelkreises und desto höher ist die Dämpfung des Regelkreises. Üblich sind Werte von 40°...70° für gutes Führungsverhalten und 20°...50° für gutes Störverhalten.&lt;br /&gt;
* Die Durchtrittsfrequenz ist ein Maß für die Schnelligkeit des Regelkreises, je höher, desto schneller ist die Reaktion auf Änderungen der Führungsgröße oder Störungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel zur Dimensionierung mit dem Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bode1.gif]]&lt;br /&gt;
&lt;br /&gt;
Die Strecke ist rot dargestellt und besteht in dem Beispiel aus einem nicht schwingfähigem PT2-Glied. Man sucht sich den Punkt, wo die Strecke für sich alleine noch ausreichend Phasenreserve hat, z.B. 70°. In dem Beispiel also die Frequenz, bei der die Strecke –110° Phasendrehung aufweist. Das ist etwa bei 15Hz. Da hat die Strecke ungefähr eine Dämpfung von 25dB. Wenn man nun diese Dämpfung durch eine Verstärkung von 25dB kompensiert, dann wird dieser Punkt zur Durchtrittsfrequenz. D.h. man wählt den P-Anteil des Reglers Kp=18, denn 25dB entspricht ungefähr dem Faktor 18. Um die Regelabweichung zu minimieren, wird noch ein I-Anteil hinzugefügt.&lt;br /&gt;
&lt;br /&gt;
Üblicherweise wählt man für die Grenzfrequenz des PI-Reglers die Grenzfrequenz des dominierenden Streckenteils, in dem Beispiel ca. 1.4Hz. Damit ergibt sich ein I-Anteil von 170. Im Bode-Diagramm ist der PI-Regler als schwarze Kurve eingezeichnet. Die Addition der Strecke und des Reglers im Bode-Diagramm führt dann zum Frequenzgang des offenen Regelkreises (blaue Kurve). Die resultierende Durchtrittsfrequenz ist wie gewählt bei etwa 15Hz. Der Phasenrand hat sich durch den I-Anteil im Regler auf ca. 60° reduziert, ist aber noch ausreichend. Das Einschwingen des geschlossenen Regelkreises für diese Dimensionierung sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort3.gif]]&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf könnte noch ein D-Anteil (PID-Regler) hinzugenommen werden, das würde die Phase anheben und man könnte dadurch die Durchtrittsfrequenz weiter nach oben schieben. In der Praxis wird dies allerdings wegen der wahrscheinlichen Begrenzung des Stellglieds kein schnelleres Einschwingen mehr bringen. &lt;br /&gt;
&lt;br /&gt;
Begrenzungen oder Nichtlinearitäten werden bei der Dimensionierung mit dem Bode-Diagramm nicht berücksichtigt. Das ist ein Nachteil dieser Methode. Eventuell muss deshalb noch einmal im Zeitbereich nachoptimiert werden.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit der Ortskurve===&lt;br /&gt;
Eine Alternative zur Dimensionierung mit dem Bodediagramm stellt die Methode über die Ortskurve des offenen Regelkreises dar.  Bei diesem Verfahren ist schnell auf einem Blick ersichtlich ob der Regelkreis stabil ist.&lt;br /&gt;
&lt;br /&gt;
Liegt der Punkt –1 auf der Realteilachse links von der Ortskurve in Richtung steigendem &amp;amp;omega; (omega) so ist der Regelkreis stabil.&lt;br /&gt;
Der Abstand zu der kritischen Kreisfrequenz ω&amp;lt;sub&amp;gt;Krit&amp;lt;/sub&amp;gt; von der Imaginärteilachse ist die Verstärkung Vr. Mit diesem Wert lässt sich der Amplitudenrand nach folgender Formelermitteln: Ar = 20 lg (1/Vr) in dB&lt;br /&gt;
&lt;br /&gt;
Die Durchtrittskreisfrequenz ω&amp;lt;sub&amp;gt;D&amp;lt;/sub&amp;gt; liegt an dem Punkt, wo der Betrag aus Realteil und Imaginärteil 1 ergibt. Wenn man weiß, wo die Durchtrittskreisfrequenz ist, dann kann man den Phasenrand bestimmen.&lt;br /&gt;
Dies ist der Winkel zwischen der –180°-Linie zu ω&amp;lt;sub&amp;gt;D&amp;lt;/sub&amp;gt;.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ortskurve.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Hilfsprogramme zur Analyse und Optimierung==&lt;br /&gt;
Die Analyse und Optimierung von Regelkreisen wird wesentlich erleichtert durch die Zuhilfenahme von Programmen. Es erspart einem eine komplizierte Rechnerei von Hand oder umfangreiche Testläufe. Stellvertretend für all die verfügbaren Programme werden hier zwei Freeware-Programme vorgestellt, die dafür gut geeignet sind. Die Beschreibung hier ersetzt aber keine Tutorials, es wird nur die Anwendung für die Regelungstechnik beschrieben. &lt;br /&gt;
&lt;br /&gt;
===Scilab/Scicos===&lt;br /&gt;
Scilab ist ein wissenschaftlich-technisches Softwarepaket für numerische Berechnungen. Scicos ist eine Erweiterung dazu, die eine blockorientierte und modellbasierte Simulation und Analyse von dynamischen Systemen bietet. Dieses Softwarepaket kann von der [http://www.scilab.org/ Scilab Homepage] herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
====Scilab====&lt;br /&gt;
Mit Scilab ist es sehr einfach ein Bode-Diagramm zu zeichnen, es bedarf nur 3 Zeilen Code.&lt;br /&gt;
 s=poly(0,'s');&lt;br /&gt;
 G=syslin('c',0.72/(0.11*s+1));&lt;br /&gt;
 bode(G)&lt;br /&gt;
Die 1.Zeile '''s=poly(0,'s');''' legt die Variable s als Polynomvariable fest. Dies braucht in einer Sitzung nur einmal gemacht zu werden. Die 2.Zeile '''G=syslin('c',0.72/(0.11*s+1));''' definiert ein lineares System mit der Übertragungsfunktion 0.72/(0.11s+1). Die 3.Zeile '''bode(G)''' zeichnet das Bode-Diagramm des zuvor mit syslin definierten Systems G. Zu beachten ist, dass Scilab auf der x-Achse im Bode-Diagramm die Frequenz in Hertz und nicht wie üblich die Kreisfrequenz darstellt. Anstelle des Bode-Diagramms kann auch die Sprungantwort gezeichnet werden. Dies geschieht mit folgenden Befehlen:&lt;br /&gt;
 xbasc();&lt;br /&gt;
 t=[0:0.001:2];&lt;br /&gt;
 y=csim('step',t,G);&lt;br /&gt;
 plot2d(t,y)&lt;br /&gt;
'''xbasc()''' löscht den letzten Plot mit dem Bode-Diagramm und mit '''t=[0:0.001:2]''' wird ein Vektor t mit den angegebenen Zeiten im Intervall von 1ms definiert. Die Zeile '''y=csim('step',t,G)''' berechnet die Sprungantwort des zuvor mit syslin definierten Systems G und speichert sie in y ab. Das Ergebnis wird dann mit '''plot2d(t,y)''' dargestellt. Bei Bedarf können noch Gitternetzlinien mit dem Befehl '''xgrid()''' hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Ergänzend hier noch ein Scilab-Skript, welches recht hilfreich bei der Dimensionierung mit dem Bode-Diagramm ist. Den nachfolgenden Code einfach in das SciPad-Fenster (Editor von Scilab) kopieren und starten. Es werden 2 Grafikfenster angezeigt, eines mit dem Bode-Diagramm und ein zweites mit der Sprungantwort. Man kann im Skript die Streckencharakteristik anpassen und verschiedene Reglerparameter ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ks=0.72;                            // Verstärkung der Strecke&lt;br /&gt;
T1=0.11;                            // Zeitkonstante 1&lt;br /&gt;
T2=0.005;                           // Zeitkonstante 2&lt;br /&gt;
Kp=18;                              // Proportionalbeiwert&lt;br /&gt;
Ki=170;                             // Integralbeiwert&lt;br /&gt;
Kd=0;                               // Differenzialbeiwert&lt;br /&gt;
 &lt;br /&gt;
s=poly(0,'s');                      // definiert s als Polynomvariable&lt;br /&gt;
P=(T1*s+1)*(T2*s+1);                // Streckencharakteristik&lt;br /&gt;
Gs=syslin('c',Ks,P)                 // Übertragungsfunktion der Strecke&lt;br /&gt;
&lt;br /&gt;
RZ=poly([Ki Kp Kd],'s','coeff')     // Zählerpolynom des Reglers&lt;br /&gt;
RN=poly([0 1],'s','coeff')          // Nennerpolynom des Reglers&lt;br /&gt;
Gr=syslin('c',RZ,RN)                // Übertragungsfunktion des Reglers&lt;br /&gt;
&lt;br /&gt;
G=Gr*Gs                             // Übertragungsfunktion gesamt&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,0);&lt;br /&gt;
xbasc(0);&lt;br /&gt;
bode([Gr;G;Gs],0.1,100,['Regler';'gesamt';'Strecke'])&lt;br /&gt;
&lt;br /&gt;
Gcl=G/(G+1)                         // geschlossene Regelschleife&lt;br /&gt;
t=0:0.001:0.2;&lt;br /&gt;
y=csim('step',t,Gcl);               // berechnet Sprungantwort&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,1);&lt;br /&gt;
xbasc(1);&lt;br /&gt;
plot2d(t,y,2);&lt;br /&gt;
xgrid();&lt;br /&gt;
xtitle(&amp;quot;Sprungantwort&amp;quot;,&amp;quot;sec&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Scicos====&lt;br /&gt;
Eine weitere Möglichkeit zur Simulation im Zeitbereich bietet Scicos. Die Modellierung geschieht mit einem grafischen Editor, in dem Blöcke mit vordefinierten oder selbstgemachten Funktionen miteinander verbunden werden. Ein einfaches Modell eines Regelkreises mit PID-Regler sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_anaReg.gif]]&lt;br /&gt;
&lt;br /&gt;
Der PID-Regler ist mit seinen 3 Zweigen (P, I und D) dargestellt. In den Verstärkerblöcken kann durch Ändern der Reglerparameter (KP, KI und KD) der Regler optimiert werden. Die Strecke ist in diesem Beispiel nur ein einzelner Block, in dem die Übertragungsfunktion eingegeben wird. Man kann die Strecke auch detaillierter mit einzelnen Funktionsblöcken darstellen. Ein Beispiel eines komplexen Blockschaltbilds für einen balancierenden Bot ist unter diesem [http://www.roboternetz.de/phpBB2/download.php?id=5082 Link] zu finden.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil der Simulation mit Scicos ist die Möglichkeit Nichtlinearitäten zu berücksichtigen und die Kombination von kontinuierlichen und diskreten Funktionen. Das heißt, man kann einen digitalen Regler mit seinen diskreten Schritten und eine analoge Strecke, als kontinuierliche Funktion eingegeben, zusammen simulieren. Scicos bietet sogar einen 'Scifunc'-Block, mit dem Rechenschritte des digitalen Reglers nachgebildet werden können. Damit wird sowohl das dynamische Verhalten, verursacht durch die Abtastzeit Ta, als auch die etwas unterschiedliche Dynamik durch die digitale Ausführung eines I- und D-Anteils richtig simuliert. Ein Beispiel für den Einsatz des Scifunc-Blocks ist in folgendem Blockschaltbild zu sehen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_digReg.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel: [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlregelung]] mit digitalem Regler&lt;br /&gt;
&lt;br /&gt;
Die globalen Variablen für die Reglerparameter und die Abtastzeit werden unter dem Menüpunkt „Edit - Context“ abgelegt.&lt;br /&gt;
 Kp=18;&lt;br /&gt;
 Ki=60;&lt;br /&gt;
 Ta=0.01;&lt;br /&gt;
In den Taktgeber für den digitalen Regler wird als Clock-Periode die Abtastzeit Ta eingetragen. In das Dialogfenster zum Scifunc-Block wird folgender Code zur Simulation des digitalen PI-Reglers eingetragen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z=z+Ki*Ta*u1&lt;br /&gt;
if z&amp;gt;5 then&lt;br /&gt;
z=5;&lt;br /&gt;
end&lt;br /&gt;
y1=Kp*u1+z&lt;br /&gt;
if y1&amp;gt;5 then&lt;br /&gt;
y1=5;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
z entspricht der Variable esum vom Beispiel des [[Regelungstechnik#Realisierung_mit_digitalem_Regler| digitalen Drehzahlreglers]]; u1 ist die Eingangsvariable und y1 die Ausgangsvariable des Scifunc-Blocks.&lt;br /&gt;
In den Block für die Strecke wird die Übertragungsfunktion eingetragen. Als Zähler die Verstärkung Ks, also 0.72. Im Nenner das Polynom (1+0.11*s) für die Charakteristik der Strecke. Mit ‚Simulate – Run’ wird die Simulation gestartet. Als Ergebnis sollte das Einschwingen der Stellgröße (schwarz) und der Regelgröße (grün), wie in folgender Abbildung erscheinen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort_DZR.png]]&lt;br /&gt;
&lt;br /&gt;
Man kann nun mit den Reglerparametern und verschiedenen Abtastzeiten spielen, um zu sehen wie sich die Änderungen auswirken. Zum Beispiel wird bei einer Verdopplung der Abtastzeit der Regelkreis bereits instabil.&lt;br /&gt;
&lt;br /&gt;
Diese Beispiele sind nur ein kurzer Auszug von den Möglichkeiten mit Scilab/Scicos für den Einsatz in der Regelungstechnik. Darüber hinaus ist es auch sehr gut geeignet bei anderen Optimierungsverfahren wie z.B. beim WOK-Verfahren (Wurzelortskurven) oder zur Analyse und Optimierung von modernen Reglern wie z.B. Zustandsregler und Kalmanfilter.&lt;br /&gt;
&lt;br /&gt;
===LTspice/SwitcherCad III===&lt;br /&gt;
Dieses Programm ist ein SPICE-Derivat von der Firma Linear Technology und ist unter den 2 Namen LTspice und SwitcherCad III bekannt. Der Einfachheit halber wird für die weitere Beschreibung hier nur der Name LTspice verwendet. Das Programm ist Freeware und kann unter diesem Link herunter geladen werden. http://ltspice.linear.com/software/LTspiceIV.exe&lt;br /&gt;
&lt;br /&gt;
LTspice ist ein Simulationsprogramm zur Analyse von elektronischen Schaltungen. Mit LTspice kann sowohl im Zeitbereich als auch im Frequenzbereich analysiert werden und bietet sich dadurch mit den entsprechenden Modellen auch für den Einsatz in der Regelungstechnik an. Wer sich bereits mit SPICE-Programmen auskennt, für den sollte es auch in der Regelungstechnik die 1.Wahl sein. &lt;br /&gt;
&lt;br /&gt;
Der Vorteil von LTspice ist die Möglichkeit einer sehr detaillierten Analyse, vorausgesetzt die Modelle sind auch so detailliert nachgebildet. Insbesondere für analoge Regler, wo die elektrische Schaltung direkt umgesetzt werden kann, empfiehlt sich der Einsatz von LTspice. Der Nachteil ist, LTspice ist nicht auf regeltechnische Belange ausgelegt worden und spezifische Symbole für die Regelungstechnik müssen selbst erstellt werden. Einige selbst erstellte Symbole für dynamische Grundelemente in LTspice sind hier abgebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTSpiceSymb.png]]&lt;br /&gt;
&lt;br /&gt;
Die 3 Symbole können [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=285 hier] heruntergeladen werden. Weitere Symbole können anhand dieser Beispiele sehr leicht selbst erstellt werden. Ein P-Glied kann durch eine spannungsgesteuerte Spannungsquelle (E-Source) oder Operationsverstärker mit einstellbarer Verstärkung dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
'''Analyse im Zeitbereich'''&lt;br /&gt;
&lt;br /&gt;
Das Beispiel des [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlreglers]] mit analogem Regler wird hier mit LTspice simuliert. Das Schaltbild des Regelkreises zeigt nachfolgende Abbildung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_TRAN.png]]&lt;br /&gt;
&lt;br /&gt;
Der Vergleicher (U1) und der analoge PI-Regler (U2) sind so dargestellt, wie es auch in Wirklichkeit ausgeführt werden kann. Da der PI-Regler in der Schaltung bereits invertiert, wurden die Eingänge am Vergleicher vertauscht, damit die Polarität wieder stimmt. Der Rest des Regelkreises wurde stark vereinfacht, kann aber nach Bedarf auch ausführlicher dargestellt werden. Das PT1-Glied U3 simuliert die Strecke des Regelkreises und der Verstärker U4 dient nur zur Umrechnung auf die Drehzahl. Zur Simulation im Zeitbereich wird auf den Führungswert w mit der Spannungsquelle V1 ein Sprung gegeben. In der Reglerschaltung wurde bewusst ein Operationsverstärker mit Versorgungsspannung gewählt, damit auch der Einfluss einer Begrenzung mit simuliert wird. Die Zeitbereichsanalyse wird durch den LTspicebefehl .TRAN erreicht. Die Sprungantwort (Tachospannung) bei diesem Regelkreis sieht dann folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tacho2.png]]&lt;br /&gt;
&lt;br /&gt;
Durch Ändern der Bauelemente R5, R6 und C1 kann man den Regler optimieren. Eine Umrechnung auf die Reglerparameter Kp und Ki ist mit folgenden Formeln möglich, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1)&lt;br /&gt;
&lt;br /&gt;
Mit einem Mausklick auf den entsprechenden Knoten in der Schaltung können noch weitere Signale, wie z.B. die Stellgröße y angezeigt werden. Durch Verändern der Versorgungsspannung V3, V4 kann man sich auch die Auswirkung der Begrenzung ansehen. &lt;br /&gt;
&lt;br /&gt;
'''Analyse im Frequenzbereich'''&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung des Bode-Diagramms der offenen Regelschleife in LTspice muss ein Trick angewendet werden, denn durch das Auftrennen der Regelschleife würde der Arbeitspunkt verloren gehen und dadurch die offene Schleife ohne Gegenkopplung an den Anschlag fahren.&lt;br /&gt;
&lt;br /&gt;
Mit einer zusätzlichen Spannungsquelle in der Schleife kann man dieses Problem umgehen. Die Schleife bleibt für den Erhalt des Arbeitspunktes weiterhin geschlossen und man kann trotzdem die Verstärkung der offenen Schleife durch das Verhältnis der Spannung vor und hinter der Spannungsquelle bestimmen. Das erweiterte Blockschaltbild sieht folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_AC.png]]&lt;br /&gt;
&lt;br /&gt;
V2 ist die zusätzliche Spannungsquelle für die AC-Analyse. Die Spannungsquelle V1 wird von Pulsform auf Gleichspannung umgestellt. Sie wird so gewählt, dass sich der gewünschte Arbeitspunkt einstellt. Durch den LTspicebefehl .AC wird die Analyse im Frequenzbereich veranlasst. Um das Bode-Diagramm des offenen Regelkreises darzustellen, wird als Kurve nicht ein einzelner Knoten ausgewählt, sondern das Verhältnis der Spannung vom Ende zum Anfang des Regelkreises, in unserem Beispiel also V(tacho)/V(x). Zur Anzeige kommt dann das Bode-Diagramm (grüne Kurve) der offenen Schleife, wie in der folgenden Abbildung zu sehen. Für den Amplitudengang (durchgezogene Linien) gilt die linke Skala in dB, für den Phasengang (gestrichelte Linien) die rechte Skala in Grad.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_Bode.png]]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist noch das Bode-Diagramm der Strecke (rote Kurve) zu sehen. Dies ist durch einfaches Hinzufügen einer weiteren Kurve mit dem Ausdruck V(tacho)/V(y) durchgeführt worden. &lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zur üblichen Darstellung des Bode-Diagramms eines offenen Regelkreises, beinhaltet das mit LTspice erstellte Bode-Diagramm auch die -180 Grad Phasendrehung der Gegenkopplung. Der Phasenrand ist deshalb nicht auf -180 Grad sondern auf 0 Grad zu beziehen. In unserem Beispiel ist der Phasenrand etwa 90 Grad, also ein sehr stabiler Regelkreis. Zu beachten ist, dass die Frequenzachse des Bode-Diagramms wie auch schon bei Scilab in der Einheit Hertz anstatt wie üblich in der Kreisfrequenzeinheit rad/s dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
==Modellierung eines Motors/Antriebs==&lt;br /&gt;
[[Bild:ESB_Motor.png|thumb|320px|Ersatzschaltbild DC-Motor]]&lt;br /&gt;
Der Motor ist ein oft verwendeter Aktuator in der Robotik. Deshalb wird hier am Beispiel des Gleichstrommotors mit Permanentmagnet (Nebenschlussmotor) die Modellbildung gezeigt. Zur Modellierung gibt es mehrere Möglichkeiten. Je nachdem wie detailliert die Simulation sein soll, kann man sich ein Modell, von sehr einfach bis sehr detailliert, auswählen. Zwei Zeitkonstanten bestimmen die Dynamik eines Gleichstrommotors. Eine davon ist die mechanische Zeitkonstante, die ist meistens die dominierende Zeitkonstante und wird durch das Trägheitsmoment J des Rotors verursacht. Die zweite Zeitkonstante ist die elektrische Zeitkonstante, sie wird durch die Induktivität L bestimmt. Bei einfachen Regelungen kann in den meisten Fällen die elektrische Zeitkonstante vernachlässigt werden, damit reduziert sich das Modell auf ein einzelnes PT1-Glied.&lt;br /&gt;
&lt;br /&gt;
'''Definition: Motor und Antrieb'''&lt;br /&gt;
&lt;br /&gt;
Als '''Motor''' wird hier der Motor alleine verstanden. Die Ausgangsgröße ist die Winkelgeschwindigkeit w (Drehzahl).&lt;br /&gt;
 &lt;br /&gt;
Als '''Antrieb''' wird hier der komplette Antrieb eines Fahrzeugs verstanden, also Motor inklusive Getriebe und Masse des Fahrzeugs. Für die Dynamik ist nicht nur das Trägheitsmoment des Motors sondern auch die Masse des Fahrzeugs verantwortlich. Die Ausgangsgröße der Einheit „Antrieb“ ist die Geschwindigkeit v.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellten Modelle gelten sowohl für einen Motor als auch für einen kompletten Antrieb, wenn man die Elastizität und das Spiel des Getriebes vernachlässigt.&lt;br /&gt;
&lt;br /&gt;
===Einfaches Modell mit PT1-Glied===&lt;br /&gt;
Die einfachste Art einen Motor oder Antrieb zu simulieren, ist mit einem PT1-Glied als Modell. Das Simulationsprogramm [[Regelungstechnik#Scicos|Scicos]] bietet dazu einen Block zur Eingabe der Übertragungsfunktion (num(s)=Zähler, den(s)=Nenner der Übertragungsfunktion).&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G(s)=\frac{K}{1+Ts}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |Beispiel:&lt;br /&gt;
 num(s) = K = 0.72&lt;br /&gt;
 den(s) = 1 + Ts = 1 + 0.11s&lt;br /&gt;
 |[[Bild:Scicos_TF.png]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Wird nicht nur das Ausgangssignal, also die Geschwindigkeit oder Drehzahl in der Simulation benötigt, sondern auch die Beschleunigung, dann kann nachfolgendes Modell verwendet werden. Dieses Modell ist der Differentialgleichung eines PT1-Glieds nachempfunden und liefert das gleiche Ergebnis wie vorheriges Modell, bietet aber noch den Zugriff auf das Beschleunigungssignal.&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Differentialgleichung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;v'=\frac{K}{T}U-\frac{1}{T}v&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |&lt;br /&gt;
 v = Geschwindigkeit&lt;br /&gt;
 v’= Beschleunigung (Ableitung von v)&lt;br /&gt;
 K = Übertragungsmaß&lt;br /&gt;
 T = Zeitkonstante&lt;br /&gt;
 U = Eingangsgröße (z.B. Spannung)&lt;br /&gt;
 |[[Bild:Antrieb_PT1.png|thumb|Einfaches Modell eines Antriebs]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Die beiden Parameter K und T müssen ausgemessen werden, wenn sie nicht bekannt sind. Die Zeitkonstante T kann in einem Anlaufversuch ermittelt werden. Dazu wird auf den Motor ein Spannungssprung gegeben und die Sprungantwort am Ausgang nachgemessen. Bei einem Antrieb erspart diese Methode die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente (Motor, Getriebe, Fahrzeug). Bei der Ermittlung des Übertragungsmaß K ist zu beachten, dass sich möglicherweise der Motor durch starke Reibung erst ab einer bestimmten Spannung dreht. Hier ist die Steigung der Kennlinie mit delta&amp;amp;nbsp;v&amp;amp;nbsp;/&amp;amp;nbsp;delta&amp;amp;nbsp;U auszuwerten, wie im folgenden Bild zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_stat.png]]&lt;br /&gt;
&lt;br /&gt;
Die einfachen Modelle gelten nur für den linearen Teil der Kennlinie. Soll auch die Nichtlinearität durch Reibung modelliert werden, dann sind detailliertere Modelle, wie im Folgenden beschrieben, zu verwenden. Die Auswirkung einer Haftreibung ist auch in dem Geschwindigkeitsdiagramm durch die Hysterese in der Kennlinie zu sehen. Beim Hochfahren der Ansteuerspannung bewegt sich das Fahrzeug erst ab ca. 1.25V, während beim Herunterfahren der Ansteuerspannung das Fahrzeug noch bis 0.75V rollt und erst unter 0.75V stehen bleibt.&lt;br /&gt;
&lt;br /&gt;
===Detailliertes Modell===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Motor_Model.png|thumb|350px|Detailliertes Motormodell]]&lt;br /&gt;
Ein detailliertes Motormodell ist rechts in dem Bild zu sehen. Es hat auf der linken Seite den elektrischen Teil mit den Parametern R (Widerstand) und L (Induktivität) und auf der rechten Seite den mechanischen Teil mit den Blöcken Trägheitsmoment und Reibung. Der elektrische Teil liefert das Stromsignal i, welches mit der Motorkonstante Km in das Drehmoment M umgerechnet wird. Mit dem folgenden Summierglied kann über einen zusätzlichen Eingang auch ein extern angreifendes Lastmoment mit simuliert werden. Am Ausgang des mechanischen Teils steht die Winkelgeschwindigkeit w in der Einheit [rad/s] bzw. über den Umrechnungsfaktor 9.55 die Drehzahl in [Upm] zur Verfügung. Die Reibung wird in einem nichtlinearen Block mittels Lookup-Table simuliert. In der einschlägigen Literatur wird die Reibung meistens mit einem Dämpfungsfaktor (linear) simuliert, was einer viskosen Reibung entspricht. Das passt aber nicht so gut für Kleinmotoren, da überwiegt vor allem die trockene Reibung. Die trockene Reibung hat ein konstantes Bremsmoment wenn sich der Motor dreht (unabhängig von Drehzahl, Vorzeichen abhängig von Drehrichtung). So eine Funktion kann sehr einfach mit einer Lookup-Table realisiert werden. Die Lookup-Table kann auch dazu verwendet werden, Mischformen von trockener, viskoser und turbulenter Reibung und sogar noch Haftreibung in einem Block zu simulieren, wenn man will.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Herstellern, wie z.B. Faulhaber und Maxon, kann man die für das Modell nötigen Parameter im Datenblatt finden. Das Bremsmoment der Reibung berechnet sich aus dem Leerlaufstrom wie folgt: Bremsmoment&amp;amp;nbsp;=&amp;amp;nbsp;Motorkonstante&amp;amp;nbsp;*&amp;amp;nbsp;Leerlaufstrom &lt;br /&gt;
&lt;br /&gt;
Falls die Daten nicht verfügbar sind, muss man sie selbst ausmessen. Eine Hilfestellung zur Bestimmung der Motorkonstante und des Trägheitsmoments gibt es hier:&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=96750&amp;amp;highlight=#96750&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/viewtopic.php?t=12793&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_Modell.png|thumb|350px|Modell eines Antriebs]]&lt;br /&gt;
&lt;br /&gt;
Das detaillierte Motormodell kann auch für einen Antrieb verwendet werden, wenn man eine starre Kopplung zwischen Motor und Antriebsrad voraussetzt, also Elastizität und Spiel des Getriebes vernachlässigt. Anstelle der rotatorischen Kenngrößen (Drehmoment M, Trägheitsmoment J, Winkelgeschwindigkeit w) werden die translatorischen Kenngrößen (Kraft F, Masse m, Geschwindigkeit v) eingesetzt. Das Drehmoment wird mittels Getriebeübersetzung ü und Radius r des Antriebsrades in die entsprechende Vortriebskraft umgerechnet. Daraus ergibt sich die Kraftkonstante Kf, die für das Antriebsmodell verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Die Umrechnung ist: Kf = Km * ü/r&lt;br /&gt;
&lt;br /&gt;
Bei der Trägheitsmasse m muss neben der Masse des Fahrzeugs auch das Trägheitsmoment des Motors mit berücksichtigt werden. Die Umrechnung von Trägheitsmoment in eine äquivalente Masse = J * (ü/r)²&lt;br /&gt;
&lt;br /&gt;
Der Reibungsblock in diesem Modellbeispiel enthält eine Mischform aus Haftreibung, trockener und viskoser Reibung, wie sie typisch für einen Kleinbot mit 2 Antriebsrädern und einem Gleitpin ist.&lt;br /&gt;
&lt;br /&gt;
==Beispiel: Drehzahlregelung==&lt;br /&gt;
Es wird ein Gleichstrommotor in der Drehzahl geregelt. Als Sensor ist ein Tachogenerator vorhanden, der direkt auf der Motorwelle sitzt. Das System ist in einem kleinen Modellfahrzeug eingebaut und wird zur Geschwindigkeitsregelung eingesetzt, da die Drehzahl proportional zur Geschwindigkeit ist.&lt;br /&gt;
&lt;br /&gt;
Das Funktionsschaltbild sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl1.gif&lt;br /&gt;
&lt;br /&gt;
Als Störgröße können unterschiedliche Reibwerte oder Steigung und Gefälle rückwirkend über das Getriebe die Drehzahl beeinflussen. Das Getriebe und die Last sind zwar außerhalb der Regelschleife, beeinflussen aber durch die feste Kopplung des Getriebes die Dynamik des Regelkreises. Durch die starre Kopplung kann das Trägheitsmoment des Motors und die Masse des Fahrzeugs zusammengefasst werden. Das Gleiche gilt auch für die Reibwerte. Damit vereinfacht sich die Modellierung und das Blockschaltbild reduziert sich auf folgende Schaltung:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl2.gif&lt;br /&gt;
&lt;br /&gt;
Zur Ermittlung des dynamischen Verhaltens der Regelstrecke wird die Sprungantwort gemessen. Dazu wird auf den Eingang der Regelstrecke (Stellglied) ein Spannungssprung gegeben und die Antwort am Ausgang des Tachogenerators nachgemessen. Diese Methode erspart die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente der Regelstrecke (Motor, Getriebe, Fahrzeug). Die Messung ergab folgende Sprungantwort der Regelstrecke:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/tacho.gif&lt;br /&gt;
&lt;br /&gt;
Wie zu erwarten, ist die Sprungantwort annähernd ein Verzögerungsglied 1.Ordnung. Die abgelesene Zeitkonstante ist 0.11s. Die Verstärkung der Regelstrecke ist Ks = 0.72. Das Übertragungsmaß des Tachogenerators ist 1V pro 2480Upm. Damit kann auf die Drehzahl rückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da die Regelstrecke nur aus einem PT1-Glied besteht, könnte eine analoge Regelung fast beliebig schnell gemacht werden. Wegen der Begrenzung bringt aber das Ausreizen der Optimierung für das Führungsverhalten nicht viel, nur für das Störverhalten wäre eine schnellere Regelung sinnvoll. Um aber einen Vergleich zwischen analogem und digitalem Regler anstellen zu können wird eine Parametrierung gewählt, die auch für den digitalen Regler mit seiner Totzeit noch stabil ist. Es wird deshalb auch auf einen D-Anteil im Regler verzichtet und nur ein PI-Regler realisiert. Das vereinfachte Blockschaltbild mit den dynamischen Elementen sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl3.gif&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung wurde ein analoger als auch ein digitaler Regler realisiert. Die Parametrierung des analogen Reglers wurde mit dem Programm [[Regelungstechnik#LTspice.2FSwitcherCad_III| LTspice]] durchgeführt. Es bot sich an, da die analoge Reglerschaltung exakt simuliert werden konnte. Für die Optimierung des digitalen Reglers wurde dann [[Regelungstechnik#Scicos| Scicos]] verwendet. &lt;br /&gt;
&lt;br /&gt;
===Realisierung mit analogem Regler===&lt;br /&gt;
Die elektrische Schaltung für einen analogen PI-Regler ist in der nächsten Abbildung zu sehen. Der erste Operationsverstärker vergleicht den Sollwert w mit dem Istwert x. Der zweite Operationsverstärker bildet den PI-Regler. Die Werte R5, R6 und C1 sind für die Charakteristik des PI-Reglers zuständig. Mit R6 kann der P-Anteil und mit C1 der I-Anteil eingestellt werden. Die Optimierung der Werte wurde empirisch in einer Simulation mit LTspice durchgeführt. Da die Schaltung des PI-Reglers invertiert, wurden zum Ausgleich am Vergleicher die Eingänge an U1 vertauscht, so dass sich über die gesamte Schaltung wieder die richtige Polarität ergibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Analogregler.png]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen auf Kp und Ki können diese Formeln verwendet werden, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5 = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1) = 147&lt;br /&gt;
&lt;br /&gt;
===Realisierung mit digitalem Regler===&lt;br /&gt;
Im digitalen Regelkreis wird der Istwert '''x''' vom Tachogenerator mit einem A/D-Wandler digitalisiert. Der Sollwert '''w''' wird dem µC als digitaler Wert übergeben. Die Stellgröße '''y''' entspricht dem PWM-Wert für den Motortreiber. Um zum analogen Regler vergleichbar zu sein, wurde sowohl für den A/D-Wandler als auch für den PWM-Steller eine 8-Bit-Breite vorgesehen. Damit ist die Verstärkung in beiden Fällen gleich und analoger und digitaler Regler besser vergleichbar.&lt;br /&gt;
&lt;br /&gt;
Eigentlich könnte man bei kleiner Abtastzeit direkt die Parametrierung des analogen Reglers für die digitale Realisierung übernehmen. Aber es gibt doch kleine Unterschiede in der Dynamik zwischen analoger und digitaler Ausführung und um sicher zu gehen, dass die gewählte Abtastzeit einen nicht zu großen Einfluss hat, wird noch einmal mit [[Regelungstechnik#Scicos| Scicos]] nachoptimiert. Mit einer Abtastzeit Ta = 10ms und den Parametern des analogen Reglers ergibt sich ein Überschwingen, das nur sehr langsam auf den Endwert abklingt. Durch Verringern des I-Anteils auf 60 wird ein optimales Einschwingen für den digitalen Regler erreicht. Die Parameter sind:&lt;br /&gt;
&lt;br /&gt;
Kp = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 60&lt;br /&gt;
&lt;br /&gt;
Ta = 0.01&lt;br /&gt;
&lt;br /&gt;
Zur Umsetzung in einen Code wurde die Programmiersprache C gewählt. Da der Code sehr einfach ist, sollte es auch kein Problem sein, den Code als Beispiel für andere Sprachen zu verwenden. Der Algorithmus wird im Takt der Abtastzeit, also alle 10ms aufgerufen. In der Reglergleichung kann zur Vereinfachung das Produkt Ki*Ta durch eine Ersatzvariable, die gleich das Ergebnis aus dem Produkt 60*0.01 = 0.6 hat, ersetzt werden. Zum besseren Verständnis wurde es hier beim Ki*Ta belassen. Um einen Windup-Effekt zu verhindern, wird die Summenbildung esum auf +-400 begrenzt. Der Wert wurde so gewählt, dass noch eine volle Aussteuerung durch den I-Anteil möglich ist. Zum Schluss wird die Stellgröße y auf die mögliche Aussteuerung des Stellglieds (0...255) begrenzt.&lt;br /&gt;
&lt;br /&gt;
'''Programmbeispiel digitaler PI-Regler:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	e = w - x;				//Vergleich&lt;br /&gt;
	esum = esum + e;			//Integration I-Anteil&lt;br /&gt;
	if (esum &amp;lt; -400) {esum = -400;}	        //Begrenzung I-Anteil&lt;br /&gt;
	if (esum &amp;gt; 400) {esum = 400;}&lt;br /&gt;
	y = Kp*e + Ki*Ta*esum;			//Reglergleichung&lt;br /&gt;
	if (y &amp;lt; 0) {y = 0;}			//Begrenzung Stellgröße&lt;br /&gt;
	if (y &amp;gt; 255) {y = 255;}&lt;br /&gt;
	PWM = y;				//Übergabe Stellgröße&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Lageregelung ==&lt;br /&gt;
Unter einer Lageregelung versteht man die Positionierung von Objekten. Als Beispiel soll hier ein kleiner Bot mit Radencoder eine bestimmte Weglänge fahren. Gegenüber der Drehzahl- oder Geschwindigkeitsregelung ist bei der Lageregelung noch ein zusätzlicher Integrator in der Strecke vorhanden. Die gesamte Strecke ist damit ein I-Glied mit Verzögerung. Laut Tabelle im Abschnitt „Dimensionierung des Reglers“ ist dafür ein PD-Regler gut geeignet. Der PD-Regler wird digital ausgeführt, zur Simulation und Parametrierung bietet sich deshalb Scicos an. &lt;br /&gt;
&lt;br /&gt;
Da bei einer Lageregelung der Geschwindigkeitsbereich von Null aus geht, also über den nichtlinearen Bereich geht, sollte auch in der Simulation die Nichtlinearität berücksichtigt sein. Für das Beispiel wird deshalb das Modell eines Antriebs mit Haft- und Gleitreibung genommen, wie es unter &amp;quot;Modellierung eines Antriebs – detailliertes Modell&amp;quot; bereits vorgestellt wurde. Im Scicos-Modell ist der Antrieb der Übersichtlichkeit wegen als Superblock ausgeführt. Das Blockschaltbild des Antriebs im Detail ist [http://www.roboternetz.de/wissen/images/7/73/Antrieb_Modell.png hier] zu sehen. Die Daten sind:&lt;br /&gt;
&lt;br /&gt;
R = 16 Ohm; L = 6 mH; m = 0.31 kg; Kf = 6.6 N/A&lt;br /&gt;
&lt;br /&gt;
Als Sensor kommt ein Inkrementalgeber zum Einsatz, allerdings muss der richtungssensibel sein, sonst ist keine Lageregelung möglich. Der Sensor wird in Scicos mit der Rundungsformel (round(u1*500)) simuliert. Das ergibt bei einer Auflösung von 2mm ganzzahlige Schritte, wie es auch die Hardware (Inkrementalgeber mit nachfolgendem Zähler) in Wirklichkeit macht.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lageregelung.png]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Regler folgt ein Block mit der Verstärkung (5/255), der den PWM-Wert auf die Ansteuerspannung für den Motor umsetzt. Der Bruch 5/255 entspricht der Ansteuerspannung von 5V bei PWM=255. Der PD-Regler kann damit in Scicos exakt so simuliert werden, wie er schlussendlich auch als C-Code umgesetzt wird. Dazu wird der Code des PD-Reglers als Funktion in den Scifunc-Block eingegeben. Der Code ist etwas unterschiedlich zum C-Code des realen Bots, da die Syntax in Scicos doch geringfügig anders ist und die Eingangs- und Ausgangsvariablen nur bestimmte Bezeichnungen haben dürfen. Im nachfolgenden Codefenster sind beide Varianten im Vergleich zu sehen.&lt;br /&gt;
{|&lt;br /&gt;
 | '''Scifunc-Code:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y1=Kp*u1+Kd/Ta*(u1-z);&lt;br /&gt;
z=u1;&lt;br /&gt;
if y1&amp;gt;255 then&lt;br /&gt;
y1=255;&lt;br /&gt;
end&lt;br /&gt;
if y1&amp;lt;-255 then&lt;br /&gt;
y1=-255;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''C-Code für µC:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
e = w - x;&lt;br /&gt;
y = Kp*e + Kd/Ta*(e-ealt);&lt;br /&gt;
ealt = e;&lt;br /&gt;
if (y &amp;gt; 255) {&lt;br /&gt;
    y = 255;&lt;br /&gt;
    }&lt;br /&gt;
if (y &amp;lt; -255) {&lt;br /&gt;
    y = -255;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''Kommentar:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Vergleich&lt;br /&gt;
PD-Reglergleichung&lt;br /&gt;
alten Wert speichern&lt;br /&gt;
&lt;br /&gt;
pos. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
neg. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
In der praktischen Umsetzung des C-Codes wird man den Bruch Kd/Ta durch eine Ersatzvariable oder Konstante ersetzen. Dabei ergibt sich (wie in diesem Beispiel 2/0.01 = 200) meistens ein ganzzahliger Wert, was sich positiv auf die Rechenzeit auswirkt.&lt;br /&gt;
&lt;br /&gt;
Für die Abtastzeit Ta wurde 10ms gewählt. Das ist einerseits nicht zu schnell für einen µC und andererseits nicht zu lang, um die Regelung unnötig zu verlangsamen. Die Parametrierung von Kp und Kd erfolgte empirisch durch Probieren in der Simulation. Begonnen wurde mit einem reinen P-Regler und kleinem P-Anteil (Kp=1, Kd=0). In groben Schritten wurde Kp solange erhöht, bis sich deutlich Überschwinger zeigten. Dann wurde ein D-Anteil hinzugefügt und Kd so variiert, dass der Überschwinger verschwindet. Mit ein bisschen Feintuning ergaben sich so die Werte Kp=61 und Kd=2. Das Simulationsergebnis für Ansteuerspannung, Geschwindigkeit und Weg sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lage_antwort.png]]&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:Waste|Waste]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[SwitcherCAD-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/viewtopic.php?t=11818 Post: Line follower with PID controller]&lt;br /&gt;
*[http://www.scicos.org/ Scicos Homepage]&lt;br /&gt;
* [http://www.scicoslab.org/  ScicosLab Homepage]&lt;br /&gt;
* [http://www.scilab.org/ Scilab Homepage]&lt;br /&gt;
* [http://ltspice.linear.com/software/swcadiii.exe LTspice / SwitcherCAD III Download]&lt;br /&gt;
* [http://www.kahlert.com/web set_download.php demo version of WinFACT 7]&lt;br /&gt;
* [http://www.physi.uni-heidelberg.de/fp/anleitg/E01.pdf instructions for electronic placement, the last part is based PID controller]&lt;br /&gt;
* [http://www.simapp.com/ SimApp website] with trial&lt;br /&gt;
* [http://www.expertcontrol.com/ ExpertControl Homepage, Automatische Reglerauslegung mit ecICP] ecICP-Trial über Support-Seite verfügbar&lt;br /&gt;
* [http://www.me.th-mittelhessen.de/personen/professoren/orlowski/simulation-regelungstechnik/ TH-Mittelhessen Prof. Peter F. Orlowski, Simulationsprogramm SIMLER-PC]&lt;br /&gt;
&lt;br /&gt;
[[Category: Microcontroller]]&lt;br /&gt;
[[Category: Software]]&lt;br /&gt;
[[Category: Elektronik]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25250</id>
		<title>Regelungstechnik</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25250"/>
				<updated>2014-09-13T08:18:20Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Vergleich der Reglertypen */ wikify&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Regelungen''' sind ein Bestandteil unseres Lebens und das nicht nur seit Erfindung der Dampfmaschine. &lt;br /&gt;
&lt;br /&gt;
Allein schon der aufrechte Gang funktioniert nur mit Regelung. Dabei wirken die Sinne als Sensoren, das Gehirn als Regler und die Muskeln als Aktuatoren. Weitere Regelungen in unserem Körper sind z.B. die Konstanthaltung der Körpertemperatur, der Blutdruck, die Anpassung der Pupille auf Helligkeitsänderungen usw.&lt;br /&gt;
&lt;br /&gt;
Im technischen Zeitalter ist der erste geschichtlich bedeutende Regler der Fliehkraftregler von James Watt, der für die Drehzahlregelung seiner Dampfmaschine eingesetzt wurde. Seitdem ist die Regelungstechnik aus keinem Technikbereich mehr wegzudenken. Die Regelungstechnik begegnet uns im täglichen Leben auf Schritt und Tritt: Der Temperaturregler der Zentralheizung, der Temperaturregler des Kühlschranks, der Regler für die Belichtungsautomatik im Fotoapparat, das ABS-System im Auto und die Netzspannungs- und Frequenzregelung des europäischen Versorgungsnetzes sind nur einige wenige Beispiele aus diesem Bereich. &lt;br /&gt;
&lt;br /&gt;
''Autor Waste''&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Regelung'' ist zu unterscheiden von dem im allgemeinen Sprachgebrauch oft synonym gebrauchten Begriff der ''Steuerung''. Das Steuern ist ein rein vorwärts gerichteter Prozess ohne Rückkopplung. Die Ausgangsgröße wird dabei nicht überwacht und kann sich durch Störungen von außen verändern. Ein Beispiel ist die Steuerung eines Motors mit einer einstellbaren Spannung. Durch Laständerungen wird sich die Drehzahl des Motors ändern. Soll nun die Drehzahl konstant gehalten werden, bedarf es einer Rückkopplung um über die Spannung die Drehzahl anzupassen. Diese Rückkopplung ist das Kennzeichen einer Regelung.&lt;br /&gt;
&lt;br /&gt;
Das Regeln ist ein Vorgang, bei dem die Ausgangsgröße, im Beispiel die Drehzahl, fortlaufend überwacht wird und bei Abweichung über die Stellgröße, im Beispiel die Spannung, korrigiert wird. Der sich dabei ergebende Wirkungsablauf findet in einem geschlossenen Kreis, dem Regelkreis, statt.&lt;br /&gt;
&lt;br /&gt;
==Der Regelkreis==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis1.png|right|thumb|300px|Ein Regelkreis (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip einer Regelung ist das fortlaufende: '''Messen – Vergleichen – Stellen'''&lt;br /&gt;
&lt;br /&gt;
;Messen: Die Regelgröße wird direkt oder mittels Sensoren gemessen.&lt;br /&gt;
;Vergleichen: Der Wert der Regelgröße wird mit dem Sollwert verglichen. Die Differenz ist die ''Regelabweichung''.&lt;br /&gt;
;Stellen: Aus der Regelabweichung wird unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke die ''Stellgröße'' bestimmt.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis2.png|thumb|350px|Wirkunsweise einer Regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis dient dazu, eine vorgegebene physikalische Größe, die ''Regelgröße'', auf einen gewünschten Wert (Sollwert) zu bringen und dort zu halten, unabhängig von eventuell auftretenden Störungen.&lt;br /&gt;
Um die Regelungsaufgabe zu erfüllen, muss der Augenblickswert der Regelgröße – der Istwert – gemessen und mit dem Sollwert verglichen werden. Bei auftretenden Abweichungen muss in geeigneter Art und Weise nachgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Um nun diese Aufgabe technisch zu lösen, gibt es die Regelungstechnik. Sie baut im wesentlichen auf die mathematische Beschreibung und Modellbildung des Systems Regelkreis. Zur Modellierung, Beschreibung und Simulation werden Blockschaltbilder mit diskreten Signalgliedern verwendet.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis3.png|thumb|350px|Beispiel einer Geschwindigkeits&amp;amp;shy;regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein typisches Beispiel für einen Regelkreis – eine Geschwindigkeits&amp;amp;shy;regelung – wird im nebenstehenden Bild gezeigt. Die Sollgeschwindigkeit ist 80 km/h. Durch eine äußere Störung, in dem Fall eine Steigung, verlangsamt sich das Fahrzeug auf 70 km/h. Die Abweichung wird durch das Tachometer erfasst. Als Korrekturmaßnahme wird mehr Gas gegeben, um wieder auf die Sollgeschwindigkeit von 80 km/h zu kommen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Begriffe ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis4.png|right]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis besteht entsprechend des vereinfachten Blockschaltbildes, wie es oft in der Regelungstechnik verwendet wird, aus den Hauptteilen ''Regler'' und ''Regelstrecke'':&lt;br /&gt;
&lt;br /&gt;
;Regler: Ist der Teil des Regelkreises, der unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke aus der Regelabweichung die Korrekturmaßnahmen zum Ausregeln ergreift.&lt;br /&gt;
&lt;br /&gt;
;Regelstrecke: Ist der Teil des Regelkreises, der vom Regler ausgeregelt werden soll.&lt;br /&gt;
&lt;br /&gt;
;Führungsgröße (Sollwert) w: Vorgegebener Wert, auf dem die Regelgröße durch die Regelung gehalten werden soll. Sie ist eine von der Regelung nicht beeinflusste Größe und wird von außen zugeführt.&lt;br /&gt;
&lt;br /&gt;
;Regelgröße (Istwert) x: Ist die Ausgangsgröße der Regelstrecke, die zum Zweck des Regelns erfasst und zum Vergleich rückgeführt wird. In vielen Fällen ist in der Rückführung noch eine Messeinrichtung (Sensor) gezeichnet, die den Istwert erfasst, hier der Einfachheit halber weggelassen.&lt;br /&gt;
&lt;br /&gt;
;Regelabweichung e: Differenz zwischen Führungsgröße und Regelgröße '''e = w – x''', bildet die eigentliche Eingangsgröße des Reglers.&lt;br /&gt;
&lt;br /&gt;
;Stellgröße y: Ausgangsgröße der Regeleinrichtung und zugleich Eingangsgröße der Strecke. Sie überträgt die steuernde Wirkung des Reglers auf die Strecke.&lt;br /&gt;
&lt;br /&gt;
;Störgröße z: Eine von außen wirkende Größe, die eine Änderung des Istwertes der Regelgröße bewirkt und einen Regelvorgang auslöst.&lt;br /&gt;
&lt;br /&gt;
==Die Regelstrecke==&lt;br /&gt;
Die Regelstrecke stellt den zu regelnden Teil bzw. den zu regelnden Prozess dar und umfasst normalerweise eine Reihe von einzelnen Gliedern. Die Glieder werden entsprechend ihrem Zeitverhalten charakterisiert. Um das Zeitverhalten herauszufinden, legt man an den Eingang ein Testsignal an und zeichnet die Antwort auf. Im einfachsten Fall wird der Eingang mit einer sprunghaften Änderung beaufschlagt. Die Antwort auf die sprunghafte Änderung der Eingangsgröße wird Sprungantwort genannt und gibt Aufschluss über die Art der Regelstrecke und kann eventuell bereits genutzt werden, um die Parameter der Regelstrecke zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Für den Aufbau eines gut funktionierenden Regelkreises und die Auslegung von Reglern ist es eine Voraussetzung zu wissen, wie die Regelstrecke reagiert. Ohne ein genaues Wissen um das dynamische Verhalten der Regelstrecke ist es nicht möglich geeignete Regler auszuwählen und diese zu parametrieren.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten dynamischen Grundelemente zur Charakterisierung der Regelstrecke sind nachfolgend aufgelistet. Jedes Element wird mit einem Block dargestellt und darin durch ein Symbol oder der stilisierten Sprungantwort gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Proportionalglied (P-Glied)===&lt;br /&gt;
[[File:pglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art einer Regelstrecke.&lt;br /&gt;
;Beispiele: Hebel, Getriebe, Verstärker, Spannungsteiler, Sensoren bei denen das Zeitverhalten vernachlässigt werden kann&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Integrator (I-Glied)===&lt;br /&gt;
[[File:iglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Strecke ohne Ausgleich, ist häufig in Regelstrecken vorhanden.&lt;br /&gt;
;Beispiele: Beschleunigung → Geschwindigkeit → Weg, Strom → Kondensatorspannung&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 0.Ordnung (Totzeitglied)===&lt;br /&gt;
[[File:ttglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Entsteht durch Laufzeiten von Material oder Signalen. Je größer die Verzögerungszeit einer Regelstrecke ist, um so schwieriger ist sie zu regeln. &lt;br /&gt;
;Beispiele: Förderband, Rechenzeit, A/D-Wandler&lt;br /&gt;
&lt;br /&gt;
Nicht zu verwechseln mit der Totzeit, die durch das asynchrone Auftreten eines Ereignisses auf einen Zyklus entsteht. Vom Verzögerungsglied 0.Ordnung unterscheidet sich diese dadurch, daß sie mit einer gleichverteilten Wahrscheinlichkeit zwischen &amp;quot;gar nicht&amp;quot;  und dem gesamten Umfang auftritt. Diese Totzeit ist mechanisch mit einem Spiel vergleichbar das &amp;quot;gar nicht&amp;quot; bis zum vollen Umfang zu einem Fehler beiträgt. &lt;br /&gt;
;Beispiele: Erkennen eines Signals an einem Mikroprozessor&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 1.Ordnung (PT1-Glied)===&lt;br /&gt;
[[File:pt1glied.gif]]&lt;br /&gt;
&lt;br /&gt;
Viele einfache Regelstrecken haben ein solches Verhalten bzw. können näherungsweise damit beschrieben werden. Ist ein P-Glied mit nicht vernachlässigbarem Zeitverhalten.&lt;br /&gt;
;Beispiele: Gleichstrommotor (Spannung → Drehzahl), näherungsweise; Widerstand-Kondensator-Schaltung (RC-Glied)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 2.Ordnung (PT2-Glied)===&lt;br /&gt;
Man unterscheidet schwingungsfähige und nicht schwingungsfähige PT2-Glieder. Zur Charakterisierung gibt es die Parameter Dämpfung D und Eckfrequenz w&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; oder die Zeitkonstanten T&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und T&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Für Dämpfung D&amp;lt;1 ist es schwingungsfähig.&lt;br /&gt;
&lt;br /&gt;
'''Schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2aglied.gif]]&lt;br /&gt;
;Beispiele: Mechanischer Schwinger (Feder-Masse-System), elektrischer Schwingkreis (RLC-Kreis)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nicht schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2bglied.gif]]&lt;br /&gt;
;Beispiele: Zwei hintereinander geschaltete PT1-Glieder, Gleichstrommotor (Spannung → Drehzahl) mit berücksichtigter Induktivität&lt;br /&gt;
&lt;br /&gt;
==Der Regler==&lt;br /&gt;
Der Regler hat die Aufgabe, die Regelgröße zu messen, sie mit dem Sollwert zu vergleichen und bei Abweichungen die Stellgröße so zu verändern, dass Soll- und Istwert der Regelgröße wieder übereinstimmen bzw. die Differenz minimal wird.&lt;br /&gt;
&lt;br /&gt;
Die Wahl eines bestimmten Reglertyps richtet sich nach dem geforderten Zeitverhalten und der geforderten Regelgenauigkeit der Regelstrecke. Nachfolgend finden Sie eine Zusammenfassung der wichtigsten klassischen Reglertypen:&lt;br /&gt;
&lt;br /&gt;
===P-Regler===&lt;br /&gt;
Der proportionalwirkende Regler multipliziert die Regelabweichung mit seinem Verstärkungsfaktor '''Kp''' und gibt das Ergebnis unverzögert weiter. Er unterscheidet sich prinzipiell nicht vom dynamischen Element P-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der P-geregelte Kreis ist einfach und mittelschnell im Vergleich zu anderen Regelungen. Das Problem ist die bleibende Regelabweichung!&lt;br /&gt;
&lt;br /&gt;
[[File:pregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software P-Regler:'''&lt;br /&gt;
 y = Kp * e&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===I-Regler===&lt;br /&gt;
Der integralwirkende Regler summiert die Regelabweichung über der Zeit auf und multipliziert die Summe (d.h. das Integral) mit dem Faktor '''Ki'''. Je länger eine Regelabweichung ansteht, desto größer wird die Stellgröße des I-Reglers. Er unterscheidet sich prinzipiell nicht vom dynamischen Element I-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der I-geregelte Kreis ist langsam im Vergleich zu anderen Regelungen. Er hat aber den Vorteil, dass die Abweichung vollständig eliminiert wird.&lt;br /&gt;
&lt;br /&gt;
[[File:iregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software I-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
'''esum''' ist die Summe aller bisherigen Abweichungen '''e'''. Der Parameter des Software I-Reglers ist abhängig von der Rechenschrittweite '''Ta''' (Abtastzeit). Je öfter gerechnet wird, desto öfter wird auch hinzugezählt (aufintegriert). Eine kleine Abtastzeit erfordert also einen kleineren Faktor, dies wird durch die Multiplikation mit '''Ta''' verwirklicht.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PI-Regler===&lt;br /&gt;
Der PI-Regler ist die Kombination aus P- und I-Regler und kombiniert den Vorteil des P-Reglers, nämlich schnelle Reaktion, mit dem Vorteil des I-Reglers, der exakten Ausregelung.  Der PI-geregelte Kreis ist also genau und mittelschnell.&lt;br /&gt;
&lt;br /&gt;
[[File:piregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PI-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PD-Regler===&lt;br /&gt;
Der proportional-differential wirkende Regler kombiniert den P-Regler mit einem D-Anteil. &lt;br /&gt;
Der D-Anteil bewertet die Änderung einer Regelabweichung (er differenziert) und berechnet so deren Änderungsgeschwindigkeit. Diese wird mit dem Faktor '''Kd''' multipliziert und zum P-Anteil hinzuaddiert. Der PD-Regler reagiert damit schon auf Ankündigungen von Veränderungen, das bewirkt sozusagen ein Vorhalten beim Regeln.&lt;br /&gt;
&lt;br /&gt;
Der PD-geregelte Kreis ist sehr schnell im Vergleich zu anderen Regelungen, und manche Regelkreise (solche mit zweifacher Integration) sind ohne D-Anteil überhaupt nicht stabilisierbar. Das Problem der proportionalen Regler, die bleibende Regelabweichung, ist beim PD-Regler allerdings weiterhin vorhanden!&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil aller Regler mit D-Anteil kann die Unruhe im Kreis sein. Ist das Sensorsignal verrauscht, so wird dieses Rauschen durch die Differenziation weiter verstärkt und wieder in den Kreis hineingegeben. Dadurch wird der Aktuator stärker belastet. Macht der Regler insbesondere sehr hohe Ausschläge als Folge von schnellen Änderungen des Sollwertes, dann kann es sein, dass das Stellglied oder der Aktuator diese nicht umsetzen kann - die Wirkung des D-Anteils würde dann durch die Begrenzung verpuffen, und das Einschwingverhalten wäre nicht wie berechnet, sondern meist langsamer. Dies gilt aber nur für große Sprünge. Bei den normalen kleinen Regelvorgängen zum Ausgleich von Störeinflüssen wirkt der D-Anteil wie beabsichtigt.&lt;br /&gt;
&lt;br /&gt;
[[File:pdregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PD-Regler:'''&lt;br /&gt;
 y = Kp * e + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
Mit der neuesten Regelabweichung '''e''' und der vorhergehenden '''ealt''' wird der D-Anteil berechnet. Die Differenziation erfolgt damit angenähert durch Bildung des Differenzquotienten (e - ealt)/Ta.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PID-Regler===&lt;br /&gt;
Der PID Regler ist der universellste der klassischen Regler und vereinigt die guten Eigenschaften der anderen Regler. Zur Beschreibung der Eigenschaften des P-, I- und D-Anteils siehe die anderen Reglertypen. Der PID-geregelte Kreis ist genau und sehr schnell. In den meisten Anwendungen kommt deshalb der PID-Regler zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
[[File:pidregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PID-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Alternative PID-Reglerstruktur:'''&lt;br /&gt;
&lt;br /&gt;
Es gibt 2 Darstellungsmöglichkeiten, die inhaltlich identisch sind. In der analogen Regeltechnik ist noch die Darstellung mit der Nachstellzeit '''Tn''' und der Vorhaltezeit '''Tv''' üblich. Die Umrechnung zwischen den beiden Strukturen ist mit den angegebenen Formeln möglich.&lt;br /&gt;
&lt;br /&gt;
[[Bild:PIDstruktur.gif]]&lt;br /&gt;
&lt;br /&gt;
==Vergleich der Reglertypen==&lt;br /&gt;
In der folgenden Abbildung ist der Vergleich von P-, I-, PI-, PD- und PID-Regler in einem Regelkreis mit PT2-Glied als Regelstrecke dargestellt. Es ist deutlich zu sehen, dass die Regler ohne I-Anteil (P und PD) eine bleibende Regelabweichung aufweisen. Erst die Regler mit I-Anteil können auf den Endwert von 1 ausregeln. Beim reinen I-Regler geht das so langsam, dass es gar nicht mehr auf dem Diagramm zu sehen ist. Der Hauptzweck eines I-Anteils ist also die Vermeidung bleibender Regelabweichungen. Daher ist ein&lt;br /&gt;
I-Anteil normalerweise nicht nötig, wenn die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
Ausnahme: Es wird ein doppelter I-Anteil zur Vermeidung von Schleppfehlern benötigt.&lt;br /&gt;
&lt;br /&gt;
Die schnellsten Regler sind die mit einem D-Anteil (PD und PID). Der D-Anteil kommt deshalb hauptsächlich zum Einsatz, wenn schnelle Dynamik gefragt ist oder die Strecke selbst schon instabil ist. Voraussetzung für die Schnelligkeit ist allerdings, dass keine Begrenzung im Stellglied oder Aktuator auftritt. In der Praxis ist eine Begrenzung meistens nicht zu vermeiden, deshalb gilt die Sprungantwort in der Praxis nur für kleine Sprünge.&lt;br /&gt;
&lt;br /&gt;
Die Regler ohne D-Anteil, aber mit P-Anteil (P und PI) sind mittelschnell. Für einfache Regelaufgaben reicht auch oft schon ein reiner P-Regler aus, wenn die bleibende Regelabweichung vernachlässigt werden kann oder weil die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
&lt;br /&gt;
[[File:reglervergleich.gif]]&lt;br /&gt;
&lt;br /&gt;
Aus diesem Vergleich wird klar, warum der PID-Regler so beliebt ist, er vereinigt die Vorzüge aller anderen Regler.&lt;br /&gt;
&lt;br /&gt;
==Digitaler Regler==&lt;br /&gt;
Durch die Einführung leistungsfähiger und preiswerter Mikroprozessoren hat sich der digitale Regler mehr und mehr durchgesetzt. Im Gegensatz zum analogen Regler werden die Signale nicht mehr analog mit Operationsverstärker verarbeitet, sondern mit einem Mikroprozessor errechnet. Bevor das Signal vom Mikroprozessor bearbeitet werden kann, muss zunächst das Eingangssignal (Istwert) mit einem Analog-Digital-Umsetzer (ADU) digitalisiert werden, d.h. in einen Zahlenwert umgewandelt werden. Das vom digitalen Regler errechnete Ausgangssignal (Stellgröße) wird wiederum zur Ansteuerung des Stellglieds mit einem Digital-Analog-Umsetzer (DAU) in ein analoges Signal gewandelt. Funktionell unterscheiden sich analoger und digitaler Regler jedoch nicht wesentlich, es müssen nur die Schnittstellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
[[File:digreg.gif|right|framed|Digitaler Regler (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Da die Wandlungen und das Regelprogramm eine gewisse Zeit beanspruchen, vergeht pro Durchlauf die sogenannte Takt- oder Abtastzeit. Diese Zeit wirkt sich im Regelkreis wie ein Totzeitglied mit der halben Abtastzeit als Totzeit aus. Das verursacht eine zusätzliche Phasenverschiebung, was sich ungünstig auf die Stabilität des Regelkreises auswirken kann. Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der digitale Regler kann dann wie ein analoger dimensioniert werden. Ist die Abtastzeit größer, kann sie nicht mehr vernachlässigt werden, dann muss sie auch beim Reglerentwurf berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
'''Vorteile digitaler Regler:'''&lt;br /&gt;
* Die Verarbeitung erfolgt driftfrei.&lt;br /&gt;
* Es lassen sich nichtlineare Kennlinien, intelligentes Verhalten oder adaptive Regelung leichter realisieren.&lt;br /&gt;
* Der Regler kann bei Bedarf per Software neu konfiguriert und parametriert werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Digitale Realisierung am Beispiel des PID-Algorithmus'''&lt;br /&gt;
&lt;br /&gt;
Ausgehend von der Differentialgleichung für kontinuierliche Systeme wird die Differenzengleichung für zeitdiskrete Systeme erstellt. Daraus folgt dann der Stellungsalgorithmus in allgemeiner Form.&lt;br /&gt;
&lt;br /&gt;
Ta = Abtastzeit; k = Nummer der Abtastung&lt;br /&gt;
&lt;br /&gt;
Kp = Proportionalbeiwert; Ki = Integrierbeiwert; Kd = Differenzierbeiwert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- http://www.roboternetz.de/wiki/uploads/Main/pidformel.gif --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differentialgleichung für den kontinuierlichen PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y(t) \;=\;  Kp \!\cdot\! e(t) &lt;br /&gt;
          + Ki \int_0^t e(\tau) \, d\tau &lt;br /&gt;
          + Kd \, \frac{de(t)}{dt}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differenzengleichung für den zeitdiskreten PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  Kp \!\cdot\! e_k&lt;br /&gt;
          + Ki \!\cdot\! Ta \sum_{i=0}^k e_i&lt;br /&gt;
          + \frac{Kd}{Ta}\, ( e_k - e_{k-1} )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''PID Stellungs-Algorithmus:&lt;br /&gt;
:''' &amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  y_{k-1} &lt;br /&gt;
          + q_0 \!\cdot\! e_k&lt;br /&gt;
          + q_1 \!\cdot\! e_{k-1}&lt;br /&gt;
          + q_2 \!\cdot\! e_{k-2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den Parametern:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
q_0 \,=\, Kp + Ki \!\cdot\! Ta + \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_1 \,=\, -Kp  - 2 \, \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_2 \,=\, \frac{Kd}{Ta}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Umsetzung in Code nach der Differenzengleichung:'''&lt;br /&gt;
&lt;br /&gt;
Im Code wurden einige Variablen umbenannt, da die Indexschreibweise nicht möglich ist.&lt;br /&gt;
&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, esum ist die Summenbildung&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird man die Ausdrücke Ki*Ta und Kd/Ta vorab berechnen und mit Ersatzvariablen in die Reglergleichung einsetzen. Der Verständlichkeit halber wurde es hier im Code belassen. Des weiteren kann eine Begrenzung von esum notwendig werden, um einen Variablenüberlauf oder Windup-Effekt zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Der nachfolgende Code wird im Rhythmus der Abtastzeit Ta immer wieder aufgerufen.&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 esum = esum + e;				//Integration I-Anteil&lt;br /&gt;
 y = Kp*e + Ki*Ta*esum + Kd/Ta*(e – ealt);	//Reglergleichung&lt;br /&gt;
 ealt = e;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''Alternative Umsetzung in Code nach dem Stellungsalgorithmus:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, yalt entspricht y&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, ealt2 entspricht e&amp;lt;sub&amp;gt;k-2&amp;lt;/sub&amp;gt;&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 y = yalt + q0*e + q1*ealt + q2*ealt2;		//Reglergleichung&lt;br /&gt;
 ealt2 = ealt;&lt;br /&gt;
 ealt = e;&lt;br /&gt;
 yalt = y;&lt;br /&gt;
&lt;br /&gt;
==Dimensionierung des Reglers==&lt;br /&gt;
Die Auswahl des Reglertyps ist heutzutage bei den digitalen Reglern nicht mehr so kritisch, da der Mehraufwand in Software für einen PID-Regler gegenüber einfacheren Typen kaum zu Buche schlägt. Im Prinzip ist man deshalb mit einem PID-Regler fast immer auf der richtigen Seite, mit einer Ausnahme, bei einer Strecke mit reiner Totzeit. Die folgende Tabelle gibt eine Hilfestellung zur Auswahl des Reglers. &lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ '''Geeignete Reglertypen für die unterschiedlichen Regelstrecken'''&lt;br /&gt;
 |rowspan=2 |'''Strecke'''&lt;br /&gt;
 |colspan=4 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Regler'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PD'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |reine Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |-&lt;br /&gt;
 |1.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |2.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |höhere Ordnung&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |I-Glied und Verzögerung&lt;br /&gt;
 |geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Nachdem man einen geeigneten Reglertyp ausgewählt hat, stellt sich noch die Frage, wie man die Reglerparameter Kp, Ki, und Kd optimiert. Im Laufe der Zeit wurden viele Methoden zur Dimensionierung der Reglerparameter entwickelt, aber es können hier nicht alle aufgelistet werden. Diese Aufzählung beschränkt sich auf die einfacheren und gängigen Methoden der Parametrierung.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung durch Probieren (Empirisches Einstellen)===&lt;br /&gt;
&lt;br /&gt;
====Methode 1====&lt;br /&gt;
Diese Methode ist geeignet um einfache Systeme zu dimensionieren, insbesondere wenn man bereits Erfahrung mit ähnlichen Regelkreisen hat. Man fängt mit einer unkritischen Einstellung (Kp klein, Ki = 0, Kd = 0) an und erhöht langsam die Verstärkung Kp, bis die Dämpfung schlecht wird. Falls eine Schwingneigung auftritt, muss die Verstärkung wieder etwas zurück genommen werden. Dann nimmt man allmählich den Integralanteil hinzu, erhöht ihn in Schritten und probiert solange herum, bis das Ergebnis einigermaßen passt. Bei Bedarf kann noch ein D-Anteil (PID-Struktur) probiert werden. Wenn dabei die Regelung stabiler wird, kann noch mal Kp und Ki erhöht werden, bis man endgültig zufrieden ist. &lt;br /&gt;
&lt;br /&gt;
====Methode 2====&lt;br /&gt;
Alle Anteile erstmal auf 0. Dann erhöht man Kp so lange bis das System deutlich schwingt. Danach wird der Kd so lange erhöht bis das System nicht mehr schwingt. Anschliessend kann noch ein kleiner Ki Anteil hinzugegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es dürfte klar sein, dass so eine Optimierung im Blindflug nicht immer das Optimum ergibt, aber es ist eine gängige praktische Methode zur Ermittlung der Reglerparameter. Besser sieht es aus, wenn in einer Simulation empirisch optimiert wird. Zusätzliche Informationen über die Stabilität erlauben hierbei eine gezieltere Optimierung. Zudem ist das Probieren im Simulator gefahrlos möglich, was in der Realität nicht immer der Fall ist. Geeignete Programme zur Simulation sind [[Regelungstechnik#Hilfsprogramme_zur_Analyse_und_Optimierung| hier]] vorgestellt. Allerdings muss für eine Simulation die Regelstrecke bekannt sein. Ist das nicht der Fall, so bleibt nur das einfache Probieren oder das Einstellen nach der Schwingungsmethode wie im folgenden beschrieben.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung nach Einstellregeln===&lt;br /&gt;
Die Dimensionierung nach Rezept ist eine praktische Methode ohne viel Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die bekanntesten Einstellregeln sind von Ziegler/Nichols und von Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer Einstelltabellen, auf die hier aber verzichtet wird, das würde den Rahmen dieses Artikels sprengen. An der Vielzahl kann man schon ersehen, dass es kein universell gültiges Rezept gibt und mit diesen Tabellen nicht unbedingt das Optimum erreicht wird, eine Nachoptimierung kann nötig sein.&lt;br /&gt;
&lt;br /&gt;
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.&lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Schwingungsmethode:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter so verstellt, dass die Stabilitätsgrenze erreicht wird und der Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische Schwingungen ausführt. Aus der so gefundenen Einstellung können die Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden anrichtet und die überhaupt instabil gemacht werden können. Die Vorgehensweise ist folgende:&lt;br /&gt;
# Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0&lt;br /&gt;
# Die Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen ausführt.&lt;br /&gt;
# Der dabei eingestellte Wert Kp wird als Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; bezeichnet. &lt;br /&gt;
# Die Periodendauer der sich einstellenden Dauerschwingung T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; wird gemessen.&lt;br /&gt;
# Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.45*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;0.85*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.5*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.12*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken angewendet werden kann, die auch zum Schwingen gebracht werden können. &lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Sprungantwort:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Diese Methode der Parameterbestimmung beruht auf der Aufnahme der Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die nicht zum Schwingen gebracht werden können. Der Regelkreis muss allerdings geöffnet werden.&lt;br /&gt;
Vorgehensweise: Es wird die Sprungantwort aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu und die Ausgleichszeit Tg ermittelt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tu_Tg.gif]]&lt;br /&gt;
&lt;br /&gt;
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Ziegler/Nichols:&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.9/Ks*Tg/Tu&lt;br /&gt;
 |3.3*Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1.2/Ks*Tg/Tu&lt;br /&gt;
 |2*Tu&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Chien/Hrones/Reswick&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.3/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.35/Ks*Tg/Tu&lt;br /&gt;
 |1.2*Tg&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6/Ks*Tg/Tu&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Tg&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| cellpadding=4 width=420&lt;br /&gt;
 |Die Parameter Tn und Tv sind aus der analogen Regelungstechnik und sind dort sehr geläufig. Die Umrechnung in die Parameter Ki und Kd erfolgt mit nebenstehenden Formeln. Siehe auch [[Regelungstechnik#PID-Regler| PID-Regler]]&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit dem Bodediagramm===&lt;br /&gt;
Ein Bode-Diagramm ist die grafische Darstellung des Frequenzganges. Es werden der Betrag der Übertragungsfunktion (Amplitudengang) und der Verlauf des Phasenwinkels (Phasengang) als Funktion der Frequenz aufgetragen. Die Frequenzachse und die Amplitudenachse werden logarithmisch dargestellt. Die logarithmische Darstellung hat den Vorteil, dass eine Multiplikation auf eine einfache Addition zurückgeführt wird. Somit wird eine Hintereinanderschaltung von Systemen im Blockschaltbild zu einer einfachen Addition im Bodediagramm.&lt;br /&gt;
&lt;br /&gt;
Das Zeitverhalten des rückgekoppelten Regelkreises hängt entscheidend vom Verlauf&lt;br /&gt;
des Frequenzganges der offenen Regelschleife in der Umgebung des Durchtretens durch&lt;br /&gt;
die 0dB-Achse ab. In der Regelungstechnik wird daher der offene Regelkreis im Bode-Diagramm aufgetragen. Das erlaubt einen schnellen Überblick über Stabilität und möglichen Reserven zur Optimierung. Ein Kriterium für die Stabilität der Schleife ist der Phasenrand und der Amplitudenrand. Der Phasenrand ist der Abstand (Phasenreserve) zur -180°-Linie bei der Durchtrittsfrequenz. Die Durchtrittsfrequenz ist diejenige Frequenz, bei der der Amplitudengang durch die 0dB-Linie geht. Siehe auch folgendes Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Phasenrand.gif]]&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |'''Regel:''' Eine geschlossene Regelschleife arbeitet genau dann stabil, wenn der Phasenrand positiv ist.&lt;br /&gt;
 |}&lt;br /&gt;
Wird diese Bedingung verletzt, so wird in diesem Frequenzbereich die im Rückführzweig der Regelung eingebrachte Gegenkopplung zu einer Mitkopplung und das System kann schwingen.&lt;br /&gt;
&lt;br /&gt;
'''Beim Reglerentwurf sind folgende Punkte zu beachten:'''&lt;br /&gt;
* Der Phasenrand muss positiv sein. Der geschlossene Regelkreis kann sonst instabil sein. &lt;br /&gt;
* Je größer der Phasenrand ist, desto größer ist die Stabilitätsreserve des Regelkreises und desto höher ist die Dämpfung des Regelkreises. Üblich sind Werte von 40°...70° für gutes Führungsverhalten und 20°...50° für gutes Störverhalten.&lt;br /&gt;
* Die Durchtrittsfrequenz ist ein Maß für die Schnelligkeit des Regelkreises, je höher, desto schneller ist die Reaktion auf Änderungen der Führungsgröße oder Störungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel zur Dimensionierung mit dem Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bode1.gif]]&lt;br /&gt;
&lt;br /&gt;
Die Strecke ist rot dargestellt und besteht in dem Beispiel aus einem nicht schwingfähigem PT2-Glied. Man sucht sich den Punkt, wo die Strecke für sich alleine noch ausreichend Phasenreserve hat, z.B. 70°. In dem Beispiel also die Frequenz, bei der die Strecke -110° Phasendrehung aufweist. Das ist etwa bei 15Hz. Da hat die Strecke ungefähr eine Dämpfung von 25dB. Wenn man nun diese Dämpfung durch eine Verstärkung von 25dB kompensiert, dann wird dieser Punkt zur Durchtrittsfrequenz. D.h. man wählt den P-Anteil des Reglers Kp=18, denn 25dB entspricht ungefähr dem Faktor 18. Um die Regelabweichung zu minimieren, wird noch ein I-Anteil hinzugefügt. Üblicherweise wählt man für die Grenzfrequenz des PI-Reglers die Grenzfrequenz des dominierenden Streckenteils, in dem Beispiel ca. 1.4Hz. Damit ergibt sich ein I-Anteil von 170. Im Bode-Diagramm ist der PI-Regler als schwarze Kurve eingezeichnet. Die Addition der Strecke und des Reglers im Bode-Diagramm führt dann zum Frequenzgang des offenen Regelkreises (blaue Kurve). Die resultierende Durchtrittsfrequenz ist wie gewählt bei etwa 15Hz. Der Phasenrand hat sich durch den I-Anteil im Regler auf ca. 60° reduziert, ist aber noch ausreichend. Das Einschwingen des geschlossenen Regelkreises für diese Dimensionierung sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort3.gif]]&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf könnte noch ein D-Anteil (PID-Regler) hinzugenommen werden, das würde die Phase anheben und man könnte dadurch die Durchtrittsfrequenz weiter nach oben schieben. In der Praxis wird dies allerdings wegen der wahrscheinlichen Begrenzung des Stellglieds kein schnelleres Einschwingen mehr bringen. &lt;br /&gt;
&lt;br /&gt;
Begrenzungen oder Nichtlinearitäten werden bei der Dimensionierung mit dem Bode-Diagramm nicht berücksichtigt. Das ist ein Nachteil dieser Methode. Eventuell muss deshalb noch einmal im Zeitbereich nachoptimiert werden.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit der Ortskurve===&lt;br /&gt;
Eine Alternative zur Dimensionierung mit dem Bodediagramm stellt die Methode über die Ortskurve des offenen Regelkreises dar.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Verfahren ist schnell auf einem Blick ersichtlich ob der Regelkreis stabil ist.&lt;br /&gt;
&lt;br /&gt;
Liegt der Punkt -1 auf der Realteilachse links von der Ortskurve in Richtung steigendem Omega so ist der Regelkreis stabil.&lt;br /&gt;
Der Abstand zu der kritischen Kreisfrequenz Omega Krit von der Imaginärteilachse ist die Verstärkung Vr mit diesem Wert lässt sich der Amplitudenrand ermitteln. &lt;br /&gt;
Dazu wird folgende Formel verwendet: Ar = 20 lg (1/Vr) in dB&lt;br /&gt;
&lt;br /&gt;
Die Durchtrittskreisfrequenz Omega D ist an dem Punkt, wo der Betrag aus Realteil und Imaginärteil 1 ergibt. Wenn man weiß, wo die Durchtrittskreisfrequenz ist, dann kann man den Phasenrand bestimmen.&lt;br /&gt;
Dies ist der Winkel zwischen der -180° Linie zu Omega D.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ortskurve.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Hilfsprogramme zur Analyse und Optimierung==&lt;br /&gt;
Die Analyse und Optimierung von Regelkreisen wird wesentlich erleichtert durch die Zuhilfenahme von Programmen. Es erspart einem eine komplizierte Rechnerei von Hand oder umfangreiche Testläufe. Stellvertretend für all die verfügbaren Programme werden hier zwei Freeware-Programme vorgestellt, die dafür gut geeignet sind. Die Beschreibung hier ersetzt aber keine Tutorials, es wird nur die Anwendung für die Regelungstechnik beschrieben. &lt;br /&gt;
&lt;br /&gt;
===Scilab/Scicos===&lt;br /&gt;
Scilab ist ein wissenschaftlich-technisches Softwarepaket für numerische Berechnungen. Scicos ist eine Erweiterung dazu, die eine blockorientierte und modellbasierte Simulation und Analyse von dynamischen Systemen bietet. Dieses Softwarepaket kann von der [http://www.scilab.org/ Scilab Homepage] herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
====Scilab====&lt;br /&gt;
Mit Scilab ist es sehr einfach ein Bode-Diagramm zu zeichnen, es bedarf nur 3 Zeilen Code.&lt;br /&gt;
 s=poly(0,'s');&lt;br /&gt;
 G=syslin('c',0.72/(0.11*s+1));&lt;br /&gt;
 bode(G)&lt;br /&gt;
Die 1.Zeile '''s=poly(0,'s');''' legt die Variable s als Polynomvariable fest. Dies braucht in einer Sitzung nur einmal gemacht zu werden. Die 2.Zeile '''G=syslin('c',0.72/(0.11*s+1));''' definiert ein lineares System mit der Übertragungsfunktion 0.72/(0.11s+1). Die 3.Zeile '''bode(G)''' zeichnet das Bode-Diagramm des zuvor mit syslin definierten Systems G. Zu beachten ist, dass Scilab auf der x-Achse im Bode-Diagramm die Frequenz in Hertz und nicht wie üblich die Kreisfrequenz darstellt. Anstelle des Bode-Diagramms kann auch die Sprungantwort gezeichnet werden. Dies geschieht mit folgenden Befehlen:&lt;br /&gt;
 xbasc();&lt;br /&gt;
 t=[0:0.001:2];&lt;br /&gt;
 y=csim('step',t,G);&lt;br /&gt;
 plot2d(t,y)&lt;br /&gt;
'''xbasc()''' löscht den letzten Plot mit dem Bode-Diagramm und mit '''t=[0:0.001:2]''' wird ein Vektor t mit den angegebenen Zeiten im Intervall von 1ms definiert. Die Zeile '''y=csim('step',t,G)''' berechnet die Sprungantwort des zuvor mit syslin definierten Systems G und speichert sie in y ab. Das Ergebnis wird dann mit '''plot2d(t,y)''' dargestellt. Bei Bedarf können noch Gitternetzlinien mit dem Befehl '''xgrid()''' hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Ergänzend hier noch ein Scilab-Skript, welches recht hilfreich bei der Dimensionierung mit dem Bode-Diagramm ist. Den nachfolgenden Code einfach in das SciPad-Fenster (Editor von Scilab) kopieren und starten. Es werden 2 Grafikfenster angezeigt, eines mit dem Bode-Diagramm und ein zweites mit der Sprungantwort. Man kann im Skript die Streckencharakteristik anpassen und verschiedene Reglerparameter ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ks=0.72;                            // Verstärkung der Strecke&lt;br /&gt;
T1=0.11;                            // Zeitkonstante 1&lt;br /&gt;
T2=0.005;                           // Zeitkonstante 2&lt;br /&gt;
Kp=18;                              // Proportionalbeiwert&lt;br /&gt;
Ki=170;                             // Integralbeiwert&lt;br /&gt;
Kd=0;                               // Differenzialbeiwert&lt;br /&gt;
 &lt;br /&gt;
s=poly(0,'s');                      // definiert s als Polynomvariable&lt;br /&gt;
P=(T1*s+1)*(T2*s+1);                // Streckencharakteristik&lt;br /&gt;
Gs=syslin('c',Ks,P)                 // Übertragungsfunktion der Strecke&lt;br /&gt;
&lt;br /&gt;
RZ=poly([Ki Kp Kd],'s','coeff')     // Zählerpolynom des Reglers&lt;br /&gt;
RN=poly([0 1],'s','coeff')          // Nennerpolynom des Reglers&lt;br /&gt;
Gr=syslin('c',RZ,RN)                // Übertragungsfunktion des Reglers&lt;br /&gt;
&lt;br /&gt;
G=Gr*Gs                             // Übertragungsfunktion gesamt&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,0);&lt;br /&gt;
xbasc(0);&lt;br /&gt;
bode([Gr;G;Gs],0.1,100,['Regler';'gesamt';'Strecke'])&lt;br /&gt;
&lt;br /&gt;
Gcl=G/(G+1)                         // geschlossene Regelschleife&lt;br /&gt;
t=0:0.001:0.2;&lt;br /&gt;
y=csim('step',t,Gcl);               // berechnet Sprungantwort&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,1);&lt;br /&gt;
xbasc(1);&lt;br /&gt;
plot2d(t,y,2);&lt;br /&gt;
xgrid();&lt;br /&gt;
xtitle(&amp;quot;Sprungantwort&amp;quot;,&amp;quot;sec&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Scicos====&lt;br /&gt;
Eine weitere Möglichkeit zur Simulation im Zeitbereich bietet Scicos. Die Modellierung geschieht mit einem grafischen Editor, in dem Blöcke mit vordefinierten oder selbstgemachten Funktionen miteinander verbunden werden. Ein einfaches Modell eines Regelkreises mit PID-Regler sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_anaReg.gif]]&lt;br /&gt;
&lt;br /&gt;
Der PID-Regler ist mit seinen 3 Zweigen (P, I und D) dargestellt. In den Verstärkerblöcken kann durch Ändern der Reglerparameter (KP, KI und KD) der Regler optimiert werden. Die Strecke ist in diesem Beispiel nur ein einzelner Block, in dem die Übertragungsfunktion eingegeben wird. Man kann die Strecke auch detaillierter mit einzelnen Funktionsblöcken darstellen. Ein Beispiel eines komplexen Blockschaltbilds für einen balancierenden Bot ist unter diesem [http://www.roboternetz.de/phpBB2/download.php?id=5082 Link] zu finden.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil der Simulation mit Scicos ist die Möglichkeit Nichtlinearitäten zu berücksichtigen und die Kombination von kontinuierlichen und diskreten Funktionen. Das heißt, man kann einen digitalen Regler mit seinen diskreten Schritten und eine analoge Strecke, als kontinuierliche Funktion eingegeben, zusammen simulieren. Scicos bietet sogar einen 'Scifunc'-Block, mit dem Rechenschritte des digitalen Reglers nachgebildet werden können. Damit wird sowohl das dynamische Verhalten, verursacht durch die Abtastzeit Ta, als auch die etwas unterschiedliche Dynamik durch die digitale Ausführung eines I- und D-Anteils richtig simuliert. Ein Beispiel für den Einsatz des Scifunc-Blocks ist in folgendem Blockschaltbild zu sehen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_digReg.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel: [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlregelung]] mit digitalem Regler&lt;br /&gt;
&lt;br /&gt;
Die globalen Variablen für die Reglerparameter und die Abtastzeit werden unter dem Menüpunkt „Edit - Context“ abgelegt.&lt;br /&gt;
 Kp=18;&lt;br /&gt;
 Ki=60;&lt;br /&gt;
 Ta=0.01;&lt;br /&gt;
In den Taktgeber für den digitalen Regler wird als Clock-Periode die Abtastzeit Ta eingetragen. In das Dialogfenster zum Scifunc-Block wird folgender Code zur Simulation des digitalen PI-Reglers eingetragen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z=z+Ki*Ta*u1&lt;br /&gt;
if z&amp;gt;5 then&lt;br /&gt;
z=5;&lt;br /&gt;
end&lt;br /&gt;
y1=Kp*u1+z&lt;br /&gt;
if y1&amp;gt;5 then&lt;br /&gt;
y1=5;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
z entspricht der Variable esum vom Beispiel des [[Regelungstechnik#Realisierung_mit_digitalem_Regler| digitalen Drehzahlreglers]]; u1 ist die Eingangsvariable und y1 die Ausgangsvariable des Scifunc-Blocks.&lt;br /&gt;
In den Block für die Strecke wird die Übertragungsfunktion eingetragen. Als Zähler die Verstärkung Ks, also 0.72. Im Nenner das Polynom (1+0.11*s) für die Charakteristik der Strecke. Mit ‚Simulate – Run’ wird die Simulation gestartet. Als Ergebnis sollte das Einschwingen der Stellgröße (schwarz) und der Regelgröße (grün), wie in folgender Abbildung erscheinen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort_DZR.png]]&lt;br /&gt;
&lt;br /&gt;
Man kann nun mit den Reglerparametern und verschiedenen Abtastzeiten spielen, um zu sehen wie sich die Änderungen auswirken. Zum Beispiel wird bei einer Verdopplung der Abtastzeit der Regelkreis bereits instabil.&lt;br /&gt;
&lt;br /&gt;
Diese Beispiele sind nur ein kurzer Auszug von den Möglichkeiten mit Scilab/Scicos für den Einsatz in der Regelungstechnik. Darüber hinaus ist es auch sehr gut geeignet bei anderen Optimierungsverfahren wie z.B. beim WOK-Verfahren (Wurzelortskurven) oder zur Analyse und Optimierung von modernen Reglern wie z.B. Zustandsregler und Kalmanfilter.&lt;br /&gt;
&lt;br /&gt;
===LTspice/SwitcherCad III===&lt;br /&gt;
Dieses Programm ist ein SPICE-Derivat von der Firma Linear Technology und ist unter den 2 Namen LTspice und SwitcherCad III bekannt. Der Einfachheit halber wird für die weitere Beschreibung hier nur der Name LTspice verwendet. Das Programm ist Freeware und kann unter diesem Link herunter geladen werden. http://ltspice.linear.com/software/LTspiceIV.exe&lt;br /&gt;
&lt;br /&gt;
LTspice ist ein Simulationsprogramm zur Analyse von elektronischen Schaltungen. Mit LTspice kann sowohl im Zeitbereich als auch im Frequenzbereich analysiert werden und bietet sich dadurch mit den entsprechenden Modellen auch für den Einsatz in der Regelungstechnik an. Wer sich bereits mit SPICE-Programmen auskennt, für den sollte es auch in der Regelungstechnik die 1.Wahl sein. &lt;br /&gt;
&lt;br /&gt;
Der Vorteil von LTspice ist die Möglichkeit einer sehr detaillierten Analyse, vorausgesetzt die Modelle sind auch so detailliert nachgebildet. Insbesondere für analoge Regler, wo die elektrische Schaltung direkt umgesetzt werden kann, empfiehlt sich der Einsatz von LTspice. Der Nachteil ist, LTspice ist nicht auf regeltechnische Belange ausgelegt worden und spezifische Symbole für die Regelungstechnik müssen selbst erstellt werden. Einige selbst erstellte Symbole für dynamische Grundelemente in LTspice sind hier abgebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTSpiceSymb.png]]&lt;br /&gt;
&lt;br /&gt;
Die 3 Symbole können [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=285 hier] heruntergeladen werden. Weitere Symbole können anhand dieser Beispiele sehr leicht selbst erstellt werden. Ein P-Glied kann durch eine spannungsgesteuerte Spannungsquelle (E-Source) oder Operationsverstärker mit einstellbarer Verstärkung dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
'''Analyse im Zeitbereich'''&lt;br /&gt;
&lt;br /&gt;
Das Beispiel des [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlreglers]] mit analogem Regler wird hier mit LTspice simuliert. Das Schaltbild des Regelkreises zeigt nachfolgende Abbildung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_TRAN.png]]&lt;br /&gt;
&lt;br /&gt;
Der Vergleicher (U1) und der analoge PI-Regler (U2) sind so dargestellt, wie es auch in Wirklichkeit ausgeführt werden kann. Da der PI-Regler in der Schaltung bereits invertiert, wurden die Eingänge am Vergleicher vertauscht, damit die Polarität wieder stimmt. Der Rest des Regelkreises wurde stark vereinfacht, kann aber nach Bedarf auch ausführlicher dargestellt werden. Das PT1-Glied U3 simuliert die Strecke des Regelkreises und der Verstärker U4 dient nur zur Umrechnung auf die Drehzahl. Zur Simulation im Zeitbereich wird auf den Führungswert w mit der Spannungsquelle V1 ein Sprung gegeben. In der Reglerschaltung wurde bewusst ein Operationsverstärker mit Versorgungsspannung gewählt, damit auch der Einfluss einer Begrenzung mit simuliert wird. Die Zeitbereichsanalyse wird durch den LTspicebefehl .TRAN erreicht. Die Sprungantwort (Tachospannung) bei diesem Regelkreis sieht dann folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tacho2.png]]&lt;br /&gt;
&lt;br /&gt;
Durch Ändern der Bauelemente R5, R6 und C1 kann man den Regler optimieren. Eine Umrechnung auf die Reglerparameter Kp und Ki ist mit folgenden Formeln möglich, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1)&lt;br /&gt;
&lt;br /&gt;
Mit einem Mausklick auf den entsprechenden Knoten in der Schaltung können noch weitere Signale, wie z.B. die Stellgröße y angezeigt werden. Durch Verändern der Versorgungsspannung V3, V4 kann man sich auch die Auswirkung der Begrenzung ansehen. &lt;br /&gt;
&lt;br /&gt;
'''Analyse im Frequenzbereich'''&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung des Bode-Diagramms der offenen Regelschleife in LTspice muss ein Trick angewendet werden, denn durch das Auftrennen der Regelschleife würde der Arbeitspunkt verloren gehen und dadurch die offene Schleife ohne Gegenkopplung an den Anschlag fahren.&lt;br /&gt;
&lt;br /&gt;
Mit einer zusätzlichen Spannungsquelle in der Schleife kann man dieses Problem umgehen. Die Schleife bleibt für den Erhalt des Arbeitspunktes weiterhin geschlossen und man kann trotzdem die Verstärkung der offenen Schleife durch das Verhältnis der Spannung vor und hinter der Spannungsquelle bestimmen. Das erweiterte Blockschaltbild sieht folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_AC.png]]&lt;br /&gt;
&lt;br /&gt;
V2 ist die zusätzliche Spannungsquelle für die AC-Analyse. Die Spannungsquelle V1 wird von Pulsform auf Gleichspannung umgestellt. Sie wird so gewählt, dass sich der gewünschte Arbeitspunkt einstellt. Durch den LTspicebefehl .AC wird die Analyse im Frequenzbereich veranlasst. Um das Bode-Diagramm des offenen Regelkreises darzustellen, wird als Kurve nicht ein einzelner Knoten ausgewählt, sondern das Verhältnis der Spannung vom Ende zum Anfang des Regelkreises, in unserem Beispiel also V(tacho)/V(x). Zur Anzeige kommt dann das Bode-Diagramm (grüne Kurve) der offenen Schleife, wie in der folgenden Abbildung zu sehen. Für den Amplitudengang (durchgezogene Linien) gilt die linke Skala in dB, für den Phasengang (gestrichelte Linien) die rechte Skala in Grad.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_Bode.png]]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist noch das Bode-Diagramm der Strecke (rote Kurve) zu sehen. Dies ist durch einfaches Hinzufügen einer weiteren Kurve mit dem Ausdruck V(tacho)/V(y) durchgeführt worden. &lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zur üblichen Darstellung des Bode-Diagramms eines offenen Regelkreises, beinhaltet das mit LTspice erstellte Bode-Diagramm auch die -180 Grad Phasendrehung der Gegenkopplung. Der Phasenrand ist deshalb nicht auf -180 Grad sondern auf 0 Grad zu beziehen. In unserem Beispiel ist der Phasenrand etwa 90 Grad, also ein sehr stabiler Regelkreis. Zu beachten ist, dass die Frequenzachse des Bode-Diagramms wie auch schon bei Scilab in der Einheit Hertz anstatt wie üblich in der Kreisfrequenzeinheit rad/s dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
==Modellierung eines Motors/Antriebs==&lt;br /&gt;
[[Bild:ESB_Motor.png|thumb|320px|Ersatzschaltbild DC-Motor]]&lt;br /&gt;
Der Motor ist ein oft verwendeter Aktuator in der Robotik. Deshalb wird hier am Beispiel des Gleichstrommotors mit Permanentmagnet (Nebenschlussmotor) die Modellbildung gezeigt. Zur Modellierung gibt es mehrere Möglichkeiten. Je nachdem wie detailliert die Simulation sein soll, kann man sich ein Modell, von sehr einfach bis sehr detailliert, auswählen. Zwei Zeitkonstanten bestimmen die Dynamik eines Gleichstrommotors. Eine davon ist die mechanische Zeitkonstante, die ist meistens die dominierende Zeitkonstante und wird durch das Trägheitsmoment J des Rotors verursacht. Die zweite Zeitkonstante ist die elektrische Zeitkonstante, sie wird durch die Induktivität L bestimmt. Bei einfachen Regelungen kann in den meisten Fällen die elektrische Zeitkonstante vernachlässigt werden, damit reduziert sich das Modell auf ein einzelnes PT1-Glied.&lt;br /&gt;
&lt;br /&gt;
'''Definition: Motor und Antrieb'''&lt;br /&gt;
&lt;br /&gt;
Als '''Motor''' wird hier der Motor alleine verstanden. Die Ausgangsgröße ist die Winkelgeschwindigkeit w (Drehzahl).&lt;br /&gt;
 &lt;br /&gt;
Als '''Antrieb''' wird hier der komplette Antrieb eines Fahrzeugs verstanden, also Motor inklusive Getriebe und Masse des Fahrzeugs. Für die Dynamik ist nicht nur das Trägheitsmoment des Motors sondern auch die Masse des Fahrzeugs verantwortlich. Die Ausgangsgröße der Einheit „Antrieb“ ist die Geschwindigkeit v.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellten Modelle gelten sowohl für einen Motor als auch für einen kompletten Antrieb, wenn man die Elastizität und das Spiel des Getriebes vernachlässigt.&lt;br /&gt;
&lt;br /&gt;
===Einfaches Modell mit PT1-Glied===&lt;br /&gt;
Die einfachste Art einen Motor oder Antrieb zu simulieren, ist mit einem PT1-Glied als Modell. Das Simulationsprogramm [[Regelungstechnik#Scicos|Scicos]] bietet dazu einen Block zur Eingabe der Übertragungsfunktion (num(s)=Zähler, den(s)=Nenner der Übertragungsfunktion).&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G(s)=\frac{K}{1+Ts}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |Beispiel:&lt;br /&gt;
 num(s) = K = 0.72&lt;br /&gt;
 den(s) = 1 + Ts = 1 + 0.11s&lt;br /&gt;
 |[[Bild:Scicos_TF.png]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Wird nicht nur das Ausgangssignal, also die Geschwindigkeit oder Drehzahl in der Simulation benötigt, sondern auch die Beschleunigung, dann kann nachfolgendes Modell verwendet werden. Dieses Modell ist der Differentialgleichung eines PT1-Glieds nachempfunden und liefert das gleiche Ergebnis wie vorheriges Modell, bietet aber noch den Zugriff auf das Beschleunigungssignal.&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Differentialgleichung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;v'=\frac{K}{T}U-\frac{1}{T}v&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |&lt;br /&gt;
 v = Geschwindigkeit&lt;br /&gt;
 v’= Beschleunigung (Ableitung von v)&lt;br /&gt;
 K = Übertragungsmaß&lt;br /&gt;
 T = Zeitkonstante&lt;br /&gt;
 U = Eingangsgröße (z.B. Spannung)&lt;br /&gt;
 |[[Bild:Antrieb_PT1.png|thumb|Einfaches Modell eines Antriebs]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Die beiden Parameter K und T müssen ausgemessen werden, wenn sie nicht bekannt sind. Die Zeitkonstante T kann in einem Anlaufversuch ermittelt werden. Dazu wird auf den Motor ein Spannungssprung gegeben und die Sprungantwort am Ausgang nachgemessen. Bei einem Antrieb erspart diese Methode die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente (Motor, Getriebe, Fahrzeug). Bei der Ermittlung des Übertragungsmaß K ist zu beachten, dass sich möglicherweise der Motor durch starke Reibung erst ab einer bestimmten Spannung dreht. Hier ist die Steigung der Kennlinie mit delta&amp;amp;nbsp;v&amp;amp;nbsp;/&amp;amp;nbsp;delta&amp;amp;nbsp;U auszuwerten, wie im folgenden Bild zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_stat.png]]&lt;br /&gt;
&lt;br /&gt;
Die einfachen Modelle gelten nur für den linearen Teil der Kennlinie. Soll auch die Nichtlinearität durch Reibung modelliert werden, dann sind detailliertere Modelle, wie im Folgenden beschrieben, zu verwenden. Die Auswirkung einer Haftreibung ist auch in dem Geschwindigkeitsdiagramm durch die Hysterese in der Kennlinie zu sehen. Beim Hochfahren der Ansteuerspannung bewegt sich das Fahrzeug erst ab ca. 1.25V, während beim Herunterfahren der Ansteuerspannung das Fahrzeug noch bis 0.75V rollt und erst unter 0.75V stehen bleibt.&lt;br /&gt;
&lt;br /&gt;
===Detailliertes Modell===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Motor_Model.png|thumb|350px|Detailliertes Motormodell]]&lt;br /&gt;
Ein detailliertes Motormodell ist rechts in dem Bild zu sehen. Es hat auf der linken Seite den elektrischen Teil mit den Parametern R (Widerstand) und L (Induktivität) und auf der rechten Seite den mechanischen Teil mit den Blöcken Trägheitsmoment und Reibung. Der elektrische Teil liefert das Stromsignal i, welches mit der Motorkonstante Km in das Drehmoment M umgerechnet wird. Mit dem folgenden Summierglied kann über einen zusätzlichen Eingang auch ein extern angreifendes Lastmoment mit simuliert werden. Am Ausgang des mechanischen Teils steht die Winkelgeschwindigkeit w in der Einheit [rad/s] bzw. über den Umrechnungsfaktor 9.55 die Drehzahl in [Upm] zur Verfügung. Die Reibung wird in einem nichtlinearen Block mittels Lookup-Table simuliert. In der einschlägigen Literatur wird die Reibung meistens mit einem Dämpfungsfaktor (linear) simuliert, was einer viskosen Reibung entspricht. Das passt aber nicht so gut für Kleinmotoren, da überwiegt vor allem die trockene Reibung. Die trockene Reibung hat ein konstantes Bremsmoment wenn sich der Motor dreht (unabhängig von Drehzahl, Vorzeichen abhängig von Drehrichtung). So eine Funktion kann sehr einfach mit einer Lookup-Table realisiert werden. Die Lookup-Table kann auch dazu verwendet werden, Mischformen von trockener, viskoser und turbulenter Reibung und sogar noch Haftreibung in einem Block zu simulieren, wenn man will.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Herstellern, wie z.B. Faulhaber und Maxon, kann man die für das Modell nötigen Parameter im Datenblatt finden. Das Bremsmoment der Reibung berechnet sich aus dem Leerlaufstrom wie folgt: Bremsmoment&amp;amp;nbsp;=&amp;amp;nbsp;Motorkonstante&amp;amp;nbsp;*&amp;amp;nbsp;Leerlaufstrom &lt;br /&gt;
&lt;br /&gt;
Falls die Daten nicht verfügbar sind, muss man sie selbst ausmessen. Eine Hilfestellung zur Bestimmung der Motorkonstante und des Trägheitsmoments gibt es hier:&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=96750&amp;amp;highlight=#96750&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/viewtopic.php?t=12793&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_Modell.png|thumb|350px|Modell eines Antriebs]]&lt;br /&gt;
&lt;br /&gt;
Das detaillierte Motormodell kann auch für einen Antrieb verwendet werden, wenn man eine starre Kopplung zwischen Motor und Antriebsrad voraussetzt, also Elastizität und Spiel des Getriebes vernachlässigt. Anstelle der rotatorischen Kenngrößen (Drehmoment M, Trägheitsmoment J, Winkelgeschwindigkeit w) werden die translatorischen Kenngrößen (Kraft F, Masse m, Geschwindigkeit v) eingesetzt. Das Drehmoment wird mittels Getriebeübersetzung ü und Radius r des Antriebsrades in die entsprechende Vortriebskraft umgerechnet. Daraus ergibt sich die Kraftkonstante Kf, die für das Antriebsmodell verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Die Umrechnung ist: Kf = Km * ü/r&lt;br /&gt;
&lt;br /&gt;
Bei der Trägheitsmasse m muss neben der Masse des Fahrzeugs auch das Trägheitsmoment des Motors mit berücksichtigt werden. Die Umrechnung von Trägheitsmoment in eine äquivalente Masse = J * (ü/r)²&lt;br /&gt;
&lt;br /&gt;
Der Reibungsblock in diesem Modellbeispiel enthält eine Mischform aus Haftreibung, trockener und viskoser Reibung, wie sie typisch für einen Kleinbot mit 2 Antriebsrädern und einem Gleitpin ist.&lt;br /&gt;
&lt;br /&gt;
==Beispiel: Drehzahlregelung==&lt;br /&gt;
Es wird ein Gleichstrommotor in der Drehzahl geregelt. Als Sensor ist ein Tachogenerator vorhanden, der direkt auf der Motorwelle sitzt. Das System ist in einem kleinen Modellfahrzeug eingebaut und wird zur Geschwindigkeitsregelung eingesetzt, da die Drehzahl proportional zur Geschwindigkeit ist.&lt;br /&gt;
&lt;br /&gt;
Das Funktionsschaltbild sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl1.gif&lt;br /&gt;
&lt;br /&gt;
Als Störgröße können unterschiedliche Reibwerte oder Steigung und Gefälle rückwirkend über das Getriebe die Drehzahl beeinflussen. Das Getriebe und die Last sind zwar außerhalb der Regelschleife, beeinflussen aber durch die feste Kopplung des Getriebes die Dynamik des Regelkreises. Durch die starre Kopplung kann das Trägheitsmoment des Motors und die Masse des Fahrzeugs zusammengefasst werden. Das Gleiche gilt auch für die Reibwerte. Damit vereinfacht sich die Modellierung und das Blockschaltbild reduziert sich auf folgende Schaltung:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl2.gif&lt;br /&gt;
&lt;br /&gt;
Zur Ermittlung des dynamischen Verhaltens der Regelstrecke wird die Sprungantwort gemessen. Dazu wird auf den Eingang der Regelstrecke (Stellglied) ein Spannungssprung gegeben und die Antwort am Ausgang des Tachogenerators nachgemessen. Diese Methode erspart die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente der Regelstrecke (Motor, Getriebe, Fahrzeug). Die Messung ergab folgende Sprungantwort der Regelstrecke:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/tacho.gif&lt;br /&gt;
&lt;br /&gt;
Wie zu erwarten, ist die Sprungantwort annähernd ein Verzögerungsglied 1.Ordnung. Die abgelesene Zeitkonstante ist 0.11s. Die Verstärkung der Regelstrecke ist Ks = 0.72. Das Übertragungsmaß des Tachogenerators ist 1V pro 2480Upm. Damit kann auf die Drehzahl rückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da die Regelstrecke nur aus einem PT1-Glied besteht, könnte eine analoge Regelung fast beliebig schnell gemacht werden. Wegen der Begrenzung bringt aber das Ausreizen der Optimierung für das Führungsverhalten nicht viel, nur für das Störverhalten wäre eine schnellere Regelung sinnvoll. Um aber einen Vergleich zwischen analogem und digitalem Regler anstellen zu können wird eine Parametrierung gewählt, die auch für den digitalen Regler mit seiner Totzeit noch stabil ist. Es wird deshalb auch auf einen D-Anteil im Regler verzichtet und nur ein PI-Regler realisiert. Das vereinfachte Blockschaltbild mit den dynamischen Elementen sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl3.gif&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung wurde ein analoger als auch ein digitaler Regler realisiert. Die Parametrierung des analogen Reglers wurde mit dem Programm [[Regelungstechnik#LTspice.2FSwitcherCad_III| LTspice]] durchgeführt. Es bot sich an, da die analoge Reglerschaltung exakt simuliert werden konnte. Für die Optimierung des digitalen Reglers wurde dann [[Regelungstechnik#Scicos| Scicos]] verwendet. &lt;br /&gt;
&lt;br /&gt;
===Realisierung mit analogem Regler===&lt;br /&gt;
Die elektrische Schaltung für einen analogen PI-Regler ist in der nächsten Abbildung zu sehen. Der erste Operationsverstärker vergleicht den Sollwert w mit dem Istwert x. Der zweite Operationsverstärker bildet den PI-Regler. Die Werte R5, R6 und C1 sind für die Charakteristik des PI-Reglers zuständig. Mit R6 kann der P-Anteil und mit C1 der I-Anteil eingestellt werden. Die Optimierung der Werte wurde empirisch in einer Simulation mit LTspice durchgeführt. Da die Schaltung des PI-Reglers invertiert, wurden zum Ausgleich am Vergleicher die Eingänge an U1 vertauscht, so dass sich über die gesamte Schaltung wieder die richtige Polarität ergibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Analogregler.png]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen auf Kp und Ki können diese Formeln verwendet werden, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5 = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1) = 147&lt;br /&gt;
&lt;br /&gt;
===Realisierung mit digitalem Regler===&lt;br /&gt;
Im digitalen Regelkreis wird der Istwert '''x''' vom Tachogenerator mit einem A/D-Wandler digitalisiert. Der Sollwert '''w''' wird dem µC als digitaler Wert übergeben. Die Stellgröße '''y''' entspricht dem PWM-Wert für den Motortreiber. Um zum analogen Regler vergleichbar zu sein, wurde sowohl für den A/D-Wandler als auch für den PWM-Steller eine 8-Bit-Breite vorgesehen. Damit ist die Verstärkung in beiden Fällen gleich und analoger und digitaler Regler besser vergleichbar.&lt;br /&gt;
&lt;br /&gt;
Eigentlich könnte man bei kleiner Abtastzeit direkt die Parametrierung des analogen Reglers für die digitale Realisierung übernehmen. Aber es gibt doch kleine Unterschiede in der Dynamik zwischen analoger und digitaler Ausführung und um sicher zu gehen, dass die gewählte Abtastzeit einen nicht zu großen Einfluss hat, wird noch einmal mit [[Regelungstechnik#Scicos| Scicos]] nachoptimiert. Mit einer Abtastzeit Ta = 10ms und den Parametern des analogen Reglers ergibt sich ein Überschwingen, das nur sehr langsam auf den Endwert abklingt. Durch Verringern des I-Anteils auf 60 wird ein optimales Einschwingen für den digitalen Regler erreicht. Die Parameter sind:&lt;br /&gt;
&lt;br /&gt;
Kp = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 60&lt;br /&gt;
&lt;br /&gt;
Ta = 0.01&lt;br /&gt;
&lt;br /&gt;
Zur Umsetzung in einen Code wurde die Programmiersprache C gewählt. Da der Code sehr einfach ist, sollte es auch kein Problem sein, den Code als Beispiel für andere Sprachen zu verwenden. Der Algorithmus wird im Takt der Abtastzeit, also alle 10ms aufgerufen. In der Reglergleichung kann zur Vereinfachung das Produkt Ki*Ta durch eine Ersatzvariable, die gleich das Ergebnis aus dem Produkt 60*0.01 = 0.6 hat, ersetzt werden. Zum besseren Verständnis wurde es hier beim Ki*Ta belassen. Um einen Windup-Effekt zu verhindern, wird die Summenbildung esum auf +-400 begrenzt. Der Wert wurde so gewählt, dass noch eine volle Aussteuerung durch den I-Anteil möglich ist. Zum Schluss wird die Stellgröße y auf die mögliche Aussteuerung des Stellglieds (0...255) begrenzt.&lt;br /&gt;
&lt;br /&gt;
'''Programmbeispiel digitaler PI-Regler:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	e = w - x;				//Vergleich&lt;br /&gt;
	esum = esum + e;			//Integration I-Anteil&lt;br /&gt;
	if (esum &amp;lt; -400) {esum = -400;}	        //Begrenzung I-Anteil&lt;br /&gt;
	if (esum &amp;gt; 400) {esum = 400;}&lt;br /&gt;
	y = Kp*e + Ki*Ta*esum;			//Reglergleichung&lt;br /&gt;
	if (y &amp;lt; 0) {y = 0;}			//Begrenzung Stellgröße&lt;br /&gt;
	if (y &amp;gt; 255) {y = 255;}&lt;br /&gt;
	PWM = y;				//Übergabe Stellgröße&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Lageregelung ==&lt;br /&gt;
Unter einer Lageregelung versteht man die Positionierung von Objekten. Als Beispiel soll hier ein kleiner Bot mit Radencoder eine bestimmte Weglänge fahren. Gegenüber der Drehzahl- oder Geschwindigkeitsregelung ist bei der Lageregelung noch ein zusätzlicher Integrator in der Strecke vorhanden. Die gesamte Strecke ist damit ein I-Glied mit Verzögerung. Laut Tabelle im Abschnitt „Dimensionierung des Reglers“ ist dafür ein PD-Regler gut geeignet. Der PD-Regler wird digital ausgeführt, zur Simulation und Parametrierung bietet sich deshalb Scicos an. &lt;br /&gt;
&lt;br /&gt;
Da bei einer Lageregelung der Geschwindigkeitsbereich von Null aus geht, also über den nichtlinearen Bereich geht, sollte auch in der Simulation die Nichtlinearität berücksichtigt sein. Für das Beispiel wird deshalb das Modell eines Antriebs mit Haft- und Gleitreibung genommen, wie es unter &amp;quot;Modellierung eines Antriebs – detailliertes Modell&amp;quot; bereits vorgestellt wurde. Im Scicos-Modell ist der Antrieb der Übersichtlichkeit wegen als Superblock ausgeführt. Das Blockschaltbild des Antriebs im Detail ist [http://www.roboternetz.de/wissen/images/7/73/Antrieb_Modell.png hier] zu sehen. Die Daten sind:&lt;br /&gt;
&lt;br /&gt;
R = 16 Ohm; L = 6 mH; m = 0.31 kg; Kf = 6.6 N/A&lt;br /&gt;
&lt;br /&gt;
Als Sensor kommt ein Inkrementalgeber zum Einsatz, allerdings muss der richtungssensibel sein, sonst ist keine Lageregelung möglich. Der Sensor wird in Scicos mit der Rundungsformel (round(u1*500)) simuliert. Das ergibt bei einer Auflösung von 2mm ganzzahlige Schritte, wie es auch die Hardware (Inkrementalgeber mit nachfolgendem Zähler) in Wirklichkeit macht.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lageregelung.png]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Regler folgt ein Block mit der Verstärkung (5/255), der den PWM-Wert auf die Ansteuerspannung für den Motor umsetzt. Der Bruch 5/255 entspricht der Ansteuerspannung von 5V bei PWM=255. Der PD-Regler kann damit in Scicos exakt so simuliert werden, wie er schlussendlich auch als C-Code umgesetzt wird. Dazu wird der Code des PD-Reglers als Funktion in den Scifunc-Block eingegeben. Der Code ist etwas unterschiedlich zum C-Code des realen Bots, da die Syntax in Scicos doch geringfügig anders ist und die Eingangs- und Ausgangsvariablen nur bestimmte Bezeichnungen haben dürfen. Im nachfolgenden Codefenster sind beide Varianten im Vergleich zu sehen.&lt;br /&gt;
{|&lt;br /&gt;
 | '''Scifunc-Code:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y1=Kp*u1+Kd/Ta*(u1-z);&lt;br /&gt;
z=u1;&lt;br /&gt;
if y1&amp;gt;255 then&lt;br /&gt;
y1=255;&lt;br /&gt;
end&lt;br /&gt;
if y1&amp;lt;-255 then&lt;br /&gt;
y1=-255;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''C-Code für µC:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
e = w - x;&lt;br /&gt;
y = Kp*e + Kd/Ta*(e-ealt);&lt;br /&gt;
ealt = e;&lt;br /&gt;
if (y &amp;gt; 255) {&lt;br /&gt;
    y = 255;&lt;br /&gt;
    }&lt;br /&gt;
if (y &amp;lt; -255) {&lt;br /&gt;
    y = -255;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''Kommentar:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Vergleich&lt;br /&gt;
PD-Reglergleichung&lt;br /&gt;
alten Wert speichern&lt;br /&gt;
&lt;br /&gt;
pos. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
neg. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
In der praktischen Umsetzung des C-Codes wird man den Bruch Kd/Ta durch eine Ersatzvariable oder Konstante ersetzen. Dabei ergibt sich (wie in diesem Beispiel 2/0.01 = 200) meistens ein ganzzahliger Wert, was sich positiv auf die Rechenzeit auswirkt.&lt;br /&gt;
&lt;br /&gt;
Für die Abtastzeit Ta wurde 10ms gewählt. Das ist einerseits nicht zu schnell für einen µC und andererseits nicht zu lang, um die Regelung unnötig zu verlangsamen. Die Parametrierung von Kp und Kd erfolgte empirisch durch Probieren in der Simulation. Begonnen wurde mit einem reinen P-Regler und kleinem P-Anteil (Kp=1, Kd=0). In groben Schritten wurde Kp solange erhöht, bis sich deutlich Überschwinger zeigten. Dann wurde ein D-Anteil hinzugefügt und Kd so variiert, dass der Überschwinger verschwindet. Mit ein bisschen Feintuning ergaben sich so die Werte Kp=61 und Kd=2. Das Simulationsergebnis für Ansteuerspannung, Geschwindigkeit und Weg sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lage_antwort.png]]&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:Waste|Waste]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[SwitcherCAD-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/viewtopic.php?t=11818 Post: Line follower with PID controller]&lt;br /&gt;
*[http://www.scicos.org/ Scicos Homepage]&lt;br /&gt;
* [http://www.scicoslab.org/  ScicosLab Homepage]&lt;br /&gt;
* [http://www.scilab.org/ Scilab Homepage]&lt;br /&gt;
* [http://ltspice.linear.com/software/swcadiii.exe LTspice / SwitcherCAD III Download]&lt;br /&gt;
* [http://www.kahlert.com/web set_download.php demo version of WinFACT 7]&lt;br /&gt;
* [http://www.physi.uni-heidelberg.de/fp/anleitg/E01.pdf instructions for electronic placement, the last part is based PID controller]&lt;br /&gt;
* [http://www.simapp.com/ SimApp website] with trial&lt;br /&gt;
* [http://www.expertcontrol.com/ ExpertControl Homepage, Automatische Reglerauslegung mit ecICP] ecICP-Trial über Support-Seite verfügbar&lt;br /&gt;
* [http://www.me.th-mittelhessen.de/personen/professoren/orlowski/simulation-regelungstechnik/ TH-Mittelhessen Prof. Peter F. Orlowski, Simulationsprogramm SIMLER-PC]&lt;br /&gt;
&lt;br /&gt;
[[Category: Microcontroller]]&lt;br /&gt;
[[Category: Software]]&lt;br /&gt;
[[Category: Elektronik]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Reglervergleich.gif&amp;diff=25249</id>
		<title>Datei:Reglervergleich.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Reglervergleich.gif&amp;diff=25249"/>
				<updated>2014-09-13T08:17:50Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/vergleich.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/vergleich.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25248</id>
		<title>Regelungstechnik</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25248"/>
				<updated>2014-09-13T08:15:25Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Der Regler */ wikify: iregler.gif, pregler.gif, piregler.gif, pdregler.gif, pidregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Regelungen''' sind ein Bestandteil unseres Lebens und das nicht nur seit Erfindung der Dampfmaschine. &lt;br /&gt;
&lt;br /&gt;
Allein schon der aufrechte Gang funktioniert nur mit Regelung. Dabei wirken die Sinne als Sensoren, das Gehirn als Regler und die Muskeln als Aktuatoren. Weitere Regelungen in unserem Körper sind z.B. die Konstanthaltung der Körpertemperatur, der Blutdruck, die Anpassung der Pupille auf Helligkeitsänderungen usw.&lt;br /&gt;
&lt;br /&gt;
Im technischen Zeitalter ist der erste geschichtlich bedeutende Regler der Fliehkraftregler von James Watt, der für die Drehzahlregelung seiner Dampfmaschine eingesetzt wurde. Seitdem ist die Regelungstechnik aus keinem Technikbereich mehr wegzudenken. Die Regelungstechnik begegnet uns im täglichen Leben auf Schritt und Tritt: Der Temperaturregler der Zentralheizung, der Temperaturregler des Kühlschranks, der Regler für die Belichtungsautomatik im Fotoapparat, das ABS-System im Auto und die Netzspannungs- und Frequenzregelung des europäischen Versorgungsnetzes sind nur einige wenige Beispiele aus diesem Bereich. &lt;br /&gt;
&lt;br /&gt;
''Autor Waste''&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Regelung'' ist zu unterscheiden von dem im allgemeinen Sprachgebrauch oft synonym gebrauchten Begriff der ''Steuerung''. Das Steuern ist ein rein vorwärts gerichteter Prozess ohne Rückkopplung. Die Ausgangsgröße wird dabei nicht überwacht und kann sich durch Störungen von außen verändern. Ein Beispiel ist die Steuerung eines Motors mit einer einstellbaren Spannung. Durch Laständerungen wird sich die Drehzahl des Motors ändern. Soll nun die Drehzahl konstant gehalten werden, bedarf es einer Rückkopplung um über die Spannung die Drehzahl anzupassen. Diese Rückkopplung ist das Kennzeichen einer Regelung.&lt;br /&gt;
&lt;br /&gt;
Das Regeln ist ein Vorgang, bei dem die Ausgangsgröße, im Beispiel die Drehzahl, fortlaufend überwacht wird und bei Abweichung über die Stellgröße, im Beispiel die Spannung, korrigiert wird. Der sich dabei ergebende Wirkungsablauf findet in einem geschlossenen Kreis, dem Regelkreis, statt.&lt;br /&gt;
&lt;br /&gt;
==Der Regelkreis==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis1.png|right|thumb|300px|Ein Regelkreis (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip einer Regelung ist das fortlaufende: '''Messen – Vergleichen – Stellen'''&lt;br /&gt;
&lt;br /&gt;
;Messen: Die Regelgröße wird direkt oder mittels Sensoren gemessen.&lt;br /&gt;
;Vergleichen: Der Wert der Regelgröße wird mit dem Sollwert verglichen. Die Differenz ist die ''Regelabweichung''.&lt;br /&gt;
;Stellen: Aus der Regelabweichung wird unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke die ''Stellgröße'' bestimmt.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis2.png|thumb|350px|Wirkunsweise einer Regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis dient dazu, eine vorgegebene physikalische Größe, die ''Regelgröße'', auf einen gewünschten Wert (Sollwert) zu bringen und dort zu halten, unabhängig von eventuell auftretenden Störungen.&lt;br /&gt;
Um die Regelungsaufgabe zu erfüllen, muss der Augenblickswert der Regelgröße – der Istwert – gemessen und mit dem Sollwert verglichen werden. Bei auftretenden Abweichungen muss in geeigneter Art und Weise nachgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Um nun diese Aufgabe technisch zu lösen, gibt es die Regelungstechnik. Sie baut im wesentlichen auf die mathematische Beschreibung und Modellbildung des Systems Regelkreis. Zur Modellierung, Beschreibung und Simulation werden Blockschaltbilder mit diskreten Signalgliedern verwendet.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis3.png|thumb|350px|Beispiel einer Geschwindigkeits&amp;amp;shy;regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein typisches Beispiel für einen Regelkreis – eine Geschwindigkeits&amp;amp;shy;regelung – wird im nebenstehenden Bild gezeigt. Die Sollgeschwindigkeit ist 80 km/h. Durch eine äußere Störung, in dem Fall eine Steigung, verlangsamt sich das Fahrzeug auf 70 km/h. Die Abweichung wird durch das Tachometer erfasst. Als Korrekturmaßnahme wird mehr Gas gegeben, um wieder auf die Sollgeschwindigkeit von 80 km/h zu kommen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Begriffe ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis4.png|right]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis besteht entsprechend des vereinfachten Blockschaltbildes, wie es oft in der Regelungstechnik verwendet wird, aus den Hauptteilen ''Regler'' und ''Regelstrecke'':&lt;br /&gt;
&lt;br /&gt;
;Regler: Ist der Teil des Regelkreises, der unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke aus der Regelabweichung die Korrekturmaßnahmen zum Ausregeln ergreift.&lt;br /&gt;
&lt;br /&gt;
;Regelstrecke: Ist der Teil des Regelkreises, der vom Regler ausgeregelt werden soll.&lt;br /&gt;
&lt;br /&gt;
;Führungsgröße (Sollwert) w: Vorgegebener Wert, auf dem die Regelgröße durch die Regelung gehalten werden soll. Sie ist eine von der Regelung nicht beeinflusste Größe und wird von außen zugeführt.&lt;br /&gt;
&lt;br /&gt;
;Regelgröße (Istwert) x: Ist die Ausgangsgröße der Regelstrecke, die zum Zweck des Regelns erfasst und zum Vergleich rückgeführt wird. In vielen Fällen ist in der Rückführung noch eine Messeinrichtung (Sensor) gezeichnet, die den Istwert erfasst, hier der Einfachheit halber weggelassen.&lt;br /&gt;
&lt;br /&gt;
;Regelabweichung e: Differenz zwischen Führungsgröße und Regelgröße '''e = w – x''', bildet die eigentliche Eingangsgröße des Reglers.&lt;br /&gt;
&lt;br /&gt;
;Stellgröße y: Ausgangsgröße der Regeleinrichtung und zugleich Eingangsgröße der Strecke. Sie überträgt die steuernde Wirkung des Reglers auf die Strecke.&lt;br /&gt;
&lt;br /&gt;
;Störgröße z: Eine von außen wirkende Größe, die eine Änderung des Istwertes der Regelgröße bewirkt und einen Regelvorgang auslöst.&lt;br /&gt;
&lt;br /&gt;
==Die Regelstrecke==&lt;br /&gt;
Die Regelstrecke stellt den zu regelnden Teil bzw. den zu regelnden Prozess dar und umfasst normalerweise eine Reihe von einzelnen Gliedern. Die Glieder werden entsprechend ihrem Zeitverhalten charakterisiert. Um das Zeitverhalten herauszufinden, legt man an den Eingang ein Testsignal an und zeichnet die Antwort auf. Im einfachsten Fall wird der Eingang mit einer sprunghaften Änderung beaufschlagt. Die Antwort auf die sprunghafte Änderung der Eingangsgröße wird Sprungantwort genannt und gibt Aufschluss über die Art der Regelstrecke und kann eventuell bereits genutzt werden, um die Parameter der Regelstrecke zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Für den Aufbau eines gut funktionierenden Regelkreises und die Auslegung von Reglern ist es eine Voraussetzung zu wissen, wie die Regelstrecke reagiert. Ohne ein genaues Wissen um das dynamische Verhalten der Regelstrecke ist es nicht möglich geeignete Regler auszuwählen und diese zu parametrieren.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten dynamischen Grundelemente zur Charakterisierung der Regelstrecke sind nachfolgend aufgelistet. Jedes Element wird mit einem Block dargestellt und darin durch ein Symbol oder der stilisierten Sprungantwort gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Proportionalglied (P-Glied)===&lt;br /&gt;
[[File:pglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art einer Regelstrecke.&lt;br /&gt;
;Beispiele: Hebel, Getriebe, Verstärker, Spannungsteiler, Sensoren bei denen das Zeitverhalten vernachlässigt werden kann&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Integrator (I-Glied)===&lt;br /&gt;
[[File:iglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Strecke ohne Ausgleich, ist häufig in Regelstrecken vorhanden.&lt;br /&gt;
;Beispiele: Beschleunigung → Geschwindigkeit → Weg, Strom → Kondensatorspannung&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 0.Ordnung (Totzeitglied)===&lt;br /&gt;
[[File:ttglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Entsteht durch Laufzeiten von Material oder Signalen. Je größer die Verzögerungszeit einer Regelstrecke ist, um so schwieriger ist sie zu regeln. &lt;br /&gt;
;Beispiele: Förderband, Rechenzeit, A/D-Wandler&lt;br /&gt;
&lt;br /&gt;
Nicht zu verwechseln mit der Totzeit, die durch das asynchrone Auftreten eines Ereignisses auf einen Zyklus entsteht. Vom Verzögerungsglied 0.Ordnung unterscheidet sich diese dadurch, daß sie mit einer gleichverteilten Wahrscheinlichkeit zwischen &amp;quot;gar nicht&amp;quot;  und dem gesamten Umfang auftritt. Diese Totzeit ist mechanisch mit einem Spiel vergleichbar das &amp;quot;gar nicht&amp;quot; bis zum vollen Umfang zu einem Fehler beiträgt. &lt;br /&gt;
;Beispiele: Erkennen eines Signals an einem Mikroprozessor&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 1.Ordnung (PT1-Glied)===&lt;br /&gt;
[[File:pt1glied.gif]]&lt;br /&gt;
&lt;br /&gt;
Viele einfache Regelstrecken haben ein solches Verhalten bzw. können näherungsweise damit beschrieben werden. Ist ein P-Glied mit nicht vernachlässigbarem Zeitverhalten.&lt;br /&gt;
;Beispiele: Gleichstrommotor (Spannung → Drehzahl), näherungsweise; Widerstand-Kondensator-Schaltung (RC-Glied)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 2.Ordnung (PT2-Glied)===&lt;br /&gt;
Man unterscheidet schwingungsfähige und nicht schwingungsfähige PT2-Glieder. Zur Charakterisierung gibt es die Parameter Dämpfung D und Eckfrequenz w&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; oder die Zeitkonstanten T&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und T&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Für Dämpfung D&amp;lt;1 ist es schwingungsfähig.&lt;br /&gt;
&lt;br /&gt;
'''Schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2aglied.gif]]&lt;br /&gt;
;Beispiele: Mechanischer Schwinger (Feder-Masse-System), elektrischer Schwingkreis (RLC-Kreis)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nicht schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2bglied.gif]]&lt;br /&gt;
;Beispiele: Zwei hintereinander geschaltete PT1-Glieder, Gleichstrommotor (Spannung → Drehzahl) mit berücksichtigter Induktivität&lt;br /&gt;
&lt;br /&gt;
==Der Regler==&lt;br /&gt;
Der Regler hat die Aufgabe, die Regelgröße zu messen, sie mit dem Sollwert zu vergleichen und bei Abweichungen die Stellgröße so zu verändern, dass Soll- und Istwert der Regelgröße wieder übereinstimmen bzw. die Differenz minimal wird.&lt;br /&gt;
&lt;br /&gt;
Die Wahl eines bestimmten Reglertyps richtet sich nach dem geforderten Zeitverhalten und der geforderten Regelgenauigkeit der Regelstrecke. Nachfolgend finden Sie eine Zusammenfassung der wichtigsten klassischen Reglertypen:&lt;br /&gt;
&lt;br /&gt;
===P-Regler===&lt;br /&gt;
Der proportionalwirkende Regler multipliziert die Regelabweichung mit seinem Verstärkungsfaktor '''Kp''' und gibt das Ergebnis unverzögert weiter. Er unterscheidet sich prinzipiell nicht vom dynamischen Element P-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der P-geregelte Kreis ist einfach und mittelschnell im Vergleich zu anderen Regelungen. Das Problem ist die bleibende Regelabweichung!&lt;br /&gt;
&lt;br /&gt;
[[File:pregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software P-Regler:'''&lt;br /&gt;
 y = Kp * e&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===I-Regler===&lt;br /&gt;
Der integralwirkende Regler summiert die Regelabweichung über der Zeit auf und multipliziert die Summe (d.h. das Integral) mit dem Faktor '''Ki'''. Je länger eine Regelabweichung ansteht, desto größer wird die Stellgröße des I-Reglers. Er unterscheidet sich prinzipiell nicht vom dynamischen Element I-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der I-geregelte Kreis ist langsam im Vergleich zu anderen Regelungen. Er hat aber den Vorteil, dass die Abweichung vollständig eliminiert wird.&lt;br /&gt;
&lt;br /&gt;
[[File:iregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software I-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
'''esum''' ist die Summe aller bisherigen Abweichungen '''e'''. Der Parameter des Software I-Reglers ist abhängig von der Rechenschrittweite '''Ta''' (Abtastzeit). Je öfter gerechnet wird, desto öfter wird auch hinzugezählt (aufintegriert). Eine kleine Abtastzeit erfordert also einen kleineren Faktor, dies wird durch die Multiplikation mit '''Ta''' verwirklicht.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PI-Regler===&lt;br /&gt;
Der PI-Regler ist die Kombination aus P- und I-Regler und kombiniert den Vorteil des P-Reglers, nämlich schnelle Reaktion, mit dem Vorteil des I-Reglers, der exakten Ausregelung.  Der PI-geregelte Kreis ist also genau und mittelschnell.&lt;br /&gt;
&lt;br /&gt;
[[File:piregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PI-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PD-Regler===&lt;br /&gt;
Der proportional-differential wirkende Regler kombiniert den P-Regler mit einem D-Anteil. &lt;br /&gt;
Der D-Anteil bewertet die Änderung einer Regelabweichung (er differenziert) und berechnet so deren Änderungsgeschwindigkeit. Diese wird mit dem Faktor '''Kd''' multipliziert und zum P-Anteil hinzuaddiert. Der PD-Regler reagiert damit schon auf Ankündigungen von Veränderungen, das bewirkt sozusagen ein Vorhalten beim Regeln.&lt;br /&gt;
&lt;br /&gt;
Der PD-geregelte Kreis ist sehr schnell im Vergleich zu anderen Regelungen, und manche Regelkreise (solche mit zweifacher Integration) sind ohne D-Anteil überhaupt nicht stabilisierbar. Das Problem der proportionalen Regler, die bleibende Regelabweichung, ist beim PD-Regler allerdings weiterhin vorhanden!&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil aller Regler mit D-Anteil kann die Unruhe im Kreis sein. Ist das Sensorsignal verrauscht, so wird dieses Rauschen durch die Differenziation weiter verstärkt und wieder in den Kreis hineingegeben. Dadurch wird der Aktuator stärker belastet. Macht der Regler insbesondere sehr hohe Ausschläge als Folge von schnellen Änderungen des Sollwertes, dann kann es sein, dass das Stellglied oder der Aktuator diese nicht umsetzen kann - die Wirkung des D-Anteils würde dann durch die Begrenzung verpuffen, und das Einschwingverhalten wäre nicht wie berechnet, sondern meist langsamer. Dies gilt aber nur für große Sprünge. Bei den normalen kleinen Regelvorgängen zum Ausgleich von Störeinflüssen wirkt der D-Anteil wie beabsichtigt.&lt;br /&gt;
&lt;br /&gt;
[[File:pdregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PD-Regler:'''&lt;br /&gt;
 y = Kp * e + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
Mit der neuesten Regelabweichung '''e''' und der vorhergehenden '''ealt''' wird der D-Anteil berechnet. Die Differenziation erfolgt damit angenähert durch Bildung des Differenzquotienten (e - ealt)/Ta.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PID-Regler===&lt;br /&gt;
Der PID Regler ist der universellste der klassischen Regler und vereinigt die guten Eigenschaften der anderen Regler. Zur Beschreibung der Eigenschaften des P-, I- und D-Anteils siehe die anderen Reglertypen. Der PID-geregelte Kreis ist genau und sehr schnell. In den meisten Anwendungen kommt deshalb der PID-Regler zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
[[File:pidregler.gif]]&lt;br /&gt;
&lt;br /&gt;
'''Software PID-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Alternative PID-Reglerstruktur:'''&lt;br /&gt;
&lt;br /&gt;
Es gibt 2 Darstellungsmöglichkeiten, die inhaltlich identisch sind. In der analogen Regeltechnik ist noch die Darstellung mit der Nachstellzeit '''Tn''' und der Vorhaltezeit '''Tv''' üblich. Die Umrechnung zwischen den beiden Strukturen ist mit den angegebenen Formeln möglich.&lt;br /&gt;
&lt;br /&gt;
[[Bild:PIDstruktur.gif]]&lt;br /&gt;
&lt;br /&gt;
==Vergleich der Reglertypen==&lt;br /&gt;
In der folgenden Abbildung ist der Vergleich von P-, I-, PI-, PD- und PID-Regler in einem Regelkreis mit PT2-Glied als Regelstrecke dargestellt. Es ist deutlich zu sehen, dass die Regler ohne I-Anteil (P und PD) eine bleibende Regelabweichung aufweisen. Erst die Regler mit I-Anteil können auf den Endwert von 1 ausregeln. Beim reinen I-Regler geht das so langsam, dass es gar nicht mehr auf dem Diagramm zu sehen ist. Der Hauptzweck eines I-Anteils ist also die Vermeidung bleibender Regelabweichungen. Daher ist ein&lt;br /&gt;
I-Anteil normalerweise nicht nötig, wenn die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
Ausnahme: Es wird ein doppelter I-Anteil zur Vermeidung von Schleppfehlern benötigt.&lt;br /&gt;
&lt;br /&gt;
Die schnellsten Regler sind die mit einem D-Anteil (PD und PID). Der D-Anteil kommt deshalb hauptsächlich zum Einsatz, wenn schnelle Dynamik gefragt ist oder die Strecke selbst schon instabil ist. Voraussetzung für die Schnelligkeit ist allerdings, dass keine Begrenzung im Stellglied oder Aktuator auftritt. In der Praxis ist eine Begrenzung meistens nicht zu vermeiden, deshalb gilt die Sprungantwort in der Praxis nur für kleine Sprünge.&lt;br /&gt;
&lt;br /&gt;
Die Regler ohne D-Anteil, aber mit P-Anteil (P und PI) sind mittelschnell. Für einfache Regelaufgaben reicht auch oft schon ein reiner P-Regler aus, wenn die bleibende Regelabweichung vernachlässigt werden kann oder weil die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/vergleich.gif&lt;br /&gt;
&lt;br /&gt;
Aus diesem Vergleich wird klar, warum der PID-Regler so beliebt ist, er vereinigt die Vorzüge aller anderen Regler.&lt;br /&gt;
&lt;br /&gt;
==Digitaler Regler==&lt;br /&gt;
Durch die Einführung leistungsfähiger und preiswerter Mikroprozessoren hat sich der digitale Regler mehr und mehr durchgesetzt. Im Gegensatz zum analogen Regler werden die Signale nicht mehr analog mit Operationsverstärker verarbeitet, sondern mit einem Mikroprozessor errechnet. Bevor das Signal vom Mikroprozessor bearbeitet werden kann, muss zunächst das Eingangssignal (Istwert) mit einem Analog-Digital-Umsetzer (ADU) digitalisiert werden, d.h. in einen Zahlenwert umgewandelt werden. Das vom digitalen Regler errechnete Ausgangssignal (Stellgröße) wird wiederum zur Ansteuerung des Stellglieds mit einem Digital-Analog-Umsetzer (DAU) in ein analoges Signal gewandelt. Funktionell unterscheiden sich analoger und digitaler Regler jedoch nicht wesentlich, es müssen nur die Schnittstellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
[[File:digreg.gif|right|framed|Digitaler Regler (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Da die Wandlungen und das Regelprogramm eine gewisse Zeit beanspruchen, vergeht pro Durchlauf die sogenannte Takt- oder Abtastzeit. Diese Zeit wirkt sich im Regelkreis wie ein Totzeitglied mit der halben Abtastzeit als Totzeit aus. Das verursacht eine zusätzliche Phasenverschiebung, was sich ungünstig auf die Stabilität des Regelkreises auswirken kann. Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der digitale Regler kann dann wie ein analoger dimensioniert werden. Ist die Abtastzeit größer, kann sie nicht mehr vernachlässigt werden, dann muss sie auch beim Reglerentwurf berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
'''Vorteile digitaler Regler:'''&lt;br /&gt;
* Die Verarbeitung erfolgt driftfrei.&lt;br /&gt;
* Es lassen sich nichtlineare Kennlinien, intelligentes Verhalten oder adaptive Regelung leichter realisieren.&lt;br /&gt;
* Der Regler kann bei Bedarf per Software neu konfiguriert und parametriert werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Digitale Realisierung am Beispiel des PID-Algorithmus'''&lt;br /&gt;
&lt;br /&gt;
Ausgehend von der Differentialgleichung für kontinuierliche Systeme wird die Differenzengleichung für zeitdiskrete Systeme erstellt. Daraus folgt dann der Stellungsalgorithmus in allgemeiner Form.&lt;br /&gt;
&lt;br /&gt;
Ta = Abtastzeit; k = Nummer der Abtastung&lt;br /&gt;
&lt;br /&gt;
Kp = Proportionalbeiwert; Ki = Integrierbeiwert; Kd = Differenzierbeiwert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- http://www.roboternetz.de/wiki/uploads/Main/pidformel.gif --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differentialgleichung für den kontinuierlichen PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y(t) \;=\;  Kp \!\cdot\! e(t) &lt;br /&gt;
          + Ki \int_0^t e(\tau) \, d\tau &lt;br /&gt;
          + Kd \, \frac{de(t)}{dt}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differenzengleichung für den zeitdiskreten PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  Kp \!\cdot\! e_k&lt;br /&gt;
          + Ki \!\cdot\! Ta \sum_{i=0}^k e_i&lt;br /&gt;
          + \frac{Kd}{Ta}\, ( e_k - e_{k-1} )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''PID Stellungs-Algorithmus:&lt;br /&gt;
:''' &amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  y_{k-1} &lt;br /&gt;
          + q_0 \!\cdot\! e_k&lt;br /&gt;
          + q_1 \!\cdot\! e_{k-1}&lt;br /&gt;
          + q_2 \!\cdot\! e_{k-2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den Parametern:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
q_0 \,=\, Kp + Ki \!\cdot\! Ta + \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_1 \,=\, -Kp  - 2 \, \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_2 \,=\, \frac{Kd}{Ta}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Umsetzung in Code nach der Differenzengleichung:'''&lt;br /&gt;
&lt;br /&gt;
Im Code wurden einige Variablen umbenannt, da die Indexschreibweise nicht möglich ist.&lt;br /&gt;
&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, esum ist die Summenbildung&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird man die Ausdrücke Ki*Ta und Kd/Ta vorab berechnen und mit Ersatzvariablen in die Reglergleichung einsetzen. Der Verständlichkeit halber wurde es hier im Code belassen. Des weiteren kann eine Begrenzung von esum notwendig werden, um einen Variablenüberlauf oder Windup-Effekt zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Der nachfolgende Code wird im Rhythmus der Abtastzeit Ta immer wieder aufgerufen.&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 esum = esum + e;				//Integration I-Anteil&lt;br /&gt;
 y = Kp*e + Ki*Ta*esum + Kd/Ta*(e – ealt);	//Reglergleichung&lt;br /&gt;
 ealt = e;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''Alternative Umsetzung in Code nach dem Stellungsalgorithmus:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, yalt entspricht y&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, ealt2 entspricht e&amp;lt;sub&amp;gt;k-2&amp;lt;/sub&amp;gt;&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 y = yalt + q0*e + q1*ealt + q2*ealt2;		//Reglergleichung&lt;br /&gt;
 ealt2 = ealt;&lt;br /&gt;
 ealt = e;&lt;br /&gt;
 yalt = y;&lt;br /&gt;
&lt;br /&gt;
==Dimensionierung des Reglers==&lt;br /&gt;
Die Auswahl des Reglertyps ist heutzutage bei den digitalen Reglern nicht mehr so kritisch, da der Mehraufwand in Software für einen PID-Regler gegenüber einfacheren Typen kaum zu Buche schlägt. Im Prinzip ist man deshalb mit einem PID-Regler fast immer auf der richtigen Seite, mit einer Ausnahme, bei einer Strecke mit reiner Totzeit. Die folgende Tabelle gibt eine Hilfestellung zur Auswahl des Reglers. &lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ '''Geeignete Reglertypen für die unterschiedlichen Regelstrecken'''&lt;br /&gt;
 |rowspan=2 |'''Strecke'''&lt;br /&gt;
 |colspan=4 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Regler'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PD'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |reine Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |-&lt;br /&gt;
 |1.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |2.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |höhere Ordnung&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |I-Glied und Verzögerung&lt;br /&gt;
 |geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Nachdem man einen geeigneten Reglertyp ausgewählt hat, stellt sich noch die Frage, wie man die Reglerparameter Kp, Ki, und Kd optimiert. Im Laufe der Zeit wurden viele Methoden zur Dimensionierung der Reglerparameter entwickelt, aber es können hier nicht alle aufgelistet werden. Diese Aufzählung beschränkt sich auf die einfacheren und gängigen Methoden der Parametrierung.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung durch Probieren (Empirisches Einstellen)===&lt;br /&gt;
&lt;br /&gt;
====Methode 1====&lt;br /&gt;
Diese Methode ist geeignet um einfache Systeme zu dimensionieren, insbesondere wenn man bereits Erfahrung mit ähnlichen Regelkreisen hat. Man fängt mit einer unkritischen Einstellung (Kp klein, Ki = 0, Kd = 0) an und erhöht langsam die Verstärkung Kp, bis die Dämpfung schlecht wird. Falls eine Schwingneigung auftritt, muss die Verstärkung wieder etwas zurück genommen werden. Dann nimmt man allmählich den Integralanteil hinzu, erhöht ihn in Schritten und probiert solange herum, bis das Ergebnis einigermaßen passt. Bei Bedarf kann noch ein D-Anteil (PID-Struktur) probiert werden. Wenn dabei die Regelung stabiler wird, kann noch mal Kp und Ki erhöht werden, bis man endgültig zufrieden ist. &lt;br /&gt;
&lt;br /&gt;
====Methode 2====&lt;br /&gt;
Alle Anteile erstmal auf 0. Dann erhöht man Kp so lange bis das System deutlich schwingt. Danach wird der Kd so lange erhöht bis das System nicht mehr schwingt. Anschliessend kann noch ein kleiner Ki Anteil hinzugegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es dürfte klar sein, dass so eine Optimierung im Blindflug nicht immer das Optimum ergibt, aber es ist eine gängige praktische Methode zur Ermittlung der Reglerparameter. Besser sieht es aus, wenn in einer Simulation empirisch optimiert wird. Zusätzliche Informationen über die Stabilität erlauben hierbei eine gezieltere Optimierung. Zudem ist das Probieren im Simulator gefahrlos möglich, was in der Realität nicht immer der Fall ist. Geeignete Programme zur Simulation sind [[Regelungstechnik#Hilfsprogramme_zur_Analyse_und_Optimierung| hier]] vorgestellt. Allerdings muss für eine Simulation die Regelstrecke bekannt sein. Ist das nicht der Fall, so bleibt nur das einfache Probieren oder das Einstellen nach der Schwingungsmethode wie im folgenden beschrieben.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung nach Einstellregeln===&lt;br /&gt;
Die Dimensionierung nach Rezept ist eine praktische Methode ohne viel Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die bekanntesten Einstellregeln sind von Ziegler/Nichols und von Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer Einstelltabellen, auf die hier aber verzichtet wird, das würde den Rahmen dieses Artikels sprengen. An der Vielzahl kann man schon ersehen, dass es kein universell gültiges Rezept gibt und mit diesen Tabellen nicht unbedingt das Optimum erreicht wird, eine Nachoptimierung kann nötig sein.&lt;br /&gt;
&lt;br /&gt;
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.&lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Schwingungsmethode:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter so verstellt, dass die Stabilitätsgrenze erreicht wird und der Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische Schwingungen ausführt. Aus der so gefundenen Einstellung können die Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden anrichtet und die überhaupt instabil gemacht werden können. Die Vorgehensweise ist folgende:&lt;br /&gt;
# Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0&lt;br /&gt;
# Die Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen ausführt.&lt;br /&gt;
# Der dabei eingestellte Wert Kp wird als Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; bezeichnet. &lt;br /&gt;
# Die Periodendauer der sich einstellenden Dauerschwingung T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; wird gemessen.&lt;br /&gt;
# Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.45*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;0.85*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.5*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.12*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken angewendet werden kann, die auch zum Schwingen gebracht werden können. &lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Sprungantwort:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Diese Methode der Parameterbestimmung beruht auf der Aufnahme der Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die nicht zum Schwingen gebracht werden können. Der Regelkreis muss allerdings geöffnet werden.&lt;br /&gt;
Vorgehensweise: Es wird die Sprungantwort aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu und die Ausgleichszeit Tg ermittelt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tu_Tg.gif]]&lt;br /&gt;
&lt;br /&gt;
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Ziegler/Nichols:&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.9/Ks*Tg/Tu&lt;br /&gt;
 |3.3*Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1.2/Ks*Tg/Tu&lt;br /&gt;
 |2*Tu&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Chien/Hrones/Reswick&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.3/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.35/Ks*Tg/Tu&lt;br /&gt;
 |1.2*Tg&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6/Ks*Tg/Tu&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Tg&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| cellpadding=4 width=420&lt;br /&gt;
 |Die Parameter Tn und Tv sind aus der analogen Regelungstechnik und sind dort sehr geläufig. Die Umrechnung in die Parameter Ki und Kd erfolgt mit nebenstehenden Formeln. Siehe auch [[Regelungstechnik#PID-Regler| PID-Regler]]&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit dem Bodediagramm===&lt;br /&gt;
Ein Bode-Diagramm ist die grafische Darstellung des Frequenzganges. Es werden der Betrag der Übertragungsfunktion (Amplitudengang) und der Verlauf des Phasenwinkels (Phasengang) als Funktion der Frequenz aufgetragen. Die Frequenzachse und die Amplitudenachse werden logarithmisch dargestellt. Die logarithmische Darstellung hat den Vorteil, dass eine Multiplikation auf eine einfache Addition zurückgeführt wird. Somit wird eine Hintereinanderschaltung von Systemen im Blockschaltbild zu einer einfachen Addition im Bodediagramm.&lt;br /&gt;
&lt;br /&gt;
Das Zeitverhalten des rückgekoppelten Regelkreises hängt entscheidend vom Verlauf&lt;br /&gt;
des Frequenzganges der offenen Regelschleife in der Umgebung des Durchtretens durch&lt;br /&gt;
die 0dB-Achse ab. In der Regelungstechnik wird daher der offene Regelkreis im Bode-Diagramm aufgetragen. Das erlaubt einen schnellen Überblick über Stabilität und möglichen Reserven zur Optimierung. Ein Kriterium für die Stabilität der Schleife ist der Phasenrand und der Amplitudenrand. Der Phasenrand ist der Abstand (Phasenreserve) zur -180°-Linie bei der Durchtrittsfrequenz. Die Durchtrittsfrequenz ist diejenige Frequenz, bei der der Amplitudengang durch die 0dB-Linie geht. Siehe auch folgendes Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Phasenrand.gif]]&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |'''Regel:''' Eine geschlossene Regelschleife arbeitet genau dann stabil, wenn der Phasenrand positiv ist.&lt;br /&gt;
 |}&lt;br /&gt;
Wird diese Bedingung verletzt, so wird in diesem Frequenzbereich die im Rückführzweig der Regelung eingebrachte Gegenkopplung zu einer Mitkopplung und das System kann schwingen.&lt;br /&gt;
&lt;br /&gt;
'''Beim Reglerentwurf sind folgende Punkte zu beachten:'''&lt;br /&gt;
* Der Phasenrand muss positiv sein. Der geschlossene Regelkreis kann sonst instabil sein. &lt;br /&gt;
* Je größer der Phasenrand ist, desto größer ist die Stabilitätsreserve des Regelkreises und desto höher ist die Dämpfung des Regelkreises. Üblich sind Werte von 40°...70° für gutes Führungsverhalten und 20°...50° für gutes Störverhalten.&lt;br /&gt;
* Die Durchtrittsfrequenz ist ein Maß für die Schnelligkeit des Regelkreises, je höher, desto schneller ist die Reaktion auf Änderungen der Führungsgröße oder Störungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel zur Dimensionierung mit dem Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bode1.gif]]&lt;br /&gt;
&lt;br /&gt;
Die Strecke ist rot dargestellt und besteht in dem Beispiel aus einem nicht schwingfähigem PT2-Glied. Man sucht sich den Punkt, wo die Strecke für sich alleine noch ausreichend Phasenreserve hat, z.B. 70°. In dem Beispiel also die Frequenz, bei der die Strecke -110° Phasendrehung aufweist. Das ist etwa bei 15Hz. Da hat die Strecke ungefähr eine Dämpfung von 25dB. Wenn man nun diese Dämpfung durch eine Verstärkung von 25dB kompensiert, dann wird dieser Punkt zur Durchtrittsfrequenz. D.h. man wählt den P-Anteil des Reglers Kp=18, denn 25dB entspricht ungefähr dem Faktor 18. Um die Regelabweichung zu minimieren, wird noch ein I-Anteil hinzugefügt. Üblicherweise wählt man für die Grenzfrequenz des PI-Reglers die Grenzfrequenz des dominierenden Streckenteils, in dem Beispiel ca. 1.4Hz. Damit ergibt sich ein I-Anteil von 170. Im Bode-Diagramm ist der PI-Regler als schwarze Kurve eingezeichnet. Die Addition der Strecke und des Reglers im Bode-Diagramm führt dann zum Frequenzgang des offenen Regelkreises (blaue Kurve). Die resultierende Durchtrittsfrequenz ist wie gewählt bei etwa 15Hz. Der Phasenrand hat sich durch den I-Anteil im Regler auf ca. 60° reduziert, ist aber noch ausreichend. Das Einschwingen des geschlossenen Regelkreises für diese Dimensionierung sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort3.gif]]&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf könnte noch ein D-Anteil (PID-Regler) hinzugenommen werden, das würde die Phase anheben und man könnte dadurch die Durchtrittsfrequenz weiter nach oben schieben. In der Praxis wird dies allerdings wegen der wahrscheinlichen Begrenzung des Stellglieds kein schnelleres Einschwingen mehr bringen. &lt;br /&gt;
&lt;br /&gt;
Begrenzungen oder Nichtlinearitäten werden bei der Dimensionierung mit dem Bode-Diagramm nicht berücksichtigt. Das ist ein Nachteil dieser Methode. Eventuell muss deshalb noch einmal im Zeitbereich nachoptimiert werden.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit der Ortskurve===&lt;br /&gt;
Eine Alternative zur Dimensionierung mit dem Bodediagramm stellt die Methode über die Ortskurve des offenen Regelkreises dar.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Verfahren ist schnell auf einem Blick ersichtlich ob der Regelkreis stabil ist.&lt;br /&gt;
&lt;br /&gt;
Liegt der Punkt -1 auf der Realteilachse links von der Ortskurve in Richtung steigendem Omega so ist der Regelkreis stabil.&lt;br /&gt;
Der Abstand zu der kritischen Kreisfrequenz Omega Krit von der Imaginärteilachse ist die Verstärkung Vr mit diesem Wert lässt sich der Amplitudenrand ermitteln. &lt;br /&gt;
Dazu wird folgende Formel verwendet: Ar = 20 lg (1/Vr) in dB&lt;br /&gt;
&lt;br /&gt;
Die Durchtrittskreisfrequenz Omega D ist an dem Punkt, wo der Betrag aus Realteil und Imaginärteil 1 ergibt. Wenn man weiß, wo die Durchtrittskreisfrequenz ist, dann kann man den Phasenrand bestimmen.&lt;br /&gt;
Dies ist der Winkel zwischen der -180° Linie zu Omega D.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ortskurve.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Hilfsprogramme zur Analyse und Optimierung==&lt;br /&gt;
Die Analyse und Optimierung von Regelkreisen wird wesentlich erleichtert durch die Zuhilfenahme von Programmen. Es erspart einem eine komplizierte Rechnerei von Hand oder umfangreiche Testläufe. Stellvertretend für all die verfügbaren Programme werden hier zwei Freeware-Programme vorgestellt, die dafür gut geeignet sind. Die Beschreibung hier ersetzt aber keine Tutorials, es wird nur die Anwendung für die Regelungstechnik beschrieben. &lt;br /&gt;
&lt;br /&gt;
===Scilab/Scicos===&lt;br /&gt;
Scilab ist ein wissenschaftlich-technisches Softwarepaket für numerische Berechnungen. Scicos ist eine Erweiterung dazu, die eine blockorientierte und modellbasierte Simulation und Analyse von dynamischen Systemen bietet. Dieses Softwarepaket kann von der [http://www.scilab.org/ Scilab Homepage] herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
====Scilab====&lt;br /&gt;
Mit Scilab ist es sehr einfach ein Bode-Diagramm zu zeichnen, es bedarf nur 3 Zeilen Code.&lt;br /&gt;
 s=poly(0,'s');&lt;br /&gt;
 G=syslin('c',0.72/(0.11*s+1));&lt;br /&gt;
 bode(G)&lt;br /&gt;
Die 1.Zeile '''s=poly(0,'s');''' legt die Variable s als Polynomvariable fest. Dies braucht in einer Sitzung nur einmal gemacht zu werden. Die 2.Zeile '''G=syslin('c',0.72/(0.11*s+1));''' definiert ein lineares System mit der Übertragungsfunktion 0.72/(0.11s+1). Die 3.Zeile '''bode(G)''' zeichnet das Bode-Diagramm des zuvor mit syslin definierten Systems G. Zu beachten ist, dass Scilab auf der x-Achse im Bode-Diagramm die Frequenz in Hertz und nicht wie üblich die Kreisfrequenz darstellt. Anstelle des Bode-Diagramms kann auch die Sprungantwort gezeichnet werden. Dies geschieht mit folgenden Befehlen:&lt;br /&gt;
 xbasc();&lt;br /&gt;
 t=[0:0.001:2];&lt;br /&gt;
 y=csim('step',t,G);&lt;br /&gt;
 plot2d(t,y)&lt;br /&gt;
'''xbasc()''' löscht den letzten Plot mit dem Bode-Diagramm und mit '''t=[0:0.001:2]''' wird ein Vektor t mit den angegebenen Zeiten im Intervall von 1ms definiert. Die Zeile '''y=csim('step',t,G)''' berechnet die Sprungantwort des zuvor mit syslin definierten Systems G und speichert sie in y ab. Das Ergebnis wird dann mit '''plot2d(t,y)''' dargestellt. Bei Bedarf können noch Gitternetzlinien mit dem Befehl '''xgrid()''' hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Ergänzend hier noch ein Scilab-Skript, welches recht hilfreich bei der Dimensionierung mit dem Bode-Diagramm ist. Den nachfolgenden Code einfach in das SciPad-Fenster (Editor von Scilab) kopieren und starten. Es werden 2 Grafikfenster angezeigt, eines mit dem Bode-Diagramm und ein zweites mit der Sprungantwort. Man kann im Skript die Streckencharakteristik anpassen und verschiedene Reglerparameter ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ks=0.72;                            // Verstärkung der Strecke&lt;br /&gt;
T1=0.11;                            // Zeitkonstante 1&lt;br /&gt;
T2=0.005;                           // Zeitkonstante 2&lt;br /&gt;
Kp=18;                              // Proportionalbeiwert&lt;br /&gt;
Ki=170;                             // Integralbeiwert&lt;br /&gt;
Kd=0;                               // Differenzialbeiwert&lt;br /&gt;
 &lt;br /&gt;
s=poly(0,'s');                      // definiert s als Polynomvariable&lt;br /&gt;
P=(T1*s+1)*(T2*s+1);                // Streckencharakteristik&lt;br /&gt;
Gs=syslin('c',Ks,P)                 // Übertragungsfunktion der Strecke&lt;br /&gt;
&lt;br /&gt;
RZ=poly([Ki Kp Kd],'s','coeff')     // Zählerpolynom des Reglers&lt;br /&gt;
RN=poly([0 1],'s','coeff')          // Nennerpolynom des Reglers&lt;br /&gt;
Gr=syslin('c',RZ,RN)                // Übertragungsfunktion des Reglers&lt;br /&gt;
&lt;br /&gt;
G=Gr*Gs                             // Übertragungsfunktion gesamt&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,0);&lt;br /&gt;
xbasc(0);&lt;br /&gt;
bode([Gr;G;Gs],0.1,100,['Regler';'gesamt';'Strecke'])&lt;br /&gt;
&lt;br /&gt;
Gcl=G/(G+1)                         // geschlossene Regelschleife&lt;br /&gt;
t=0:0.001:0.2;&lt;br /&gt;
y=csim('step',t,Gcl);               // berechnet Sprungantwort&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,1);&lt;br /&gt;
xbasc(1);&lt;br /&gt;
plot2d(t,y,2);&lt;br /&gt;
xgrid();&lt;br /&gt;
xtitle(&amp;quot;Sprungantwort&amp;quot;,&amp;quot;sec&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Scicos====&lt;br /&gt;
Eine weitere Möglichkeit zur Simulation im Zeitbereich bietet Scicos. Die Modellierung geschieht mit einem grafischen Editor, in dem Blöcke mit vordefinierten oder selbstgemachten Funktionen miteinander verbunden werden. Ein einfaches Modell eines Regelkreises mit PID-Regler sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_anaReg.gif]]&lt;br /&gt;
&lt;br /&gt;
Der PID-Regler ist mit seinen 3 Zweigen (P, I und D) dargestellt. In den Verstärkerblöcken kann durch Ändern der Reglerparameter (KP, KI und KD) der Regler optimiert werden. Die Strecke ist in diesem Beispiel nur ein einzelner Block, in dem die Übertragungsfunktion eingegeben wird. Man kann die Strecke auch detaillierter mit einzelnen Funktionsblöcken darstellen. Ein Beispiel eines komplexen Blockschaltbilds für einen balancierenden Bot ist unter diesem [http://www.roboternetz.de/phpBB2/download.php?id=5082 Link] zu finden.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil der Simulation mit Scicos ist die Möglichkeit Nichtlinearitäten zu berücksichtigen und die Kombination von kontinuierlichen und diskreten Funktionen. Das heißt, man kann einen digitalen Regler mit seinen diskreten Schritten und eine analoge Strecke, als kontinuierliche Funktion eingegeben, zusammen simulieren. Scicos bietet sogar einen 'Scifunc'-Block, mit dem Rechenschritte des digitalen Reglers nachgebildet werden können. Damit wird sowohl das dynamische Verhalten, verursacht durch die Abtastzeit Ta, als auch die etwas unterschiedliche Dynamik durch die digitale Ausführung eines I- und D-Anteils richtig simuliert. Ein Beispiel für den Einsatz des Scifunc-Blocks ist in folgendem Blockschaltbild zu sehen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_digReg.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel: [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlregelung]] mit digitalem Regler&lt;br /&gt;
&lt;br /&gt;
Die globalen Variablen für die Reglerparameter und die Abtastzeit werden unter dem Menüpunkt „Edit - Context“ abgelegt.&lt;br /&gt;
 Kp=18;&lt;br /&gt;
 Ki=60;&lt;br /&gt;
 Ta=0.01;&lt;br /&gt;
In den Taktgeber für den digitalen Regler wird als Clock-Periode die Abtastzeit Ta eingetragen. In das Dialogfenster zum Scifunc-Block wird folgender Code zur Simulation des digitalen PI-Reglers eingetragen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z=z+Ki*Ta*u1&lt;br /&gt;
if z&amp;gt;5 then&lt;br /&gt;
z=5;&lt;br /&gt;
end&lt;br /&gt;
y1=Kp*u1+z&lt;br /&gt;
if y1&amp;gt;5 then&lt;br /&gt;
y1=5;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
z entspricht der Variable esum vom Beispiel des [[Regelungstechnik#Realisierung_mit_digitalem_Regler| digitalen Drehzahlreglers]]; u1 ist die Eingangsvariable und y1 die Ausgangsvariable des Scifunc-Blocks.&lt;br /&gt;
In den Block für die Strecke wird die Übertragungsfunktion eingetragen. Als Zähler die Verstärkung Ks, also 0.72. Im Nenner das Polynom (1+0.11*s) für die Charakteristik der Strecke. Mit ‚Simulate – Run’ wird die Simulation gestartet. Als Ergebnis sollte das Einschwingen der Stellgröße (schwarz) und der Regelgröße (grün), wie in folgender Abbildung erscheinen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort_DZR.png]]&lt;br /&gt;
&lt;br /&gt;
Man kann nun mit den Reglerparametern und verschiedenen Abtastzeiten spielen, um zu sehen wie sich die Änderungen auswirken. Zum Beispiel wird bei einer Verdopplung der Abtastzeit der Regelkreis bereits instabil.&lt;br /&gt;
&lt;br /&gt;
Diese Beispiele sind nur ein kurzer Auszug von den Möglichkeiten mit Scilab/Scicos für den Einsatz in der Regelungstechnik. Darüber hinaus ist es auch sehr gut geeignet bei anderen Optimierungsverfahren wie z.B. beim WOK-Verfahren (Wurzelortskurven) oder zur Analyse und Optimierung von modernen Reglern wie z.B. Zustandsregler und Kalmanfilter.&lt;br /&gt;
&lt;br /&gt;
===LTspice/SwitcherCad III===&lt;br /&gt;
Dieses Programm ist ein SPICE-Derivat von der Firma Linear Technology und ist unter den 2 Namen LTspice und SwitcherCad III bekannt. Der Einfachheit halber wird für die weitere Beschreibung hier nur der Name LTspice verwendet. Das Programm ist Freeware und kann unter diesem Link herunter geladen werden. http://ltspice.linear.com/software/LTspiceIV.exe&lt;br /&gt;
&lt;br /&gt;
LTspice ist ein Simulationsprogramm zur Analyse von elektronischen Schaltungen. Mit LTspice kann sowohl im Zeitbereich als auch im Frequenzbereich analysiert werden und bietet sich dadurch mit den entsprechenden Modellen auch für den Einsatz in der Regelungstechnik an. Wer sich bereits mit SPICE-Programmen auskennt, für den sollte es auch in der Regelungstechnik die 1.Wahl sein. &lt;br /&gt;
&lt;br /&gt;
Der Vorteil von LTspice ist die Möglichkeit einer sehr detaillierten Analyse, vorausgesetzt die Modelle sind auch so detailliert nachgebildet. Insbesondere für analoge Regler, wo die elektrische Schaltung direkt umgesetzt werden kann, empfiehlt sich der Einsatz von LTspice. Der Nachteil ist, LTspice ist nicht auf regeltechnische Belange ausgelegt worden und spezifische Symbole für die Regelungstechnik müssen selbst erstellt werden. Einige selbst erstellte Symbole für dynamische Grundelemente in LTspice sind hier abgebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTSpiceSymb.png]]&lt;br /&gt;
&lt;br /&gt;
Die 3 Symbole können [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=285 hier] heruntergeladen werden. Weitere Symbole können anhand dieser Beispiele sehr leicht selbst erstellt werden. Ein P-Glied kann durch eine spannungsgesteuerte Spannungsquelle (E-Source) oder Operationsverstärker mit einstellbarer Verstärkung dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
'''Analyse im Zeitbereich'''&lt;br /&gt;
&lt;br /&gt;
Das Beispiel des [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlreglers]] mit analogem Regler wird hier mit LTspice simuliert. Das Schaltbild des Regelkreises zeigt nachfolgende Abbildung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_TRAN.png]]&lt;br /&gt;
&lt;br /&gt;
Der Vergleicher (U1) und der analoge PI-Regler (U2) sind so dargestellt, wie es auch in Wirklichkeit ausgeführt werden kann. Da der PI-Regler in der Schaltung bereits invertiert, wurden die Eingänge am Vergleicher vertauscht, damit die Polarität wieder stimmt. Der Rest des Regelkreises wurde stark vereinfacht, kann aber nach Bedarf auch ausführlicher dargestellt werden. Das PT1-Glied U3 simuliert die Strecke des Regelkreises und der Verstärker U4 dient nur zur Umrechnung auf die Drehzahl. Zur Simulation im Zeitbereich wird auf den Führungswert w mit der Spannungsquelle V1 ein Sprung gegeben. In der Reglerschaltung wurde bewusst ein Operationsverstärker mit Versorgungsspannung gewählt, damit auch der Einfluss einer Begrenzung mit simuliert wird. Die Zeitbereichsanalyse wird durch den LTspicebefehl .TRAN erreicht. Die Sprungantwort (Tachospannung) bei diesem Regelkreis sieht dann folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tacho2.png]]&lt;br /&gt;
&lt;br /&gt;
Durch Ändern der Bauelemente R5, R6 und C1 kann man den Regler optimieren. Eine Umrechnung auf die Reglerparameter Kp und Ki ist mit folgenden Formeln möglich, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1)&lt;br /&gt;
&lt;br /&gt;
Mit einem Mausklick auf den entsprechenden Knoten in der Schaltung können noch weitere Signale, wie z.B. die Stellgröße y angezeigt werden. Durch Verändern der Versorgungsspannung V3, V4 kann man sich auch die Auswirkung der Begrenzung ansehen. &lt;br /&gt;
&lt;br /&gt;
'''Analyse im Frequenzbereich'''&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung des Bode-Diagramms der offenen Regelschleife in LTspice muss ein Trick angewendet werden, denn durch das Auftrennen der Regelschleife würde der Arbeitspunkt verloren gehen und dadurch die offene Schleife ohne Gegenkopplung an den Anschlag fahren.&lt;br /&gt;
&lt;br /&gt;
Mit einer zusätzlichen Spannungsquelle in der Schleife kann man dieses Problem umgehen. Die Schleife bleibt für den Erhalt des Arbeitspunktes weiterhin geschlossen und man kann trotzdem die Verstärkung der offenen Schleife durch das Verhältnis der Spannung vor und hinter der Spannungsquelle bestimmen. Das erweiterte Blockschaltbild sieht folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_AC.png]]&lt;br /&gt;
&lt;br /&gt;
V2 ist die zusätzliche Spannungsquelle für die AC-Analyse. Die Spannungsquelle V1 wird von Pulsform auf Gleichspannung umgestellt. Sie wird so gewählt, dass sich der gewünschte Arbeitspunkt einstellt. Durch den LTspicebefehl .AC wird die Analyse im Frequenzbereich veranlasst. Um das Bode-Diagramm des offenen Regelkreises darzustellen, wird als Kurve nicht ein einzelner Knoten ausgewählt, sondern das Verhältnis der Spannung vom Ende zum Anfang des Regelkreises, in unserem Beispiel also V(tacho)/V(x). Zur Anzeige kommt dann das Bode-Diagramm (grüne Kurve) der offenen Schleife, wie in der folgenden Abbildung zu sehen. Für den Amplitudengang (durchgezogene Linien) gilt die linke Skala in dB, für den Phasengang (gestrichelte Linien) die rechte Skala in Grad.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_Bode.png]]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist noch das Bode-Diagramm der Strecke (rote Kurve) zu sehen. Dies ist durch einfaches Hinzufügen einer weiteren Kurve mit dem Ausdruck V(tacho)/V(y) durchgeführt worden. &lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zur üblichen Darstellung des Bode-Diagramms eines offenen Regelkreises, beinhaltet das mit LTspice erstellte Bode-Diagramm auch die -180 Grad Phasendrehung der Gegenkopplung. Der Phasenrand ist deshalb nicht auf -180 Grad sondern auf 0 Grad zu beziehen. In unserem Beispiel ist der Phasenrand etwa 90 Grad, also ein sehr stabiler Regelkreis. Zu beachten ist, dass die Frequenzachse des Bode-Diagramms wie auch schon bei Scilab in der Einheit Hertz anstatt wie üblich in der Kreisfrequenzeinheit rad/s dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
==Modellierung eines Motors/Antriebs==&lt;br /&gt;
[[Bild:ESB_Motor.png|thumb|320px|Ersatzschaltbild DC-Motor]]&lt;br /&gt;
Der Motor ist ein oft verwendeter Aktuator in der Robotik. Deshalb wird hier am Beispiel des Gleichstrommotors mit Permanentmagnet (Nebenschlussmotor) die Modellbildung gezeigt. Zur Modellierung gibt es mehrere Möglichkeiten. Je nachdem wie detailliert die Simulation sein soll, kann man sich ein Modell, von sehr einfach bis sehr detailliert, auswählen. Zwei Zeitkonstanten bestimmen die Dynamik eines Gleichstrommotors. Eine davon ist die mechanische Zeitkonstante, die ist meistens die dominierende Zeitkonstante und wird durch das Trägheitsmoment J des Rotors verursacht. Die zweite Zeitkonstante ist die elektrische Zeitkonstante, sie wird durch die Induktivität L bestimmt. Bei einfachen Regelungen kann in den meisten Fällen die elektrische Zeitkonstante vernachlässigt werden, damit reduziert sich das Modell auf ein einzelnes PT1-Glied.&lt;br /&gt;
&lt;br /&gt;
'''Definition: Motor und Antrieb'''&lt;br /&gt;
&lt;br /&gt;
Als '''Motor''' wird hier der Motor alleine verstanden. Die Ausgangsgröße ist die Winkelgeschwindigkeit w (Drehzahl).&lt;br /&gt;
 &lt;br /&gt;
Als '''Antrieb''' wird hier der komplette Antrieb eines Fahrzeugs verstanden, also Motor inklusive Getriebe und Masse des Fahrzeugs. Für die Dynamik ist nicht nur das Trägheitsmoment des Motors sondern auch die Masse des Fahrzeugs verantwortlich. Die Ausgangsgröße der Einheit „Antrieb“ ist die Geschwindigkeit v.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellten Modelle gelten sowohl für einen Motor als auch für einen kompletten Antrieb, wenn man die Elastizität und das Spiel des Getriebes vernachlässigt.&lt;br /&gt;
&lt;br /&gt;
===Einfaches Modell mit PT1-Glied===&lt;br /&gt;
Die einfachste Art einen Motor oder Antrieb zu simulieren, ist mit einem PT1-Glied als Modell. Das Simulationsprogramm [[Regelungstechnik#Scicos|Scicos]] bietet dazu einen Block zur Eingabe der Übertragungsfunktion (num(s)=Zähler, den(s)=Nenner der Übertragungsfunktion).&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G(s)=\frac{K}{1+Ts}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |Beispiel:&lt;br /&gt;
 num(s) = K = 0.72&lt;br /&gt;
 den(s) = 1 + Ts = 1 + 0.11s&lt;br /&gt;
 |[[Bild:Scicos_TF.png]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Wird nicht nur das Ausgangssignal, also die Geschwindigkeit oder Drehzahl in der Simulation benötigt, sondern auch die Beschleunigung, dann kann nachfolgendes Modell verwendet werden. Dieses Modell ist der Differentialgleichung eines PT1-Glieds nachempfunden und liefert das gleiche Ergebnis wie vorheriges Modell, bietet aber noch den Zugriff auf das Beschleunigungssignal.&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Differentialgleichung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;v'=\frac{K}{T}U-\frac{1}{T}v&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |&lt;br /&gt;
 v = Geschwindigkeit&lt;br /&gt;
 v’= Beschleunigung (Ableitung von v)&lt;br /&gt;
 K = Übertragungsmaß&lt;br /&gt;
 T = Zeitkonstante&lt;br /&gt;
 U = Eingangsgröße (z.B. Spannung)&lt;br /&gt;
 |[[Bild:Antrieb_PT1.png|thumb|Einfaches Modell eines Antriebs]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Die beiden Parameter K und T müssen ausgemessen werden, wenn sie nicht bekannt sind. Die Zeitkonstante T kann in einem Anlaufversuch ermittelt werden. Dazu wird auf den Motor ein Spannungssprung gegeben und die Sprungantwort am Ausgang nachgemessen. Bei einem Antrieb erspart diese Methode die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente (Motor, Getriebe, Fahrzeug). Bei der Ermittlung des Übertragungsmaß K ist zu beachten, dass sich möglicherweise der Motor durch starke Reibung erst ab einer bestimmten Spannung dreht. Hier ist die Steigung der Kennlinie mit delta&amp;amp;nbsp;v&amp;amp;nbsp;/&amp;amp;nbsp;delta&amp;amp;nbsp;U auszuwerten, wie im folgenden Bild zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_stat.png]]&lt;br /&gt;
&lt;br /&gt;
Die einfachen Modelle gelten nur für den linearen Teil der Kennlinie. Soll auch die Nichtlinearität durch Reibung modelliert werden, dann sind detailliertere Modelle, wie im Folgenden beschrieben, zu verwenden. Die Auswirkung einer Haftreibung ist auch in dem Geschwindigkeitsdiagramm durch die Hysterese in der Kennlinie zu sehen. Beim Hochfahren der Ansteuerspannung bewegt sich das Fahrzeug erst ab ca. 1.25V, während beim Herunterfahren der Ansteuerspannung das Fahrzeug noch bis 0.75V rollt und erst unter 0.75V stehen bleibt.&lt;br /&gt;
&lt;br /&gt;
===Detailliertes Modell===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Motor_Model.png|thumb|350px|Detailliertes Motormodell]]&lt;br /&gt;
Ein detailliertes Motormodell ist rechts in dem Bild zu sehen. Es hat auf der linken Seite den elektrischen Teil mit den Parametern R (Widerstand) und L (Induktivität) und auf der rechten Seite den mechanischen Teil mit den Blöcken Trägheitsmoment und Reibung. Der elektrische Teil liefert das Stromsignal i, welches mit der Motorkonstante Km in das Drehmoment M umgerechnet wird. Mit dem folgenden Summierglied kann über einen zusätzlichen Eingang auch ein extern angreifendes Lastmoment mit simuliert werden. Am Ausgang des mechanischen Teils steht die Winkelgeschwindigkeit w in der Einheit [rad/s] bzw. über den Umrechnungsfaktor 9.55 die Drehzahl in [Upm] zur Verfügung. Die Reibung wird in einem nichtlinearen Block mittels Lookup-Table simuliert. In der einschlägigen Literatur wird die Reibung meistens mit einem Dämpfungsfaktor (linear) simuliert, was einer viskosen Reibung entspricht. Das passt aber nicht so gut für Kleinmotoren, da überwiegt vor allem die trockene Reibung. Die trockene Reibung hat ein konstantes Bremsmoment wenn sich der Motor dreht (unabhängig von Drehzahl, Vorzeichen abhängig von Drehrichtung). So eine Funktion kann sehr einfach mit einer Lookup-Table realisiert werden. Die Lookup-Table kann auch dazu verwendet werden, Mischformen von trockener, viskoser und turbulenter Reibung und sogar noch Haftreibung in einem Block zu simulieren, wenn man will.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Herstellern, wie z.B. Faulhaber und Maxon, kann man die für das Modell nötigen Parameter im Datenblatt finden. Das Bremsmoment der Reibung berechnet sich aus dem Leerlaufstrom wie folgt: Bremsmoment&amp;amp;nbsp;=&amp;amp;nbsp;Motorkonstante&amp;amp;nbsp;*&amp;amp;nbsp;Leerlaufstrom &lt;br /&gt;
&lt;br /&gt;
Falls die Daten nicht verfügbar sind, muss man sie selbst ausmessen. Eine Hilfestellung zur Bestimmung der Motorkonstante und des Trägheitsmoments gibt es hier:&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=96750&amp;amp;highlight=#96750&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/viewtopic.php?t=12793&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_Modell.png|thumb|350px|Modell eines Antriebs]]&lt;br /&gt;
&lt;br /&gt;
Das detaillierte Motormodell kann auch für einen Antrieb verwendet werden, wenn man eine starre Kopplung zwischen Motor und Antriebsrad voraussetzt, also Elastizität und Spiel des Getriebes vernachlässigt. Anstelle der rotatorischen Kenngrößen (Drehmoment M, Trägheitsmoment J, Winkelgeschwindigkeit w) werden die translatorischen Kenngrößen (Kraft F, Masse m, Geschwindigkeit v) eingesetzt. Das Drehmoment wird mittels Getriebeübersetzung ü und Radius r des Antriebsrades in die entsprechende Vortriebskraft umgerechnet. Daraus ergibt sich die Kraftkonstante Kf, die für das Antriebsmodell verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Die Umrechnung ist: Kf = Km * ü/r&lt;br /&gt;
&lt;br /&gt;
Bei der Trägheitsmasse m muss neben der Masse des Fahrzeugs auch das Trägheitsmoment des Motors mit berücksichtigt werden. Die Umrechnung von Trägheitsmoment in eine äquivalente Masse = J * (ü/r)²&lt;br /&gt;
&lt;br /&gt;
Der Reibungsblock in diesem Modellbeispiel enthält eine Mischform aus Haftreibung, trockener und viskoser Reibung, wie sie typisch für einen Kleinbot mit 2 Antriebsrädern und einem Gleitpin ist.&lt;br /&gt;
&lt;br /&gt;
==Beispiel: Drehzahlregelung==&lt;br /&gt;
Es wird ein Gleichstrommotor in der Drehzahl geregelt. Als Sensor ist ein Tachogenerator vorhanden, der direkt auf der Motorwelle sitzt. Das System ist in einem kleinen Modellfahrzeug eingebaut und wird zur Geschwindigkeitsregelung eingesetzt, da die Drehzahl proportional zur Geschwindigkeit ist.&lt;br /&gt;
&lt;br /&gt;
Das Funktionsschaltbild sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl1.gif&lt;br /&gt;
&lt;br /&gt;
Als Störgröße können unterschiedliche Reibwerte oder Steigung und Gefälle rückwirkend über das Getriebe die Drehzahl beeinflussen. Das Getriebe und die Last sind zwar außerhalb der Regelschleife, beeinflussen aber durch die feste Kopplung des Getriebes die Dynamik des Regelkreises. Durch die starre Kopplung kann das Trägheitsmoment des Motors und die Masse des Fahrzeugs zusammengefasst werden. Das Gleiche gilt auch für die Reibwerte. Damit vereinfacht sich die Modellierung und das Blockschaltbild reduziert sich auf folgende Schaltung:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl2.gif&lt;br /&gt;
&lt;br /&gt;
Zur Ermittlung des dynamischen Verhaltens der Regelstrecke wird die Sprungantwort gemessen. Dazu wird auf den Eingang der Regelstrecke (Stellglied) ein Spannungssprung gegeben und die Antwort am Ausgang des Tachogenerators nachgemessen. Diese Methode erspart die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente der Regelstrecke (Motor, Getriebe, Fahrzeug). Die Messung ergab folgende Sprungantwort der Regelstrecke:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/tacho.gif&lt;br /&gt;
&lt;br /&gt;
Wie zu erwarten, ist die Sprungantwort annähernd ein Verzögerungsglied 1.Ordnung. Die abgelesene Zeitkonstante ist 0.11s. Die Verstärkung der Regelstrecke ist Ks = 0.72. Das Übertragungsmaß des Tachogenerators ist 1V pro 2480Upm. Damit kann auf die Drehzahl rückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da die Regelstrecke nur aus einem PT1-Glied besteht, könnte eine analoge Regelung fast beliebig schnell gemacht werden. Wegen der Begrenzung bringt aber das Ausreizen der Optimierung für das Führungsverhalten nicht viel, nur für das Störverhalten wäre eine schnellere Regelung sinnvoll. Um aber einen Vergleich zwischen analogem und digitalem Regler anstellen zu können wird eine Parametrierung gewählt, die auch für den digitalen Regler mit seiner Totzeit noch stabil ist. Es wird deshalb auch auf einen D-Anteil im Regler verzichtet und nur ein PI-Regler realisiert. Das vereinfachte Blockschaltbild mit den dynamischen Elementen sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl3.gif&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung wurde ein analoger als auch ein digitaler Regler realisiert. Die Parametrierung des analogen Reglers wurde mit dem Programm [[Regelungstechnik#LTspice.2FSwitcherCad_III| LTspice]] durchgeführt. Es bot sich an, da die analoge Reglerschaltung exakt simuliert werden konnte. Für die Optimierung des digitalen Reglers wurde dann [[Regelungstechnik#Scicos| Scicos]] verwendet. &lt;br /&gt;
&lt;br /&gt;
===Realisierung mit analogem Regler===&lt;br /&gt;
Die elektrische Schaltung für einen analogen PI-Regler ist in der nächsten Abbildung zu sehen. Der erste Operationsverstärker vergleicht den Sollwert w mit dem Istwert x. Der zweite Operationsverstärker bildet den PI-Regler. Die Werte R5, R6 und C1 sind für die Charakteristik des PI-Reglers zuständig. Mit R6 kann der P-Anteil und mit C1 der I-Anteil eingestellt werden. Die Optimierung der Werte wurde empirisch in einer Simulation mit LTspice durchgeführt. Da die Schaltung des PI-Reglers invertiert, wurden zum Ausgleich am Vergleicher die Eingänge an U1 vertauscht, so dass sich über die gesamte Schaltung wieder die richtige Polarität ergibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Analogregler.png]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen auf Kp und Ki können diese Formeln verwendet werden, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5 = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1) = 147&lt;br /&gt;
&lt;br /&gt;
===Realisierung mit digitalem Regler===&lt;br /&gt;
Im digitalen Regelkreis wird der Istwert '''x''' vom Tachogenerator mit einem A/D-Wandler digitalisiert. Der Sollwert '''w''' wird dem µC als digitaler Wert übergeben. Die Stellgröße '''y''' entspricht dem PWM-Wert für den Motortreiber. Um zum analogen Regler vergleichbar zu sein, wurde sowohl für den A/D-Wandler als auch für den PWM-Steller eine 8-Bit-Breite vorgesehen. Damit ist die Verstärkung in beiden Fällen gleich und analoger und digitaler Regler besser vergleichbar.&lt;br /&gt;
&lt;br /&gt;
Eigentlich könnte man bei kleiner Abtastzeit direkt die Parametrierung des analogen Reglers für die digitale Realisierung übernehmen. Aber es gibt doch kleine Unterschiede in der Dynamik zwischen analoger und digitaler Ausführung und um sicher zu gehen, dass die gewählte Abtastzeit einen nicht zu großen Einfluss hat, wird noch einmal mit [[Regelungstechnik#Scicos| Scicos]] nachoptimiert. Mit einer Abtastzeit Ta = 10ms und den Parametern des analogen Reglers ergibt sich ein Überschwingen, das nur sehr langsam auf den Endwert abklingt. Durch Verringern des I-Anteils auf 60 wird ein optimales Einschwingen für den digitalen Regler erreicht. Die Parameter sind:&lt;br /&gt;
&lt;br /&gt;
Kp = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 60&lt;br /&gt;
&lt;br /&gt;
Ta = 0.01&lt;br /&gt;
&lt;br /&gt;
Zur Umsetzung in einen Code wurde die Programmiersprache C gewählt. Da der Code sehr einfach ist, sollte es auch kein Problem sein, den Code als Beispiel für andere Sprachen zu verwenden. Der Algorithmus wird im Takt der Abtastzeit, also alle 10ms aufgerufen. In der Reglergleichung kann zur Vereinfachung das Produkt Ki*Ta durch eine Ersatzvariable, die gleich das Ergebnis aus dem Produkt 60*0.01 = 0.6 hat, ersetzt werden. Zum besseren Verständnis wurde es hier beim Ki*Ta belassen. Um einen Windup-Effekt zu verhindern, wird die Summenbildung esum auf +-400 begrenzt. Der Wert wurde so gewählt, dass noch eine volle Aussteuerung durch den I-Anteil möglich ist. Zum Schluss wird die Stellgröße y auf die mögliche Aussteuerung des Stellglieds (0...255) begrenzt.&lt;br /&gt;
&lt;br /&gt;
'''Programmbeispiel digitaler PI-Regler:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	e = w - x;				//Vergleich&lt;br /&gt;
	esum = esum + e;			//Integration I-Anteil&lt;br /&gt;
	if (esum &amp;lt; -400) {esum = -400;}	        //Begrenzung I-Anteil&lt;br /&gt;
	if (esum &amp;gt; 400) {esum = 400;}&lt;br /&gt;
	y = Kp*e + Ki*Ta*esum;			//Reglergleichung&lt;br /&gt;
	if (y &amp;lt; 0) {y = 0;}			//Begrenzung Stellgröße&lt;br /&gt;
	if (y &amp;gt; 255) {y = 255;}&lt;br /&gt;
	PWM = y;				//Übergabe Stellgröße&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Lageregelung ==&lt;br /&gt;
Unter einer Lageregelung versteht man die Positionierung von Objekten. Als Beispiel soll hier ein kleiner Bot mit Radencoder eine bestimmte Weglänge fahren. Gegenüber der Drehzahl- oder Geschwindigkeitsregelung ist bei der Lageregelung noch ein zusätzlicher Integrator in der Strecke vorhanden. Die gesamte Strecke ist damit ein I-Glied mit Verzögerung. Laut Tabelle im Abschnitt „Dimensionierung des Reglers“ ist dafür ein PD-Regler gut geeignet. Der PD-Regler wird digital ausgeführt, zur Simulation und Parametrierung bietet sich deshalb Scicos an. &lt;br /&gt;
&lt;br /&gt;
Da bei einer Lageregelung der Geschwindigkeitsbereich von Null aus geht, also über den nichtlinearen Bereich geht, sollte auch in der Simulation die Nichtlinearität berücksichtigt sein. Für das Beispiel wird deshalb das Modell eines Antriebs mit Haft- und Gleitreibung genommen, wie es unter &amp;quot;Modellierung eines Antriebs – detailliertes Modell&amp;quot; bereits vorgestellt wurde. Im Scicos-Modell ist der Antrieb der Übersichtlichkeit wegen als Superblock ausgeführt. Das Blockschaltbild des Antriebs im Detail ist [http://www.roboternetz.de/wissen/images/7/73/Antrieb_Modell.png hier] zu sehen. Die Daten sind:&lt;br /&gt;
&lt;br /&gt;
R = 16 Ohm; L = 6 mH; m = 0.31 kg; Kf = 6.6 N/A&lt;br /&gt;
&lt;br /&gt;
Als Sensor kommt ein Inkrementalgeber zum Einsatz, allerdings muss der richtungssensibel sein, sonst ist keine Lageregelung möglich. Der Sensor wird in Scicos mit der Rundungsformel (round(u1*500)) simuliert. Das ergibt bei einer Auflösung von 2mm ganzzahlige Schritte, wie es auch die Hardware (Inkrementalgeber mit nachfolgendem Zähler) in Wirklichkeit macht.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lageregelung.png]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Regler folgt ein Block mit der Verstärkung (5/255), der den PWM-Wert auf die Ansteuerspannung für den Motor umsetzt. Der Bruch 5/255 entspricht der Ansteuerspannung von 5V bei PWM=255. Der PD-Regler kann damit in Scicos exakt so simuliert werden, wie er schlussendlich auch als C-Code umgesetzt wird. Dazu wird der Code des PD-Reglers als Funktion in den Scifunc-Block eingegeben. Der Code ist etwas unterschiedlich zum C-Code des realen Bots, da die Syntax in Scicos doch geringfügig anders ist und die Eingangs- und Ausgangsvariablen nur bestimmte Bezeichnungen haben dürfen. Im nachfolgenden Codefenster sind beide Varianten im Vergleich zu sehen.&lt;br /&gt;
{|&lt;br /&gt;
 | '''Scifunc-Code:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y1=Kp*u1+Kd/Ta*(u1-z);&lt;br /&gt;
z=u1;&lt;br /&gt;
if y1&amp;gt;255 then&lt;br /&gt;
y1=255;&lt;br /&gt;
end&lt;br /&gt;
if y1&amp;lt;-255 then&lt;br /&gt;
y1=-255;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''C-Code für µC:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
e = w - x;&lt;br /&gt;
y = Kp*e + Kd/Ta*(e-ealt);&lt;br /&gt;
ealt = e;&lt;br /&gt;
if (y &amp;gt; 255) {&lt;br /&gt;
    y = 255;&lt;br /&gt;
    }&lt;br /&gt;
if (y &amp;lt; -255) {&lt;br /&gt;
    y = -255;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''Kommentar:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Vergleich&lt;br /&gt;
PD-Reglergleichung&lt;br /&gt;
alten Wert speichern&lt;br /&gt;
&lt;br /&gt;
pos. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
neg. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
In der praktischen Umsetzung des C-Codes wird man den Bruch Kd/Ta durch eine Ersatzvariable oder Konstante ersetzen. Dabei ergibt sich (wie in diesem Beispiel 2/0.01 = 200) meistens ein ganzzahliger Wert, was sich positiv auf die Rechenzeit auswirkt.&lt;br /&gt;
&lt;br /&gt;
Für die Abtastzeit Ta wurde 10ms gewählt. Das ist einerseits nicht zu schnell für einen µC und andererseits nicht zu lang, um die Regelung unnötig zu verlangsamen. Die Parametrierung von Kp und Kd erfolgte empirisch durch Probieren in der Simulation. Begonnen wurde mit einem reinen P-Regler und kleinem P-Anteil (Kp=1, Kd=0). In groben Schritten wurde Kp solange erhöht, bis sich deutlich Überschwinger zeigten. Dann wurde ein D-Anteil hinzugefügt und Kd so variiert, dass der Überschwinger verschwindet. Mit ein bisschen Feintuning ergaben sich so die Werte Kp=61 und Kd=2. Das Simulationsergebnis für Ansteuerspannung, Geschwindigkeit und Weg sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lage_antwort.png]]&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:Waste|Waste]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[SwitcherCAD-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/viewtopic.php?t=11818 Post: Line follower with PID controller]&lt;br /&gt;
*[http://www.scicos.org/ Scicos Homepage]&lt;br /&gt;
* [http://www.scicoslab.org/  ScicosLab Homepage]&lt;br /&gt;
* [http://www.scilab.org/ Scilab Homepage]&lt;br /&gt;
* [http://ltspice.linear.com/software/swcadiii.exe LTspice / SwitcherCAD III Download]&lt;br /&gt;
* [http://www.kahlert.com/web set_download.php demo version of WinFACT 7]&lt;br /&gt;
* [http://www.physi.uni-heidelberg.de/fp/anleitg/E01.pdf instructions for electronic placement, the last part is based PID controller]&lt;br /&gt;
* [http://www.simapp.com/ SimApp website] with trial&lt;br /&gt;
* [http://www.expertcontrol.com/ ExpertControl Homepage, Automatische Reglerauslegung mit ecICP] ecICP-Trial über Support-Seite verfügbar&lt;br /&gt;
* [http://www.me.th-mittelhessen.de/personen/professoren/orlowski/simulation-regelungstechnik/ TH-Mittelhessen Prof. Peter F. Orlowski, Simulationsprogramm SIMLER-PC]&lt;br /&gt;
&lt;br /&gt;
[[Category: Microcontroller]]&lt;br /&gt;
[[Category: Software]]&lt;br /&gt;
[[Category: Elektronik]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pidregler.gif&amp;diff=25247</id>
		<title>Datei:Pidregler.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pidregler.gif&amp;diff=25247"/>
				<updated>2014-09-13T08:14:13Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/pidregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/pidregler.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pdregler.gif&amp;diff=25246</id>
		<title>Datei:Pdregler.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pdregler.gif&amp;diff=25246"/>
				<updated>2014-09-13T08:13:22Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/pdregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/pdregler.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Piregler.gif&amp;diff=25245</id>
		<title>Datei:Piregler.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Piregler.gif&amp;diff=25245"/>
				<updated>2014-09-13T08:12:51Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/piregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/piregler.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Iregler.gif&amp;diff=25244</id>
		<title>Datei:Iregler.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Iregler.gif&amp;diff=25244"/>
				<updated>2014-09-13T08:12:27Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/iregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/iregler.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pregler.gif&amp;diff=25243</id>
		<title>Datei:Pregler.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pregler.gif&amp;diff=25243"/>
				<updated>2014-09-13T08:11:59Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von  http://www.roboternetz.de/wiki/uploads/Main/pregler.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von  http://www.roboternetz.de/wiki/uploads/Main/pregler.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25242</id>
		<title>Regelungstechnik</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25242"/>
				<updated>2014-09-13T08:02:59Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Die Regelstrecke */ wikify: pglied.gif, iglied.gif, ttglied.gif, pt1glied.gif, pt2aglied.gif, pt2bglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Regelungen''' sind ein Bestandteil unseres Lebens und das nicht nur seit Erfindung der Dampfmaschine. &lt;br /&gt;
&lt;br /&gt;
Allein schon der aufrechte Gang funktioniert nur mit Regelung. Dabei wirken die Sinne als Sensoren, das Gehirn als Regler und die Muskeln als Aktuatoren. Weitere Regelungen in unserem Körper sind z.B. die Konstanthaltung der Körpertemperatur, der Blutdruck, die Anpassung der Pupille auf Helligkeitsänderungen usw.&lt;br /&gt;
&lt;br /&gt;
Im technischen Zeitalter ist der erste geschichtlich bedeutende Regler der Fliehkraftregler von James Watt, der für die Drehzahlregelung seiner Dampfmaschine eingesetzt wurde. Seitdem ist die Regelungstechnik aus keinem Technikbereich mehr wegzudenken. Die Regelungstechnik begegnet uns im täglichen Leben auf Schritt und Tritt: Der Temperaturregler der Zentralheizung, der Temperaturregler des Kühlschranks, der Regler für die Belichtungsautomatik im Fotoapparat, das ABS-System im Auto und die Netzspannungs- und Frequenzregelung des europäischen Versorgungsnetzes sind nur einige wenige Beispiele aus diesem Bereich. &lt;br /&gt;
&lt;br /&gt;
''Autor Waste''&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Regelung'' ist zu unterscheiden von dem im allgemeinen Sprachgebrauch oft synonym gebrauchten Begriff der ''Steuerung''. Das Steuern ist ein rein vorwärts gerichteter Prozess ohne Rückkopplung. Die Ausgangsgröße wird dabei nicht überwacht und kann sich durch Störungen von außen verändern. Ein Beispiel ist die Steuerung eines Motors mit einer einstellbaren Spannung. Durch Laständerungen wird sich die Drehzahl des Motors ändern. Soll nun die Drehzahl konstant gehalten werden, bedarf es einer Rückkopplung um über die Spannung die Drehzahl anzupassen. Diese Rückkopplung ist das Kennzeichen einer Regelung.&lt;br /&gt;
&lt;br /&gt;
Das Regeln ist ein Vorgang, bei dem die Ausgangsgröße, im Beispiel die Drehzahl, fortlaufend überwacht wird und bei Abweichung über die Stellgröße, im Beispiel die Spannung, korrigiert wird. Der sich dabei ergebende Wirkungsablauf findet in einem geschlossenen Kreis, dem Regelkreis, statt.&lt;br /&gt;
&lt;br /&gt;
==Der Regelkreis==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis1.png|right|thumb|300px|Ein Regelkreis (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip einer Regelung ist das fortlaufende: '''Messen – Vergleichen – Stellen'''&lt;br /&gt;
&lt;br /&gt;
;Messen: Die Regelgröße wird direkt oder mittels Sensoren gemessen.&lt;br /&gt;
;Vergleichen: Der Wert der Regelgröße wird mit dem Sollwert verglichen. Die Differenz ist die ''Regelabweichung''.&lt;br /&gt;
;Stellen: Aus der Regelabweichung wird unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke die ''Stellgröße'' bestimmt.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis2.png|thumb|350px|Wirkunsweise einer Regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis dient dazu, eine vorgegebene physikalische Größe, die ''Regelgröße'', auf einen gewünschten Wert (Sollwert) zu bringen und dort zu halten, unabhängig von eventuell auftretenden Störungen.&lt;br /&gt;
Um die Regelungsaufgabe zu erfüllen, muss der Augenblickswert der Regelgröße – der Istwert – gemessen und mit dem Sollwert verglichen werden. Bei auftretenden Abweichungen muss in geeigneter Art und Weise nachgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Um nun diese Aufgabe technisch zu lösen, gibt es die Regelungstechnik. Sie baut im wesentlichen auf die mathematische Beschreibung und Modellbildung des Systems Regelkreis. Zur Modellierung, Beschreibung und Simulation werden Blockschaltbilder mit diskreten Signalgliedern verwendet.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis3.png|thumb|350px|Beispiel einer Geschwindigkeits&amp;amp;shy;regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein typisches Beispiel für einen Regelkreis – eine Geschwindigkeits&amp;amp;shy;regelung – wird im nebenstehenden Bild gezeigt. Die Sollgeschwindigkeit ist 80 km/h. Durch eine äußere Störung, in dem Fall eine Steigung, verlangsamt sich das Fahrzeug auf 70 km/h. Die Abweichung wird durch das Tachometer erfasst. Als Korrekturmaßnahme wird mehr Gas gegeben, um wieder auf die Sollgeschwindigkeit von 80 km/h zu kommen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Begriffe ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis4.png|right]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis besteht entsprechend des vereinfachten Blockschaltbildes, wie es oft in der Regelungstechnik verwendet wird, aus den Hauptteilen ''Regler'' und ''Regelstrecke'':&lt;br /&gt;
&lt;br /&gt;
;Regler: Ist der Teil des Regelkreises, der unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke aus der Regelabweichung die Korrekturmaßnahmen zum Ausregeln ergreift.&lt;br /&gt;
&lt;br /&gt;
;Regelstrecke: Ist der Teil des Regelkreises, der vom Regler ausgeregelt werden soll.&lt;br /&gt;
&lt;br /&gt;
;Führungsgröße (Sollwert) w: Vorgegebener Wert, auf dem die Regelgröße durch die Regelung gehalten werden soll. Sie ist eine von der Regelung nicht beeinflusste Größe und wird von außen zugeführt.&lt;br /&gt;
&lt;br /&gt;
;Regelgröße (Istwert) x: Ist die Ausgangsgröße der Regelstrecke, die zum Zweck des Regelns erfasst und zum Vergleich rückgeführt wird. In vielen Fällen ist in der Rückführung noch eine Messeinrichtung (Sensor) gezeichnet, die den Istwert erfasst, hier der Einfachheit halber weggelassen.&lt;br /&gt;
&lt;br /&gt;
;Regelabweichung e: Differenz zwischen Führungsgröße und Regelgröße '''e = w – x''', bildet die eigentliche Eingangsgröße des Reglers.&lt;br /&gt;
&lt;br /&gt;
;Stellgröße y: Ausgangsgröße der Regeleinrichtung und zugleich Eingangsgröße der Strecke. Sie überträgt die steuernde Wirkung des Reglers auf die Strecke.&lt;br /&gt;
&lt;br /&gt;
;Störgröße z: Eine von außen wirkende Größe, die eine Änderung des Istwertes der Regelgröße bewirkt und einen Regelvorgang auslöst.&lt;br /&gt;
&lt;br /&gt;
==Die Regelstrecke==&lt;br /&gt;
Die Regelstrecke stellt den zu regelnden Teil bzw. den zu regelnden Prozess dar und umfasst normalerweise eine Reihe von einzelnen Gliedern. Die Glieder werden entsprechend ihrem Zeitverhalten charakterisiert. Um das Zeitverhalten herauszufinden, legt man an den Eingang ein Testsignal an und zeichnet die Antwort auf. Im einfachsten Fall wird der Eingang mit einer sprunghaften Änderung beaufschlagt. Die Antwort auf die sprunghafte Änderung der Eingangsgröße wird Sprungantwort genannt und gibt Aufschluss über die Art der Regelstrecke und kann eventuell bereits genutzt werden, um die Parameter der Regelstrecke zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Für den Aufbau eines gut funktionierenden Regelkreises und die Auslegung von Reglern ist es eine Voraussetzung zu wissen, wie die Regelstrecke reagiert. Ohne ein genaues Wissen um das dynamische Verhalten der Regelstrecke ist es nicht möglich geeignete Regler auszuwählen und diese zu parametrieren.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten dynamischen Grundelemente zur Charakterisierung der Regelstrecke sind nachfolgend aufgelistet. Jedes Element wird mit einem Block dargestellt und darin durch ein Symbol oder der stilisierten Sprungantwort gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Proportionalglied (P-Glied)===&lt;br /&gt;
[[File:pglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art einer Regelstrecke.&lt;br /&gt;
;Beispiele: Hebel, Getriebe, Verstärker, Spannungsteiler, Sensoren bei denen das Zeitverhalten vernachlässigt werden kann&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Integrator (I-Glied)===&lt;br /&gt;
[[File:iglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Strecke ohne Ausgleich, ist häufig in Regelstrecken vorhanden.&lt;br /&gt;
;Beispiele: Beschleunigung → Geschwindigkeit → Weg, Strom → Kondensatorspannung&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 0.Ordnung (Totzeitglied)===&lt;br /&gt;
[[File:ttglied.gif]]&lt;br /&gt;
&lt;br /&gt;
Entsteht durch Laufzeiten von Material oder Signalen. Je größer die Verzögerungszeit einer Regelstrecke ist, um so schwieriger ist sie zu regeln. &lt;br /&gt;
;Beispiele: Förderband, Rechenzeit, A/D-Wandler&lt;br /&gt;
&lt;br /&gt;
Nicht zu verwechseln mit der Totzeit, die durch das asynchrone Auftreten eines Ereignisses auf einen Zyklus entsteht. Vom Verzögerungsglied 0.Ordnung unterscheidet sich diese dadurch, daß sie mit einer gleichverteilten Wahrscheinlichkeit zwischen &amp;quot;gar nicht&amp;quot;  und dem gesamten Umfang auftritt. Diese Totzeit ist mechanisch mit einem Spiel vergleichbar das &amp;quot;gar nicht&amp;quot; bis zum vollen Umfang zu einem Fehler beiträgt. &lt;br /&gt;
;Beispiele: Erkennen eines Signals an einem Mikroprozessor&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 1.Ordnung (PT1-Glied)===&lt;br /&gt;
[[File:pt1glied.gif]]&lt;br /&gt;
&lt;br /&gt;
Viele einfache Regelstrecken haben ein solches Verhalten bzw. können näherungsweise damit beschrieben werden. Ist ein P-Glied mit nicht vernachlässigbarem Zeitverhalten.&lt;br /&gt;
;Beispiele: Gleichstrommotor (Spannung → Drehzahl), näherungsweise; Widerstand-Kondensator-Schaltung (RC-Glied)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 2.Ordnung (PT2-Glied)===&lt;br /&gt;
Man unterscheidet schwingungsfähige und nicht schwingungsfähige PT2-Glieder. Zur Charakterisierung gibt es die Parameter Dämpfung D und Eckfrequenz w&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; oder die Zeitkonstanten T&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und T&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Für Dämpfung D&amp;lt;1 ist es schwingungsfähig.&lt;br /&gt;
&lt;br /&gt;
'''Schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2aglied.gif]]&lt;br /&gt;
;Beispiele: Mechanischer Schwinger (Feder-Masse-System), elektrischer Schwingkreis (RLC-Kreis)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nicht schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
[[File:pt2bglied.gif]]&lt;br /&gt;
;Beispiele: Zwei hintereinander geschaltete PT1-Glieder, Gleichstrommotor (Spannung → Drehzahl) mit berücksichtigter Induktivität&lt;br /&gt;
&lt;br /&gt;
==Der Regler==&lt;br /&gt;
Der Regler hat die Aufgabe, die Regelgröße zu messen, sie mit dem Sollwert zu vergleichen und bei Abweichungen die Stellgröße so zu verändern, dass Soll- und Istwert der Regelgröße wieder übereinstimmen bzw. die Differenz minimal wird.&lt;br /&gt;
&lt;br /&gt;
Die Wahl eines bestimmten Reglertyps richtet sich nach dem geforderten Zeitverhalten und der geforderten Regelgenauigkeit der Regelstrecke. Nachfolgend finden Sie eine Zusammenfassung der wichtigsten klassischen Reglertypen:&lt;br /&gt;
&lt;br /&gt;
===P-Regler===&lt;br /&gt;
Der proportionalwirkende Regler multipliziert die Regelabweichung mit seinem Verstärkungsfaktor '''Kp''' und gibt das Ergebnis unverzögert weiter. Er unterscheidet sich prinzipiell nicht vom dynamischen Element P-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der P-geregelte Kreis ist einfach und mittelschnell im Vergleich zu anderen Regelungen. Das Problem ist die bleibende Regelabweichung!&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software P-Regler:'''&lt;br /&gt;
 y = Kp * e&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===I-Regler===&lt;br /&gt;
Der integralwirkende Regler summiert die Regelabweichung über der Zeit auf und multipliziert die Summe (d.h. das Integral) mit dem Faktor '''Ki'''. Je länger eine Regelabweichung ansteht, desto größer wird die Stellgröße des I-Reglers. Er unterscheidet sich prinzipiell nicht vom dynamischen Element I-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der I-geregelte Kreis ist langsam im Vergleich zu anderen Regelungen. Er hat aber den Vorteil, dass die Abweichung vollständig eliminiert wird.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/iregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software I-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
'''esum''' ist die Summe aller bisherigen Abweichungen '''e'''. Der Parameter des Software I-Reglers ist abhängig von der Rechenschrittweite '''Ta''' (Abtastzeit). Je öfter gerechnet wird, desto öfter wird auch hinzugezählt (aufintegriert). Eine kleine Abtastzeit erfordert also einen kleineren Faktor, dies wird durch die Multiplikation mit '''Ta''' verwirklicht.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PI-Regler===&lt;br /&gt;
Der PI-Regler ist die Kombination aus P- und I-Regler und kombiniert den Vorteil des P-Reglers, nämlich schnelle Reaktion, mit dem Vorteil des I-Reglers, der exakten Ausregelung.  Der PI-geregelte Kreis ist also genau und mittelschnell.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/piregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PI-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PD-Regler===&lt;br /&gt;
Der proportional-differential wirkende Regler kombiniert den P-Regler mit einem D-Anteil. &lt;br /&gt;
Der D-Anteil bewertet die Änderung einer Regelabweichung (er differenziert) und berechnet so deren Änderungsgeschwindigkeit. Diese wird mit dem Faktor '''Kd''' multipliziert und zum P-Anteil hinzuaddiert. Der PD-Regler reagiert damit schon auf Ankündigungen von Veränderungen, das bewirkt sozusagen ein Vorhalten beim Regeln.&lt;br /&gt;
&lt;br /&gt;
Der PD-geregelte Kreis ist sehr schnell im Vergleich zu anderen Regelungen, und manche Regelkreise (solche mit zweifacher Integration) sind ohne D-Anteil überhaupt nicht stabilisierbar. Das Problem der proportionalen Regler, die bleibende Regelabweichung, ist beim PD-Regler allerdings weiterhin vorhanden!&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil aller Regler mit D-Anteil kann die Unruhe im Kreis sein. Ist das Sensorsignal verrauscht, so wird dieses Rauschen durch die Differenziation weiter verstärkt und wieder in den Kreis hineingegeben. Dadurch wird der Aktuator stärker belastet. Macht der Regler insbesondere sehr hohe Ausschläge als Folge von schnellen Änderungen des Sollwertes, dann kann es sein, dass das Stellglied oder der Aktuator diese nicht umsetzen kann - die Wirkung des D-Anteils würde dann durch die Begrenzung verpuffen, und das Einschwingverhalten wäre nicht wie berechnet, sondern meist langsamer. Dies gilt aber nur für große Sprünge. Bei den normalen kleinen Regelvorgängen zum Ausgleich von Störeinflüssen wirkt der D-Anteil wie beabsichtigt.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pdregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PD-Regler:'''&lt;br /&gt;
 y = Kp * e + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
Mit der neuesten Regelabweichung '''e''' und der vorhergehenden '''ealt''' wird der D-Anteil berechnet. Die Differenziation erfolgt damit angenähert durch Bildung des Differenzquotienten (e - ealt)/Ta.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PID-Regler===&lt;br /&gt;
Der PID Regler ist der universellste der klassischen Regler und vereinigt die guten Eigenschaften der anderen Regler. Zur Beschreibung der Eigenschaften des P-, I- und D-Anteils siehe die anderen Reglertypen. Der PID-geregelte Kreis ist genau und sehr schnell. In den meisten Anwendungen kommt deshalb der PID-Regler zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pidregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PID-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Alternative PID-Reglerstruktur:'''&lt;br /&gt;
&lt;br /&gt;
Es gibt 2 Darstellungsmöglichkeiten, die inhaltlich identisch sind. In der analogen Regeltechnik ist noch die Darstellung mit der Nachstellzeit '''Tn''' und der Vorhaltezeit '''Tv''' üblich. Die Umrechnung zwischen den beiden Strukturen ist mit den angegebenen Formeln möglich.&lt;br /&gt;
&lt;br /&gt;
[[Bild:PIDstruktur.gif]]&lt;br /&gt;
&lt;br /&gt;
==Vergleich der Reglertypen==&lt;br /&gt;
In der folgenden Abbildung ist der Vergleich von P-, I-, PI-, PD- und PID-Regler in einem Regelkreis mit PT2-Glied als Regelstrecke dargestellt. Es ist deutlich zu sehen, dass die Regler ohne I-Anteil (P und PD) eine bleibende Regelabweichung aufweisen. Erst die Regler mit I-Anteil können auf den Endwert von 1 ausregeln. Beim reinen I-Regler geht das so langsam, dass es gar nicht mehr auf dem Diagramm zu sehen ist. Der Hauptzweck eines I-Anteils ist also die Vermeidung bleibender Regelabweichungen. Daher ist ein&lt;br /&gt;
I-Anteil normalerweise nicht nötig, wenn die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
Ausnahme: Es wird ein doppelter I-Anteil zur Vermeidung von Schleppfehlern benötigt.&lt;br /&gt;
&lt;br /&gt;
Die schnellsten Regler sind die mit einem D-Anteil (PD und PID). Der D-Anteil kommt deshalb hauptsächlich zum Einsatz, wenn schnelle Dynamik gefragt ist oder die Strecke selbst schon instabil ist. Voraussetzung für die Schnelligkeit ist allerdings, dass keine Begrenzung im Stellglied oder Aktuator auftritt. In der Praxis ist eine Begrenzung meistens nicht zu vermeiden, deshalb gilt die Sprungantwort in der Praxis nur für kleine Sprünge.&lt;br /&gt;
&lt;br /&gt;
Die Regler ohne D-Anteil, aber mit P-Anteil (P und PI) sind mittelschnell. Für einfache Regelaufgaben reicht auch oft schon ein reiner P-Regler aus, wenn die bleibende Regelabweichung vernachlässigt werden kann oder weil die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/vergleich.gif&lt;br /&gt;
&lt;br /&gt;
Aus diesem Vergleich wird klar, warum der PID-Regler so beliebt ist, er vereinigt die Vorzüge aller anderen Regler.&lt;br /&gt;
&lt;br /&gt;
==Digitaler Regler==&lt;br /&gt;
Durch die Einführung leistungsfähiger und preiswerter Mikroprozessoren hat sich der digitale Regler mehr und mehr durchgesetzt. Im Gegensatz zum analogen Regler werden die Signale nicht mehr analog mit Operationsverstärker verarbeitet, sondern mit einem Mikroprozessor errechnet. Bevor das Signal vom Mikroprozessor bearbeitet werden kann, muss zunächst das Eingangssignal (Istwert) mit einem Analog-Digital-Umsetzer (ADU) digitalisiert werden, d.h. in einen Zahlenwert umgewandelt werden. Das vom digitalen Regler errechnete Ausgangssignal (Stellgröße) wird wiederum zur Ansteuerung des Stellglieds mit einem Digital-Analog-Umsetzer (DAU) in ein analoges Signal gewandelt. Funktionell unterscheiden sich analoger und digitaler Regler jedoch nicht wesentlich, es müssen nur die Schnittstellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
[[File:digreg.gif|right|framed|Digitaler Regler (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Da die Wandlungen und das Regelprogramm eine gewisse Zeit beanspruchen, vergeht pro Durchlauf die sogenannte Takt- oder Abtastzeit. Diese Zeit wirkt sich im Regelkreis wie ein Totzeitglied mit der halben Abtastzeit als Totzeit aus. Das verursacht eine zusätzliche Phasenverschiebung, was sich ungünstig auf die Stabilität des Regelkreises auswirken kann. Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der digitale Regler kann dann wie ein analoger dimensioniert werden. Ist die Abtastzeit größer, kann sie nicht mehr vernachlässigt werden, dann muss sie auch beim Reglerentwurf berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
'''Vorteile digitaler Regler:'''&lt;br /&gt;
* Die Verarbeitung erfolgt driftfrei.&lt;br /&gt;
* Es lassen sich nichtlineare Kennlinien, intelligentes Verhalten oder adaptive Regelung leichter realisieren.&lt;br /&gt;
* Der Regler kann bei Bedarf per Software neu konfiguriert und parametriert werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Digitale Realisierung am Beispiel des PID-Algorithmus'''&lt;br /&gt;
&lt;br /&gt;
Ausgehend von der Differentialgleichung für kontinuierliche Systeme wird die Differenzengleichung für zeitdiskrete Systeme erstellt. Daraus folgt dann der Stellungsalgorithmus in allgemeiner Form.&lt;br /&gt;
&lt;br /&gt;
Ta = Abtastzeit; k = Nummer der Abtastung&lt;br /&gt;
&lt;br /&gt;
Kp = Proportionalbeiwert; Ki = Integrierbeiwert; Kd = Differenzierbeiwert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- http://www.roboternetz.de/wiki/uploads/Main/pidformel.gif --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differentialgleichung für den kontinuierlichen PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y(t) \;=\;  Kp \!\cdot\! e(t) &lt;br /&gt;
          + Ki \int_0^t e(\tau) \, d\tau &lt;br /&gt;
          + Kd \, \frac{de(t)}{dt}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differenzengleichung für den zeitdiskreten PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  Kp \!\cdot\! e_k&lt;br /&gt;
          + Ki \!\cdot\! Ta \sum_{i=0}^k e_i&lt;br /&gt;
          + \frac{Kd}{Ta}\, ( e_k - e_{k-1} )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''PID Stellungs-Algorithmus:&lt;br /&gt;
:''' &amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  y_{k-1} &lt;br /&gt;
          + q_0 \!\cdot\! e_k&lt;br /&gt;
          + q_1 \!\cdot\! e_{k-1}&lt;br /&gt;
          + q_2 \!\cdot\! e_{k-2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den Parametern:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
q_0 \,=\, Kp + Ki \!\cdot\! Ta + \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_1 \,=\, -Kp  - 2 \, \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_2 \,=\, \frac{Kd}{Ta}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Umsetzung in Code nach der Differenzengleichung:'''&lt;br /&gt;
&lt;br /&gt;
Im Code wurden einige Variablen umbenannt, da die Indexschreibweise nicht möglich ist.&lt;br /&gt;
&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, esum ist die Summenbildung&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird man die Ausdrücke Ki*Ta und Kd/Ta vorab berechnen und mit Ersatzvariablen in die Reglergleichung einsetzen. Der Verständlichkeit halber wurde es hier im Code belassen. Des weiteren kann eine Begrenzung von esum notwendig werden, um einen Variablenüberlauf oder Windup-Effekt zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Der nachfolgende Code wird im Rhythmus der Abtastzeit Ta immer wieder aufgerufen.&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 esum = esum + e;				//Integration I-Anteil&lt;br /&gt;
 y = Kp*e + Ki*Ta*esum + Kd/Ta*(e – ealt);	//Reglergleichung&lt;br /&gt;
 ealt = e;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''Alternative Umsetzung in Code nach dem Stellungsalgorithmus:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, yalt entspricht y&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, ealt2 entspricht e&amp;lt;sub&amp;gt;k-2&amp;lt;/sub&amp;gt;&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 y = yalt + q0*e + q1*ealt + q2*ealt2;		//Reglergleichung&lt;br /&gt;
 ealt2 = ealt;&lt;br /&gt;
 ealt = e;&lt;br /&gt;
 yalt = y;&lt;br /&gt;
&lt;br /&gt;
==Dimensionierung des Reglers==&lt;br /&gt;
Die Auswahl des Reglertyps ist heutzutage bei den digitalen Reglern nicht mehr so kritisch, da der Mehraufwand in Software für einen PID-Regler gegenüber einfacheren Typen kaum zu Buche schlägt. Im Prinzip ist man deshalb mit einem PID-Regler fast immer auf der richtigen Seite, mit einer Ausnahme, bei einer Strecke mit reiner Totzeit. Die folgende Tabelle gibt eine Hilfestellung zur Auswahl des Reglers. &lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ '''Geeignete Reglertypen für die unterschiedlichen Regelstrecken'''&lt;br /&gt;
 |rowspan=2 |'''Strecke'''&lt;br /&gt;
 |colspan=4 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Regler'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PD'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |reine Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |-&lt;br /&gt;
 |1.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |2.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |höhere Ordnung&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |I-Glied und Verzögerung&lt;br /&gt;
 |geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Nachdem man einen geeigneten Reglertyp ausgewählt hat, stellt sich noch die Frage, wie man die Reglerparameter Kp, Ki, und Kd optimiert. Im Laufe der Zeit wurden viele Methoden zur Dimensionierung der Reglerparameter entwickelt, aber es können hier nicht alle aufgelistet werden. Diese Aufzählung beschränkt sich auf die einfacheren und gängigen Methoden der Parametrierung.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung durch Probieren (Empirisches Einstellen)===&lt;br /&gt;
&lt;br /&gt;
====Methode 1====&lt;br /&gt;
Diese Methode ist geeignet um einfache Systeme zu dimensionieren, insbesondere wenn man bereits Erfahrung mit ähnlichen Regelkreisen hat. Man fängt mit einer unkritischen Einstellung (Kp klein, Ki = 0, Kd = 0) an und erhöht langsam die Verstärkung Kp, bis die Dämpfung schlecht wird. Falls eine Schwingneigung auftritt, muss die Verstärkung wieder etwas zurück genommen werden. Dann nimmt man allmählich den Integralanteil hinzu, erhöht ihn in Schritten und probiert solange herum, bis das Ergebnis einigermaßen passt. Bei Bedarf kann noch ein D-Anteil (PID-Struktur) probiert werden. Wenn dabei die Regelung stabiler wird, kann noch mal Kp und Ki erhöht werden, bis man endgültig zufrieden ist. &lt;br /&gt;
&lt;br /&gt;
====Methode 2====&lt;br /&gt;
Alle Anteile erstmal auf 0. Dann erhöht man Kp so lange bis das System deutlich schwingt. Danach wird der Kd so lange erhöht bis das System nicht mehr schwingt. Anschliessend kann noch ein kleiner Ki Anteil hinzugegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es dürfte klar sein, dass so eine Optimierung im Blindflug nicht immer das Optimum ergibt, aber es ist eine gängige praktische Methode zur Ermittlung der Reglerparameter. Besser sieht es aus, wenn in einer Simulation empirisch optimiert wird. Zusätzliche Informationen über die Stabilität erlauben hierbei eine gezieltere Optimierung. Zudem ist das Probieren im Simulator gefahrlos möglich, was in der Realität nicht immer der Fall ist. Geeignete Programme zur Simulation sind [[Regelungstechnik#Hilfsprogramme_zur_Analyse_und_Optimierung| hier]] vorgestellt. Allerdings muss für eine Simulation die Regelstrecke bekannt sein. Ist das nicht der Fall, so bleibt nur das einfache Probieren oder das Einstellen nach der Schwingungsmethode wie im folgenden beschrieben.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung nach Einstellregeln===&lt;br /&gt;
Die Dimensionierung nach Rezept ist eine praktische Methode ohne viel Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die bekanntesten Einstellregeln sind von Ziegler/Nichols und von Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer Einstelltabellen, auf die hier aber verzichtet wird, das würde den Rahmen dieses Artikels sprengen. An der Vielzahl kann man schon ersehen, dass es kein universell gültiges Rezept gibt und mit diesen Tabellen nicht unbedingt das Optimum erreicht wird, eine Nachoptimierung kann nötig sein.&lt;br /&gt;
&lt;br /&gt;
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.&lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Schwingungsmethode:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter so verstellt, dass die Stabilitätsgrenze erreicht wird und der Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische Schwingungen ausführt. Aus der so gefundenen Einstellung können die Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden anrichtet und die überhaupt instabil gemacht werden können. Die Vorgehensweise ist folgende:&lt;br /&gt;
# Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0&lt;br /&gt;
# Die Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen ausführt.&lt;br /&gt;
# Der dabei eingestellte Wert Kp wird als Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; bezeichnet. &lt;br /&gt;
# Die Periodendauer der sich einstellenden Dauerschwingung T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; wird gemessen.&lt;br /&gt;
# Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.45*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;0.85*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.5*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.12*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken angewendet werden kann, die auch zum Schwingen gebracht werden können. &lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Sprungantwort:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Diese Methode der Parameterbestimmung beruht auf der Aufnahme der Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die nicht zum Schwingen gebracht werden können. Der Regelkreis muss allerdings geöffnet werden.&lt;br /&gt;
Vorgehensweise: Es wird die Sprungantwort aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu und die Ausgleichszeit Tg ermittelt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tu_Tg.gif]]&lt;br /&gt;
&lt;br /&gt;
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Ziegler/Nichols:&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.9/Ks*Tg/Tu&lt;br /&gt;
 |3.3*Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1.2/Ks*Tg/Tu&lt;br /&gt;
 |2*Tu&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Chien/Hrones/Reswick&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.3/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.35/Ks*Tg/Tu&lt;br /&gt;
 |1.2*Tg&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6/Ks*Tg/Tu&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Tg&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| cellpadding=4 width=420&lt;br /&gt;
 |Die Parameter Tn und Tv sind aus der analogen Regelungstechnik und sind dort sehr geläufig. Die Umrechnung in die Parameter Ki und Kd erfolgt mit nebenstehenden Formeln. Siehe auch [[Regelungstechnik#PID-Regler| PID-Regler]]&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit dem Bodediagramm===&lt;br /&gt;
Ein Bode-Diagramm ist die grafische Darstellung des Frequenzganges. Es werden der Betrag der Übertragungsfunktion (Amplitudengang) und der Verlauf des Phasenwinkels (Phasengang) als Funktion der Frequenz aufgetragen. Die Frequenzachse und die Amplitudenachse werden logarithmisch dargestellt. Die logarithmische Darstellung hat den Vorteil, dass eine Multiplikation auf eine einfache Addition zurückgeführt wird. Somit wird eine Hintereinanderschaltung von Systemen im Blockschaltbild zu einer einfachen Addition im Bodediagramm.&lt;br /&gt;
&lt;br /&gt;
Das Zeitverhalten des rückgekoppelten Regelkreises hängt entscheidend vom Verlauf&lt;br /&gt;
des Frequenzganges der offenen Regelschleife in der Umgebung des Durchtretens durch&lt;br /&gt;
die 0dB-Achse ab. In der Regelungstechnik wird daher der offene Regelkreis im Bode-Diagramm aufgetragen. Das erlaubt einen schnellen Überblick über Stabilität und möglichen Reserven zur Optimierung. Ein Kriterium für die Stabilität der Schleife ist der Phasenrand und der Amplitudenrand. Der Phasenrand ist der Abstand (Phasenreserve) zur -180°-Linie bei der Durchtrittsfrequenz. Die Durchtrittsfrequenz ist diejenige Frequenz, bei der der Amplitudengang durch die 0dB-Linie geht. Siehe auch folgendes Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Phasenrand.gif]]&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |'''Regel:''' Eine geschlossene Regelschleife arbeitet genau dann stabil, wenn der Phasenrand positiv ist.&lt;br /&gt;
 |}&lt;br /&gt;
Wird diese Bedingung verletzt, so wird in diesem Frequenzbereich die im Rückführzweig der Regelung eingebrachte Gegenkopplung zu einer Mitkopplung und das System kann schwingen.&lt;br /&gt;
&lt;br /&gt;
'''Beim Reglerentwurf sind folgende Punkte zu beachten:'''&lt;br /&gt;
* Der Phasenrand muss positiv sein. Der geschlossene Regelkreis kann sonst instabil sein. &lt;br /&gt;
* Je größer der Phasenrand ist, desto größer ist die Stabilitätsreserve des Regelkreises und desto höher ist die Dämpfung des Regelkreises. Üblich sind Werte von 40°...70° für gutes Führungsverhalten und 20°...50° für gutes Störverhalten.&lt;br /&gt;
* Die Durchtrittsfrequenz ist ein Maß für die Schnelligkeit des Regelkreises, je höher, desto schneller ist die Reaktion auf Änderungen der Führungsgröße oder Störungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel zur Dimensionierung mit dem Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bode1.gif]]&lt;br /&gt;
&lt;br /&gt;
Die Strecke ist rot dargestellt und besteht in dem Beispiel aus einem nicht schwingfähigem PT2-Glied. Man sucht sich den Punkt, wo die Strecke für sich alleine noch ausreichend Phasenreserve hat, z.B. 70°. In dem Beispiel also die Frequenz, bei der die Strecke -110° Phasendrehung aufweist. Das ist etwa bei 15Hz. Da hat die Strecke ungefähr eine Dämpfung von 25dB. Wenn man nun diese Dämpfung durch eine Verstärkung von 25dB kompensiert, dann wird dieser Punkt zur Durchtrittsfrequenz. D.h. man wählt den P-Anteil des Reglers Kp=18, denn 25dB entspricht ungefähr dem Faktor 18. Um die Regelabweichung zu minimieren, wird noch ein I-Anteil hinzugefügt. Üblicherweise wählt man für die Grenzfrequenz des PI-Reglers die Grenzfrequenz des dominierenden Streckenteils, in dem Beispiel ca. 1.4Hz. Damit ergibt sich ein I-Anteil von 170. Im Bode-Diagramm ist der PI-Regler als schwarze Kurve eingezeichnet. Die Addition der Strecke und des Reglers im Bode-Diagramm führt dann zum Frequenzgang des offenen Regelkreises (blaue Kurve). Die resultierende Durchtrittsfrequenz ist wie gewählt bei etwa 15Hz. Der Phasenrand hat sich durch den I-Anteil im Regler auf ca. 60° reduziert, ist aber noch ausreichend. Das Einschwingen des geschlossenen Regelkreises für diese Dimensionierung sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort3.gif]]&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf könnte noch ein D-Anteil (PID-Regler) hinzugenommen werden, das würde die Phase anheben und man könnte dadurch die Durchtrittsfrequenz weiter nach oben schieben. In der Praxis wird dies allerdings wegen der wahrscheinlichen Begrenzung des Stellglieds kein schnelleres Einschwingen mehr bringen. &lt;br /&gt;
&lt;br /&gt;
Begrenzungen oder Nichtlinearitäten werden bei der Dimensionierung mit dem Bode-Diagramm nicht berücksichtigt. Das ist ein Nachteil dieser Methode. Eventuell muss deshalb noch einmal im Zeitbereich nachoptimiert werden.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit der Ortskurve===&lt;br /&gt;
Eine Alternative zur Dimensionierung mit dem Bodediagramm stellt die Methode über die Ortskurve des offenen Regelkreises dar.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Verfahren ist schnell auf einem Blick ersichtlich ob der Regelkreis stabil ist.&lt;br /&gt;
&lt;br /&gt;
Liegt der Punkt -1 auf der Realteilachse links von der Ortskurve in Richtung steigendem Omega so ist der Regelkreis stabil.&lt;br /&gt;
Der Abstand zu der kritischen Kreisfrequenz Omega Krit von der Imaginärteilachse ist die Verstärkung Vr mit diesem Wert lässt sich der Amplitudenrand ermitteln. &lt;br /&gt;
Dazu wird folgende Formel verwendet: Ar = 20 lg (1/Vr) in dB&lt;br /&gt;
&lt;br /&gt;
Die Durchtrittskreisfrequenz Omega D ist an dem Punkt, wo der Betrag aus Realteil und Imaginärteil 1 ergibt. Wenn man weiß, wo die Durchtrittskreisfrequenz ist, dann kann man den Phasenrand bestimmen.&lt;br /&gt;
Dies ist der Winkel zwischen der -180° Linie zu Omega D.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ortskurve.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Hilfsprogramme zur Analyse und Optimierung==&lt;br /&gt;
Die Analyse und Optimierung von Regelkreisen wird wesentlich erleichtert durch die Zuhilfenahme von Programmen. Es erspart einem eine komplizierte Rechnerei von Hand oder umfangreiche Testläufe. Stellvertretend für all die verfügbaren Programme werden hier zwei Freeware-Programme vorgestellt, die dafür gut geeignet sind. Die Beschreibung hier ersetzt aber keine Tutorials, es wird nur die Anwendung für die Regelungstechnik beschrieben. &lt;br /&gt;
&lt;br /&gt;
===Scilab/Scicos===&lt;br /&gt;
Scilab ist ein wissenschaftlich-technisches Softwarepaket für numerische Berechnungen. Scicos ist eine Erweiterung dazu, die eine blockorientierte und modellbasierte Simulation und Analyse von dynamischen Systemen bietet. Dieses Softwarepaket kann von der [http://www.scilab.org/ Scilab Homepage] herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
====Scilab====&lt;br /&gt;
Mit Scilab ist es sehr einfach ein Bode-Diagramm zu zeichnen, es bedarf nur 3 Zeilen Code.&lt;br /&gt;
 s=poly(0,'s');&lt;br /&gt;
 G=syslin('c',0.72/(0.11*s+1));&lt;br /&gt;
 bode(G)&lt;br /&gt;
Die 1.Zeile '''s=poly(0,'s');''' legt die Variable s als Polynomvariable fest. Dies braucht in einer Sitzung nur einmal gemacht zu werden. Die 2.Zeile '''G=syslin('c',0.72/(0.11*s+1));''' definiert ein lineares System mit der Übertragungsfunktion 0.72/(0.11s+1). Die 3.Zeile '''bode(G)''' zeichnet das Bode-Diagramm des zuvor mit syslin definierten Systems G. Zu beachten ist, dass Scilab auf der x-Achse im Bode-Diagramm die Frequenz in Hertz und nicht wie üblich die Kreisfrequenz darstellt. Anstelle des Bode-Diagramms kann auch die Sprungantwort gezeichnet werden. Dies geschieht mit folgenden Befehlen:&lt;br /&gt;
 xbasc();&lt;br /&gt;
 t=[0:0.001:2];&lt;br /&gt;
 y=csim('step',t,G);&lt;br /&gt;
 plot2d(t,y)&lt;br /&gt;
'''xbasc()''' löscht den letzten Plot mit dem Bode-Diagramm und mit '''t=[0:0.001:2]''' wird ein Vektor t mit den angegebenen Zeiten im Intervall von 1ms definiert. Die Zeile '''y=csim('step',t,G)''' berechnet die Sprungantwort des zuvor mit syslin definierten Systems G und speichert sie in y ab. Das Ergebnis wird dann mit '''plot2d(t,y)''' dargestellt. Bei Bedarf können noch Gitternetzlinien mit dem Befehl '''xgrid()''' hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Ergänzend hier noch ein Scilab-Skript, welches recht hilfreich bei der Dimensionierung mit dem Bode-Diagramm ist. Den nachfolgenden Code einfach in das SciPad-Fenster (Editor von Scilab) kopieren und starten. Es werden 2 Grafikfenster angezeigt, eines mit dem Bode-Diagramm und ein zweites mit der Sprungantwort. Man kann im Skript die Streckencharakteristik anpassen und verschiedene Reglerparameter ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ks=0.72;                            // Verstärkung der Strecke&lt;br /&gt;
T1=0.11;                            // Zeitkonstante 1&lt;br /&gt;
T2=0.005;                           // Zeitkonstante 2&lt;br /&gt;
Kp=18;                              // Proportionalbeiwert&lt;br /&gt;
Ki=170;                             // Integralbeiwert&lt;br /&gt;
Kd=0;                               // Differenzialbeiwert&lt;br /&gt;
 &lt;br /&gt;
s=poly(0,'s');                      // definiert s als Polynomvariable&lt;br /&gt;
P=(T1*s+1)*(T2*s+1);                // Streckencharakteristik&lt;br /&gt;
Gs=syslin('c',Ks,P)                 // Übertragungsfunktion der Strecke&lt;br /&gt;
&lt;br /&gt;
RZ=poly([Ki Kp Kd],'s','coeff')     // Zählerpolynom des Reglers&lt;br /&gt;
RN=poly([0 1],'s','coeff')          // Nennerpolynom des Reglers&lt;br /&gt;
Gr=syslin('c',RZ,RN)                // Übertragungsfunktion des Reglers&lt;br /&gt;
&lt;br /&gt;
G=Gr*Gs                             // Übertragungsfunktion gesamt&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,0);&lt;br /&gt;
xbasc(0);&lt;br /&gt;
bode([Gr;G;Gs],0.1,100,['Regler';'gesamt';'Strecke'])&lt;br /&gt;
&lt;br /&gt;
Gcl=G/(G+1)                         // geschlossene Regelschleife&lt;br /&gt;
t=0:0.001:0.2;&lt;br /&gt;
y=csim('step',t,Gcl);               // berechnet Sprungantwort&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,1);&lt;br /&gt;
xbasc(1);&lt;br /&gt;
plot2d(t,y,2);&lt;br /&gt;
xgrid();&lt;br /&gt;
xtitle(&amp;quot;Sprungantwort&amp;quot;,&amp;quot;sec&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Scicos====&lt;br /&gt;
Eine weitere Möglichkeit zur Simulation im Zeitbereich bietet Scicos. Die Modellierung geschieht mit einem grafischen Editor, in dem Blöcke mit vordefinierten oder selbstgemachten Funktionen miteinander verbunden werden. Ein einfaches Modell eines Regelkreises mit PID-Regler sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_anaReg.gif]]&lt;br /&gt;
&lt;br /&gt;
Der PID-Regler ist mit seinen 3 Zweigen (P, I und D) dargestellt. In den Verstärkerblöcken kann durch Ändern der Reglerparameter (KP, KI und KD) der Regler optimiert werden. Die Strecke ist in diesem Beispiel nur ein einzelner Block, in dem die Übertragungsfunktion eingegeben wird. Man kann die Strecke auch detaillierter mit einzelnen Funktionsblöcken darstellen. Ein Beispiel eines komplexen Blockschaltbilds für einen balancierenden Bot ist unter diesem [http://www.roboternetz.de/phpBB2/download.php?id=5082 Link] zu finden.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil der Simulation mit Scicos ist die Möglichkeit Nichtlinearitäten zu berücksichtigen und die Kombination von kontinuierlichen und diskreten Funktionen. Das heißt, man kann einen digitalen Regler mit seinen diskreten Schritten und eine analoge Strecke, als kontinuierliche Funktion eingegeben, zusammen simulieren. Scicos bietet sogar einen 'Scifunc'-Block, mit dem Rechenschritte des digitalen Reglers nachgebildet werden können. Damit wird sowohl das dynamische Verhalten, verursacht durch die Abtastzeit Ta, als auch die etwas unterschiedliche Dynamik durch die digitale Ausführung eines I- und D-Anteils richtig simuliert. Ein Beispiel für den Einsatz des Scifunc-Blocks ist in folgendem Blockschaltbild zu sehen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_digReg.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel: [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlregelung]] mit digitalem Regler&lt;br /&gt;
&lt;br /&gt;
Die globalen Variablen für die Reglerparameter und die Abtastzeit werden unter dem Menüpunkt „Edit - Context“ abgelegt.&lt;br /&gt;
 Kp=18;&lt;br /&gt;
 Ki=60;&lt;br /&gt;
 Ta=0.01;&lt;br /&gt;
In den Taktgeber für den digitalen Regler wird als Clock-Periode die Abtastzeit Ta eingetragen. In das Dialogfenster zum Scifunc-Block wird folgender Code zur Simulation des digitalen PI-Reglers eingetragen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z=z+Ki*Ta*u1&lt;br /&gt;
if z&amp;gt;5 then&lt;br /&gt;
z=5;&lt;br /&gt;
end&lt;br /&gt;
y1=Kp*u1+z&lt;br /&gt;
if y1&amp;gt;5 then&lt;br /&gt;
y1=5;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
z entspricht der Variable esum vom Beispiel des [[Regelungstechnik#Realisierung_mit_digitalem_Regler| digitalen Drehzahlreglers]]; u1 ist die Eingangsvariable und y1 die Ausgangsvariable des Scifunc-Blocks.&lt;br /&gt;
In den Block für die Strecke wird die Übertragungsfunktion eingetragen. Als Zähler die Verstärkung Ks, also 0.72. Im Nenner das Polynom (1+0.11*s) für die Charakteristik der Strecke. Mit ‚Simulate – Run’ wird die Simulation gestartet. Als Ergebnis sollte das Einschwingen der Stellgröße (schwarz) und der Regelgröße (grün), wie in folgender Abbildung erscheinen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort_DZR.png]]&lt;br /&gt;
&lt;br /&gt;
Man kann nun mit den Reglerparametern und verschiedenen Abtastzeiten spielen, um zu sehen wie sich die Änderungen auswirken. Zum Beispiel wird bei einer Verdopplung der Abtastzeit der Regelkreis bereits instabil.&lt;br /&gt;
&lt;br /&gt;
Diese Beispiele sind nur ein kurzer Auszug von den Möglichkeiten mit Scilab/Scicos für den Einsatz in der Regelungstechnik. Darüber hinaus ist es auch sehr gut geeignet bei anderen Optimierungsverfahren wie z.B. beim WOK-Verfahren (Wurzelortskurven) oder zur Analyse und Optimierung von modernen Reglern wie z.B. Zustandsregler und Kalmanfilter.&lt;br /&gt;
&lt;br /&gt;
===LTspice/SwitcherCad III===&lt;br /&gt;
Dieses Programm ist ein SPICE-Derivat von der Firma Linear Technology und ist unter den 2 Namen LTspice und SwitcherCad III bekannt. Der Einfachheit halber wird für die weitere Beschreibung hier nur der Name LTspice verwendet. Das Programm ist Freeware und kann unter diesem Link herunter geladen werden. http://ltspice.linear.com/software/LTspiceIV.exe&lt;br /&gt;
&lt;br /&gt;
LTspice ist ein Simulationsprogramm zur Analyse von elektronischen Schaltungen. Mit LTspice kann sowohl im Zeitbereich als auch im Frequenzbereich analysiert werden und bietet sich dadurch mit den entsprechenden Modellen auch für den Einsatz in der Regelungstechnik an. Wer sich bereits mit SPICE-Programmen auskennt, für den sollte es auch in der Regelungstechnik die 1.Wahl sein. &lt;br /&gt;
&lt;br /&gt;
Der Vorteil von LTspice ist die Möglichkeit einer sehr detaillierten Analyse, vorausgesetzt die Modelle sind auch so detailliert nachgebildet. Insbesondere für analoge Regler, wo die elektrische Schaltung direkt umgesetzt werden kann, empfiehlt sich der Einsatz von LTspice. Der Nachteil ist, LTspice ist nicht auf regeltechnische Belange ausgelegt worden und spezifische Symbole für die Regelungstechnik müssen selbst erstellt werden. Einige selbst erstellte Symbole für dynamische Grundelemente in LTspice sind hier abgebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTSpiceSymb.png]]&lt;br /&gt;
&lt;br /&gt;
Die 3 Symbole können [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=285 hier] heruntergeladen werden. Weitere Symbole können anhand dieser Beispiele sehr leicht selbst erstellt werden. Ein P-Glied kann durch eine spannungsgesteuerte Spannungsquelle (E-Source) oder Operationsverstärker mit einstellbarer Verstärkung dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
'''Analyse im Zeitbereich'''&lt;br /&gt;
&lt;br /&gt;
Das Beispiel des [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlreglers]] mit analogem Regler wird hier mit LTspice simuliert. Das Schaltbild des Regelkreises zeigt nachfolgende Abbildung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_TRAN.png]]&lt;br /&gt;
&lt;br /&gt;
Der Vergleicher (U1) und der analoge PI-Regler (U2) sind so dargestellt, wie es auch in Wirklichkeit ausgeführt werden kann. Da der PI-Regler in der Schaltung bereits invertiert, wurden die Eingänge am Vergleicher vertauscht, damit die Polarität wieder stimmt. Der Rest des Regelkreises wurde stark vereinfacht, kann aber nach Bedarf auch ausführlicher dargestellt werden. Das PT1-Glied U3 simuliert die Strecke des Regelkreises und der Verstärker U4 dient nur zur Umrechnung auf die Drehzahl. Zur Simulation im Zeitbereich wird auf den Führungswert w mit der Spannungsquelle V1 ein Sprung gegeben. In der Reglerschaltung wurde bewusst ein Operationsverstärker mit Versorgungsspannung gewählt, damit auch der Einfluss einer Begrenzung mit simuliert wird. Die Zeitbereichsanalyse wird durch den LTspicebefehl .TRAN erreicht. Die Sprungantwort (Tachospannung) bei diesem Regelkreis sieht dann folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tacho2.png]]&lt;br /&gt;
&lt;br /&gt;
Durch Ändern der Bauelemente R5, R6 und C1 kann man den Regler optimieren. Eine Umrechnung auf die Reglerparameter Kp und Ki ist mit folgenden Formeln möglich, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1)&lt;br /&gt;
&lt;br /&gt;
Mit einem Mausklick auf den entsprechenden Knoten in der Schaltung können noch weitere Signale, wie z.B. die Stellgröße y angezeigt werden. Durch Verändern der Versorgungsspannung V3, V4 kann man sich auch die Auswirkung der Begrenzung ansehen. &lt;br /&gt;
&lt;br /&gt;
'''Analyse im Frequenzbereich'''&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung des Bode-Diagramms der offenen Regelschleife in LTspice muss ein Trick angewendet werden, denn durch das Auftrennen der Regelschleife würde der Arbeitspunkt verloren gehen und dadurch die offene Schleife ohne Gegenkopplung an den Anschlag fahren.&lt;br /&gt;
&lt;br /&gt;
Mit einer zusätzlichen Spannungsquelle in der Schleife kann man dieses Problem umgehen. Die Schleife bleibt für den Erhalt des Arbeitspunktes weiterhin geschlossen und man kann trotzdem die Verstärkung der offenen Schleife durch das Verhältnis der Spannung vor und hinter der Spannungsquelle bestimmen. Das erweiterte Blockschaltbild sieht folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_AC.png]]&lt;br /&gt;
&lt;br /&gt;
V2 ist die zusätzliche Spannungsquelle für die AC-Analyse. Die Spannungsquelle V1 wird von Pulsform auf Gleichspannung umgestellt. Sie wird so gewählt, dass sich der gewünschte Arbeitspunkt einstellt. Durch den LTspicebefehl .AC wird die Analyse im Frequenzbereich veranlasst. Um das Bode-Diagramm des offenen Regelkreises darzustellen, wird als Kurve nicht ein einzelner Knoten ausgewählt, sondern das Verhältnis der Spannung vom Ende zum Anfang des Regelkreises, in unserem Beispiel also V(tacho)/V(x). Zur Anzeige kommt dann das Bode-Diagramm (grüne Kurve) der offenen Schleife, wie in der folgenden Abbildung zu sehen. Für den Amplitudengang (durchgezogene Linien) gilt die linke Skala in dB, für den Phasengang (gestrichelte Linien) die rechte Skala in Grad.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_Bode.png]]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist noch das Bode-Diagramm der Strecke (rote Kurve) zu sehen. Dies ist durch einfaches Hinzufügen einer weiteren Kurve mit dem Ausdruck V(tacho)/V(y) durchgeführt worden. &lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zur üblichen Darstellung des Bode-Diagramms eines offenen Regelkreises, beinhaltet das mit LTspice erstellte Bode-Diagramm auch die -180 Grad Phasendrehung der Gegenkopplung. Der Phasenrand ist deshalb nicht auf -180 Grad sondern auf 0 Grad zu beziehen. In unserem Beispiel ist der Phasenrand etwa 90 Grad, also ein sehr stabiler Regelkreis. Zu beachten ist, dass die Frequenzachse des Bode-Diagramms wie auch schon bei Scilab in der Einheit Hertz anstatt wie üblich in der Kreisfrequenzeinheit rad/s dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
==Modellierung eines Motors/Antriebs==&lt;br /&gt;
[[Bild:ESB_Motor.png|thumb|320px|Ersatzschaltbild DC-Motor]]&lt;br /&gt;
Der Motor ist ein oft verwendeter Aktuator in der Robotik. Deshalb wird hier am Beispiel des Gleichstrommotors mit Permanentmagnet (Nebenschlussmotor) die Modellbildung gezeigt. Zur Modellierung gibt es mehrere Möglichkeiten. Je nachdem wie detailliert die Simulation sein soll, kann man sich ein Modell, von sehr einfach bis sehr detailliert, auswählen. Zwei Zeitkonstanten bestimmen die Dynamik eines Gleichstrommotors. Eine davon ist die mechanische Zeitkonstante, die ist meistens die dominierende Zeitkonstante und wird durch das Trägheitsmoment J des Rotors verursacht. Die zweite Zeitkonstante ist die elektrische Zeitkonstante, sie wird durch die Induktivität L bestimmt. Bei einfachen Regelungen kann in den meisten Fällen die elektrische Zeitkonstante vernachlässigt werden, damit reduziert sich das Modell auf ein einzelnes PT1-Glied.&lt;br /&gt;
&lt;br /&gt;
'''Definition: Motor und Antrieb'''&lt;br /&gt;
&lt;br /&gt;
Als '''Motor''' wird hier der Motor alleine verstanden. Die Ausgangsgröße ist die Winkelgeschwindigkeit w (Drehzahl).&lt;br /&gt;
 &lt;br /&gt;
Als '''Antrieb''' wird hier der komplette Antrieb eines Fahrzeugs verstanden, also Motor inklusive Getriebe und Masse des Fahrzeugs. Für die Dynamik ist nicht nur das Trägheitsmoment des Motors sondern auch die Masse des Fahrzeugs verantwortlich. Die Ausgangsgröße der Einheit „Antrieb“ ist die Geschwindigkeit v.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellten Modelle gelten sowohl für einen Motor als auch für einen kompletten Antrieb, wenn man die Elastizität und das Spiel des Getriebes vernachlässigt.&lt;br /&gt;
&lt;br /&gt;
===Einfaches Modell mit PT1-Glied===&lt;br /&gt;
Die einfachste Art einen Motor oder Antrieb zu simulieren, ist mit einem PT1-Glied als Modell. Das Simulationsprogramm [[Regelungstechnik#Scicos|Scicos]] bietet dazu einen Block zur Eingabe der Übertragungsfunktion (num(s)=Zähler, den(s)=Nenner der Übertragungsfunktion).&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G(s)=\frac{K}{1+Ts}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |Beispiel:&lt;br /&gt;
 num(s) = K = 0.72&lt;br /&gt;
 den(s) = 1 + Ts = 1 + 0.11s&lt;br /&gt;
 |[[Bild:Scicos_TF.png]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Wird nicht nur das Ausgangssignal, also die Geschwindigkeit oder Drehzahl in der Simulation benötigt, sondern auch die Beschleunigung, dann kann nachfolgendes Modell verwendet werden. Dieses Modell ist der Differentialgleichung eines PT1-Glieds nachempfunden und liefert das gleiche Ergebnis wie vorheriges Modell, bietet aber noch den Zugriff auf das Beschleunigungssignal.&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Differentialgleichung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;v'=\frac{K}{T}U-\frac{1}{T}v&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |&lt;br /&gt;
 v = Geschwindigkeit&lt;br /&gt;
 v’= Beschleunigung (Ableitung von v)&lt;br /&gt;
 K = Übertragungsmaß&lt;br /&gt;
 T = Zeitkonstante&lt;br /&gt;
 U = Eingangsgröße (z.B. Spannung)&lt;br /&gt;
 |[[Bild:Antrieb_PT1.png|thumb|Einfaches Modell eines Antriebs]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Die beiden Parameter K und T müssen ausgemessen werden, wenn sie nicht bekannt sind. Die Zeitkonstante T kann in einem Anlaufversuch ermittelt werden. Dazu wird auf den Motor ein Spannungssprung gegeben und die Sprungantwort am Ausgang nachgemessen. Bei einem Antrieb erspart diese Methode die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente (Motor, Getriebe, Fahrzeug). Bei der Ermittlung des Übertragungsmaß K ist zu beachten, dass sich möglicherweise der Motor durch starke Reibung erst ab einer bestimmten Spannung dreht. Hier ist die Steigung der Kennlinie mit delta&amp;amp;nbsp;v&amp;amp;nbsp;/&amp;amp;nbsp;delta&amp;amp;nbsp;U auszuwerten, wie im folgenden Bild zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_stat.png]]&lt;br /&gt;
&lt;br /&gt;
Die einfachen Modelle gelten nur für den linearen Teil der Kennlinie. Soll auch die Nichtlinearität durch Reibung modelliert werden, dann sind detailliertere Modelle, wie im Folgenden beschrieben, zu verwenden. Die Auswirkung einer Haftreibung ist auch in dem Geschwindigkeitsdiagramm durch die Hysterese in der Kennlinie zu sehen. Beim Hochfahren der Ansteuerspannung bewegt sich das Fahrzeug erst ab ca. 1.25V, während beim Herunterfahren der Ansteuerspannung das Fahrzeug noch bis 0.75V rollt und erst unter 0.75V stehen bleibt.&lt;br /&gt;
&lt;br /&gt;
===Detailliertes Modell===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Motor_Model.png|thumb|350px|Detailliertes Motormodell]]&lt;br /&gt;
Ein detailliertes Motormodell ist rechts in dem Bild zu sehen. Es hat auf der linken Seite den elektrischen Teil mit den Parametern R (Widerstand) und L (Induktivität) und auf der rechten Seite den mechanischen Teil mit den Blöcken Trägheitsmoment und Reibung. Der elektrische Teil liefert das Stromsignal i, welches mit der Motorkonstante Km in das Drehmoment M umgerechnet wird. Mit dem folgenden Summierglied kann über einen zusätzlichen Eingang auch ein extern angreifendes Lastmoment mit simuliert werden. Am Ausgang des mechanischen Teils steht die Winkelgeschwindigkeit w in der Einheit [rad/s] bzw. über den Umrechnungsfaktor 9.55 die Drehzahl in [Upm] zur Verfügung. Die Reibung wird in einem nichtlinearen Block mittels Lookup-Table simuliert. In der einschlägigen Literatur wird die Reibung meistens mit einem Dämpfungsfaktor (linear) simuliert, was einer viskosen Reibung entspricht. Das passt aber nicht so gut für Kleinmotoren, da überwiegt vor allem die trockene Reibung. Die trockene Reibung hat ein konstantes Bremsmoment wenn sich der Motor dreht (unabhängig von Drehzahl, Vorzeichen abhängig von Drehrichtung). So eine Funktion kann sehr einfach mit einer Lookup-Table realisiert werden. Die Lookup-Table kann auch dazu verwendet werden, Mischformen von trockener, viskoser und turbulenter Reibung und sogar noch Haftreibung in einem Block zu simulieren, wenn man will.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Herstellern, wie z.B. Faulhaber und Maxon, kann man die für das Modell nötigen Parameter im Datenblatt finden. Das Bremsmoment der Reibung berechnet sich aus dem Leerlaufstrom wie folgt: Bremsmoment&amp;amp;nbsp;=&amp;amp;nbsp;Motorkonstante&amp;amp;nbsp;*&amp;amp;nbsp;Leerlaufstrom &lt;br /&gt;
&lt;br /&gt;
Falls die Daten nicht verfügbar sind, muss man sie selbst ausmessen. Eine Hilfestellung zur Bestimmung der Motorkonstante und des Trägheitsmoments gibt es hier:&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=96750&amp;amp;highlight=#96750&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/viewtopic.php?t=12793&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_Modell.png|thumb|350px|Modell eines Antriebs]]&lt;br /&gt;
&lt;br /&gt;
Das detaillierte Motormodell kann auch für einen Antrieb verwendet werden, wenn man eine starre Kopplung zwischen Motor und Antriebsrad voraussetzt, also Elastizität und Spiel des Getriebes vernachlässigt. Anstelle der rotatorischen Kenngrößen (Drehmoment M, Trägheitsmoment J, Winkelgeschwindigkeit w) werden die translatorischen Kenngrößen (Kraft F, Masse m, Geschwindigkeit v) eingesetzt. Das Drehmoment wird mittels Getriebeübersetzung ü und Radius r des Antriebsrades in die entsprechende Vortriebskraft umgerechnet. Daraus ergibt sich die Kraftkonstante Kf, die für das Antriebsmodell verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Die Umrechnung ist: Kf = Km * ü/r&lt;br /&gt;
&lt;br /&gt;
Bei der Trägheitsmasse m muss neben der Masse des Fahrzeugs auch das Trägheitsmoment des Motors mit berücksichtigt werden. Die Umrechnung von Trägheitsmoment in eine äquivalente Masse = J * (ü/r)²&lt;br /&gt;
&lt;br /&gt;
Der Reibungsblock in diesem Modellbeispiel enthält eine Mischform aus Haftreibung, trockener und viskoser Reibung, wie sie typisch für einen Kleinbot mit 2 Antriebsrädern und einem Gleitpin ist.&lt;br /&gt;
&lt;br /&gt;
==Beispiel: Drehzahlregelung==&lt;br /&gt;
Es wird ein Gleichstrommotor in der Drehzahl geregelt. Als Sensor ist ein Tachogenerator vorhanden, der direkt auf der Motorwelle sitzt. Das System ist in einem kleinen Modellfahrzeug eingebaut und wird zur Geschwindigkeitsregelung eingesetzt, da die Drehzahl proportional zur Geschwindigkeit ist.&lt;br /&gt;
&lt;br /&gt;
Das Funktionsschaltbild sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl1.gif&lt;br /&gt;
&lt;br /&gt;
Als Störgröße können unterschiedliche Reibwerte oder Steigung und Gefälle rückwirkend über das Getriebe die Drehzahl beeinflussen. Das Getriebe und die Last sind zwar außerhalb der Regelschleife, beeinflussen aber durch die feste Kopplung des Getriebes die Dynamik des Regelkreises. Durch die starre Kopplung kann das Trägheitsmoment des Motors und die Masse des Fahrzeugs zusammengefasst werden. Das Gleiche gilt auch für die Reibwerte. Damit vereinfacht sich die Modellierung und das Blockschaltbild reduziert sich auf folgende Schaltung:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl2.gif&lt;br /&gt;
&lt;br /&gt;
Zur Ermittlung des dynamischen Verhaltens der Regelstrecke wird die Sprungantwort gemessen. Dazu wird auf den Eingang der Regelstrecke (Stellglied) ein Spannungssprung gegeben und die Antwort am Ausgang des Tachogenerators nachgemessen. Diese Methode erspart die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente der Regelstrecke (Motor, Getriebe, Fahrzeug). Die Messung ergab folgende Sprungantwort der Regelstrecke:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/tacho.gif&lt;br /&gt;
&lt;br /&gt;
Wie zu erwarten, ist die Sprungantwort annähernd ein Verzögerungsglied 1.Ordnung. Die abgelesene Zeitkonstante ist 0.11s. Die Verstärkung der Regelstrecke ist Ks = 0.72. Das Übertragungsmaß des Tachogenerators ist 1V pro 2480Upm. Damit kann auf die Drehzahl rückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da die Regelstrecke nur aus einem PT1-Glied besteht, könnte eine analoge Regelung fast beliebig schnell gemacht werden. Wegen der Begrenzung bringt aber das Ausreizen der Optimierung für das Führungsverhalten nicht viel, nur für das Störverhalten wäre eine schnellere Regelung sinnvoll. Um aber einen Vergleich zwischen analogem und digitalem Regler anstellen zu können wird eine Parametrierung gewählt, die auch für den digitalen Regler mit seiner Totzeit noch stabil ist. Es wird deshalb auch auf einen D-Anteil im Regler verzichtet und nur ein PI-Regler realisiert. Das vereinfachte Blockschaltbild mit den dynamischen Elementen sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl3.gif&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung wurde ein analoger als auch ein digitaler Regler realisiert. Die Parametrierung des analogen Reglers wurde mit dem Programm [[Regelungstechnik#LTspice.2FSwitcherCad_III| LTspice]] durchgeführt. Es bot sich an, da die analoge Reglerschaltung exakt simuliert werden konnte. Für die Optimierung des digitalen Reglers wurde dann [[Regelungstechnik#Scicos| Scicos]] verwendet. &lt;br /&gt;
&lt;br /&gt;
===Realisierung mit analogem Regler===&lt;br /&gt;
Die elektrische Schaltung für einen analogen PI-Regler ist in der nächsten Abbildung zu sehen. Der erste Operationsverstärker vergleicht den Sollwert w mit dem Istwert x. Der zweite Operationsverstärker bildet den PI-Regler. Die Werte R5, R6 und C1 sind für die Charakteristik des PI-Reglers zuständig. Mit R6 kann der P-Anteil und mit C1 der I-Anteil eingestellt werden. Die Optimierung der Werte wurde empirisch in einer Simulation mit LTspice durchgeführt. Da die Schaltung des PI-Reglers invertiert, wurden zum Ausgleich am Vergleicher die Eingänge an U1 vertauscht, so dass sich über die gesamte Schaltung wieder die richtige Polarität ergibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Analogregler.png]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen auf Kp und Ki können diese Formeln verwendet werden, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5 = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1) = 147&lt;br /&gt;
&lt;br /&gt;
===Realisierung mit digitalem Regler===&lt;br /&gt;
Im digitalen Regelkreis wird der Istwert '''x''' vom Tachogenerator mit einem A/D-Wandler digitalisiert. Der Sollwert '''w''' wird dem µC als digitaler Wert übergeben. Die Stellgröße '''y''' entspricht dem PWM-Wert für den Motortreiber. Um zum analogen Regler vergleichbar zu sein, wurde sowohl für den A/D-Wandler als auch für den PWM-Steller eine 8-Bit-Breite vorgesehen. Damit ist die Verstärkung in beiden Fällen gleich und analoger und digitaler Regler besser vergleichbar.&lt;br /&gt;
&lt;br /&gt;
Eigentlich könnte man bei kleiner Abtastzeit direkt die Parametrierung des analogen Reglers für die digitale Realisierung übernehmen. Aber es gibt doch kleine Unterschiede in der Dynamik zwischen analoger und digitaler Ausführung und um sicher zu gehen, dass die gewählte Abtastzeit einen nicht zu großen Einfluss hat, wird noch einmal mit [[Regelungstechnik#Scicos| Scicos]] nachoptimiert. Mit einer Abtastzeit Ta = 10ms und den Parametern des analogen Reglers ergibt sich ein Überschwingen, das nur sehr langsam auf den Endwert abklingt. Durch Verringern des I-Anteils auf 60 wird ein optimales Einschwingen für den digitalen Regler erreicht. Die Parameter sind:&lt;br /&gt;
&lt;br /&gt;
Kp = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 60&lt;br /&gt;
&lt;br /&gt;
Ta = 0.01&lt;br /&gt;
&lt;br /&gt;
Zur Umsetzung in einen Code wurde die Programmiersprache C gewählt. Da der Code sehr einfach ist, sollte es auch kein Problem sein, den Code als Beispiel für andere Sprachen zu verwenden. Der Algorithmus wird im Takt der Abtastzeit, also alle 10ms aufgerufen. In der Reglergleichung kann zur Vereinfachung das Produkt Ki*Ta durch eine Ersatzvariable, die gleich das Ergebnis aus dem Produkt 60*0.01 = 0.6 hat, ersetzt werden. Zum besseren Verständnis wurde es hier beim Ki*Ta belassen. Um einen Windup-Effekt zu verhindern, wird die Summenbildung esum auf +-400 begrenzt. Der Wert wurde so gewählt, dass noch eine volle Aussteuerung durch den I-Anteil möglich ist. Zum Schluss wird die Stellgröße y auf die mögliche Aussteuerung des Stellglieds (0...255) begrenzt.&lt;br /&gt;
&lt;br /&gt;
'''Programmbeispiel digitaler PI-Regler:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	e = w - x;				//Vergleich&lt;br /&gt;
	esum = esum + e;			//Integration I-Anteil&lt;br /&gt;
	if (esum &amp;lt; -400) {esum = -400;}	        //Begrenzung I-Anteil&lt;br /&gt;
	if (esum &amp;gt; 400) {esum = 400;}&lt;br /&gt;
	y = Kp*e + Ki*Ta*esum;			//Reglergleichung&lt;br /&gt;
	if (y &amp;lt; 0) {y = 0;}			//Begrenzung Stellgröße&lt;br /&gt;
	if (y &amp;gt; 255) {y = 255;}&lt;br /&gt;
	PWM = y;				//Übergabe Stellgröße&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Lageregelung ==&lt;br /&gt;
Unter einer Lageregelung versteht man die Positionierung von Objekten. Als Beispiel soll hier ein kleiner Bot mit Radencoder eine bestimmte Weglänge fahren. Gegenüber der Drehzahl- oder Geschwindigkeitsregelung ist bei der Lageregelung noch ein zusätzlicher Integrator in der Strecke vorhanden. Die gesamte Strecke ist damit ein I-Glied mit Verzögerung. Laut Tabelle im Abschnitt „Dimensionierung des Reglers“ ist dafür ein PD-Regler gut geeignet. Der PD-Regler wird digital ausgeführt, zur Simulation und Parametrierung bietet sich deshalb Scicos an. &lt;br /&gt;
&lt;br /&gt;
Da bei einer Lageregelung der Geschwindigkeitsbereich von Null aus geht, also über den nichtlinearen Bereich geht, sollte auch in der Simulation die Nichtlinearität berücksichtigt sein. Für das Beispiel wird deshalb das Modell eines Antriebs mit Haft- und Gleitreibung genommen, wie es unter &amp;quot;Modellierung eines Antriebs – detailliertes Modell&amp;quot; bereits vorgestellt wurde. Im Scicos-Modell ist der Antrieb der Übersichtlichkeit wegen als Superblock ausgeführt. Das Blockschaltbild des Antriebs im Detail ist [http://www.roboternetz.de/wissen/images/7/73/Antrieb_Modell.png hier] zu sehen. Die Daten sind:&lt;br /&gt;
&lt;br /&gt;
R = 16 Ohm; L = 6 mH; m = 0.31 kg; Kf = 6.6 N/A&lt;br /&gt;
&lt;br /&gt;
Als Sensor kommt ein Inkrementalgeber zum Einsatz, allerdings muss der richtungssensibel sein, sonst ist keine Lageregelung möglich. Der Sensor wird in Scicos mit der Rundungsformel (round(u1*500)) simuliert. Das ergibt bei einer Auflösung von 2mm ganzzahlige Schritte, wie es auch die Hardware (Inkrementalgeber mit nachfolgendem Zähler) in Wirklichkeit macht.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lageregelung.png]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Regler folgt ein Block mit der Verstärkung (5/255), der den PWM-Wert auf die Ansteuerspannung für den Motor umsetzt. Der Bruch 5/255 entspricht der Ansteuerspannung von 5V bei PWM=255. Der PD-Regler kann damit in Scicos exakt so simuliert werden, wie er schlussendlich auch als C-Code umgesetzt wird. Dazu wird der Code des PD-Reglers als Funktion in den Scifunc-Block eingegeben. Der Code ist etwas unterschiedlich zum C-Code des realen Bots, da die Syntax in Scicos doch geringfügig anders ist und die Eingangs- und Ausgangsvariablen nur bestimmte Bezeichnungen haben dürfen. Im nachfolgenden Codefenster sind beide Varianten im Vergleich zu sehen.&lt;br /&gt;
{|&lt;br /&gt;
 | '''Scifunc-Code:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y1=Kp*u1+Kd/Ta*(u1-z);&lt;br /&gt;
z=u1;&lt;br /&gt;
if y1&amp;gt;255 then&lt;br /&gt;
y1=255;&lt;br /&gt;
end&lt;br /&gt;
if y1&amp;lt;-255 then&lt;br /&gt;
y1=-255;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''C-Code für µC:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
e = w - x;&lt;br /&gt;
y = Kp*e + Kd/Ta*(e-ealt);&lt;br /&gt;
ealt = e;&lt;br /&gt;
if (y &amp;gt; 255) {&lt;br /&gt;
    y = 255;&lt;br /&gt;
    }&lt;br /&gt;
if (y &amp;lt; -255) {&lt;br /&gt;
    y = -255;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''Kommentar:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Vergleich&lt;br /&gt;
PD-Reglergleichung&lt;br /&gt;
alten Wert speichern&lt;br /&gt;
&lt;br /&gt;
pos. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
neg. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
In der praktischen Umsetzung des C-Codes wird man den Bruch Kd/Ta durch eine Ersatzvariable oder Konstante ersetzen. Dabei ergibt sich (wie in diesem Beispiel 2/0.01 = 200) meistens ein ganzzahliger Wert, was sich positiv auf die Rechenzeit auswirkt.&lt;br /&gt;
&lt;br /&gt;
Für die Abtastzeit Ta wurde 10ms gewählt. Das ist einerseits nicht zu schnell für einen µC und andererseits nicht zu lang, um die Regelung unnötig zu verlangsamen. Die Parametrierung von Kp und Kd erfolgte empirisch durch Probieren in der Simulation. Begonnen wurde mit einem reinen P-Regler und kleinem P-Anteil (Kp=1, Kd=0). In groben Schritten wurde Kp solange erhöht, bis sich deutlich Überschwinger zeigten. Dann wurde ein D-Anteil hinzugefügt und Kd so variiert, dass der Überschwinger verschwindet. Mit ein bisschen Feintuning ergaben sich so die Werte Kp=61 und Kd=2. Das Simulationsergebnis für Ansteuerspannung, Geschwindigkeit und Weg sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lage_antwort.png]]&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:Waste|Waste]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[SwitcherCAD-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/viewtopic.php?t=11818 Post: Line follower with PID controller]&lt;br /&gt;
*[http://www.scicos.org/ Scicos Homepage]&lt;br /&gt;
* [http://www.scicoslab.org/  ScicosLab Homepage]&lt;br /&gt;
* [http://www.scilab.org/ Scilab Homepage]&lt;br /&gt;
* [http://ltspice.linear.com/software/swcadiii.exe LTspice / SwitcherCAD III Download]&lt;br /&gt;
* [http://www.kahlert.com/web set_download.php demo version of WinFACT 7]&lt;br /&gt;
* [http://www.physi.uni-heidelberg.de/fp/anleitg/E01.pdf instructions for electronic placement, the last part is based PID controller]&lt;br /&gt;
* [http://www.simapp.com/ SimApp website] with trial&lt;br /&gt;
* [http://www.expertcontrol.com/ ExpertControl Homepage, Automatische Reglerauslegung mit ecICP] ecICP-Trial über Support-Seite verfügbar&lt;br /&gt;
* [http://www.me.th-mittelhessen.de/personen/professoren/orlowski/simulation-regelungstechnik/ TH-Mittelhessen Prof. Peter F. Orlowski, Simulationsprogramm SIMLER-PC]&lt;br /&gt;
&lt;br /&gt;
[[Category: Microcontroller]]&lt;br /&gt;
[[Category: Software]]&lt;br /&gt;
[[Category: Elektronik]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pt2bglied.gif&amp;diff=25241</id>
		<title>Datei:Pt2bglied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pt2bglied.gif&amp;diff=25241"/>
				<updated>2014-09-13T08:00:34Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/pt2bglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/pt2bglied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pt2aglied.gif&amp;diff=25240</id>
		<title>Datei:Pt2aglied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pt2aglied.gif&amp;diff=25240"/>
				<updated>2014-09-13T08:00:09Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/pt2aglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/pt2aglied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pt1glied.gif&amp;diff=25239</id>
		<title>Datei:Pt1glied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pt1glied.gif&amp;diff=25239"/>
				<updated>2014-09-13T07:59:30Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/pt1glied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/pt1glied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Ttglied.gif&amp;diff=25238</id>
		<title>Datei:Ttglied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Ttglied.gif&amp;diff=25238"/>
				<updated>2014-09-13T07:58:46Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/ttglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/ttglied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Iglied.gif&amp;diff=25237</id>
		<title>Datei:Iglied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Iglied.gif&amp;diff=25237"/>
				<updated>2014-09-13T07:58:07Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/iglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/iglied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Pglied.gif&amp;diff=25236</id>
		<title>Datei:Pglied.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Pglied.gif&amp;diff=25236"/>
				<updated>2014-09-13T07:57:37Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von http://www.roboternetz.de/wiki/uploads/Main/pglied.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von http://www.roboternetz.de/wiki/uploads/Main/pglied.gif&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25235</id>
		<title>Regelungstechnik</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Regelungstechnik&amp;diff=25235"/>
				<updated>2014-09-13T07:50:05Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: /* Digitaler Regler */ wikify digreg.gif&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;'''Regelungen''' sind ein Bestandteil unseres Lebens und das nicht nur seit Erfindung der Dampfmaschine. &lt;br /&gt;
&lt;br /&gt;
Allein schon der aufrechte Gang funktioniert nur mit Regelung. Dabei wirken die Sinne als Sensoren, das Gehirn als Regler und die Muskeln als Aktuatoren. Weitere Regelungen in unserem Körper sind z.B. die Konstanthaltung der Körpertemperatur, der Blutdruck, die Anpassung der Pupille auf Helligkeitsänderungen usw.&lt;br /&gt;
&lt;br /&gt;
Im technischen Zeitalter ist der erste geschichtlich bedeutende Regler der Fliehkraftregler von James Watt, der für die Drehzahlregelung seiner Dampfmaschine eingesetzt wurde. Seitdem ist die Regelungstechnik aus keinem Technikbereich mehr wegzudenken. Die Regelungstechnik begegnet uns im täglichen Leben auf Schritt und Tritt: Der Temperaturregler der Zentralheizung, der Temperaturregler des Kühlschranks, der Regler für die Belichtungsautomatik im Fotoapparat, das ABS-System im Auto und die Netzspannungs- und Frequenzregelung des europäischen Versorgungsnetzes sind nur einige wenige Beispiele aus diesem Bereich. &lt;br /&gt;
&lt;br /&gt;
''Autor Waste''&lt;br /&gt;
&lt;br /&gt;
==Einleitung==&lt;br /&gt;
&lt;br /&gt;
Der Begriff ''Regelung'' ist zu unterscheiden von dem im allgemeinen Sprachgebrauch oft synonym gebrauchten Begriff der ''Steuerung''. Das Steuern ist ein rein vorwärts gerichteter Prozess ohne Rückkopplung. Die Ausgangsgröße wird dabei nicht überwacht und kann sich durch Störungen von außen verändern. Ein Beispiel ist die Steuerung eines Motors mit einer einstellbaren Spannung. Durch Laständerungen wird sich die Drehzahl des Motors ändern. Soll nun die Drehzahl konstant gehalten werden, bedarf es einer Rückkopplung um über die Spannung die Drehzahl anzupassen. Diese Rückkopplung ist das Kennzeichen einer Regelung.&lt;br /&gt;
&lt;br /&gt;
Das Regeln ist ein Vorgang, bei dem die Ausgangsgröße, im Beispiel die Drehzahl, fortlaufend überwacht wird und bei Abweichung über die Stellgröße, im Beispiel die Spannung, korrigiert wird. Der sich dabei ergebende Wirkungsablauf findet in einem geschlossenen Kreis, dem Regelkreis, statt.&lt;br /&gt;
&lt;br /&gt;
==Der Regelkreis==&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis1.png|right|thumb|300px|Ein Regelkreis (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Das Prinzip einer Regelung ist das fortlaufende: '''Messen – Vergleichen – Stellen'''&lt;br /&gt;
&lt;br /&gt;
;Messen: Die Regelgröße wird direkt oder mittels Sensoren gemessen.&lt;br /&gt;
;Vergleichen: Der Wert der Regelgröße wird mit dem Sollwert verglichen. Die Differenz ist die ''Regelabweichung''.&lt;br /&gt;
;Stellen: Aus der Regelabweichung wird unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke die ''Stellgröße'' bestimmt.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis2.png|thumb|350px|Wirkunsweise einer Regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis dient dazu, eine vorgegebene physikalische Größe, die ''Regelgröße'', auf einen gewünschten Wert (Sollwert) zu bringen und dort zu halten, unabhängig von eventuell auftretenden Störungen.&lt;br /&gt;
Um die Regelungsaufgabe zu erfüllen, muss der Augenblickswert der Regelgröße – der Istwert – gemessen und mit dem Sollwert verglichen werden. Bei auftretenden Abweichungen muss in geeigneter Art und Weise nachgestellt werden.&lt;br /&gt;
&lt;br /&gt;
Um nun diese Aufgabe technisch zu lösen, gibt es die Regelungstechnik. Sie baut im wesentlichen auf die mathematische Beschreibung und Modellbildung des Systems Regelkreis. Zur Modellierung, Beschreibung und Simulation werden Blockschaltbilder mit diskreten Signalgliedern verwendet.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis3.png|thumb|350px|Beispiel einer Geschwindigkeits&amp;amp;shy;regelung]]&lt;br /&gt;
&lt;br /&gt;
Ein typisches Beispiel für einen Regelkreis – eine Geschwindigkeits&amp;amp;shy;regelung – wird im nebenstehenden Bild gezeigt. Die Sollgeschwindigkeit ist 80 km/h. Durch eine äußere Störung, in dem Fall eine Steigung, verlangsamt sich das Fahrzeug auf 70 km/h. Die Abweichung wird durch das Tachometer erfasst. Als Korrekturmaßnahme wird mehr Gas gegeben, um wieder auf die Sollgeschwindigkeit von 80 km/h zu kommen.&lt;br /&gt;
&lt;br /&gt;
{{Absatz}}&lt;br /&gt;
&lt;br /&gt;
=== Begriffe ===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Regelkreis4.png|right]]&lt;br /&gt;
&lt;br /&gt;
Ein Regelkreis besteht entsprechend des vereinfachten Blockschaltbildes, wie es oft in der Regelungstechnik verwendet wird, aus den Hauptteilen ''Regler'' und ''Regelstrecke'':&lt;br /&gt;
&lt;br /&gt;
;Regler: Ist der Teil des Regelkreises, der unter Berücksichtigung der dynamischen Eigenschaften der Regelstrecke aus der Regelabweichung die Korrekturmaßnahmen zum Ausregeln ergreift.&lt;br /&gt;
&lt;br /&gt;
;Regelstrecke: Ist der Teil des Regelkreises, der vom Regler ausgeregelt werden soll.&lt;br /&gt;
&lt;br /&gt;
;Führungsgröße (Sollwert) w: Vorgegebener Wert, auf dem die Regelgröße durch die Regelung gehalten werden soll. Sie ist eine von der Regelung nicht beeinflusste Größe und wird von außen zugeführt.&lt;br /&gt;
&lt;br /&gt;
;Regelgröße (Istwert) x: Ist die Ausgangsgröße der Regelstrecke, die zum Zweck des Regelns erfasst und zum Vergleich rückgeführt wird. In vielen Fällen ist in der Rückführung noch eine Messeinrichtung (Sensor) gezeichnet, die den Istwert erfasst, hier der Einfachheit halber weggelassen.&lt;br /&gt;
&lt;br /&gt;
;Regelabweichung e: Differenz zwischen Führungsgröße und Regelgröße '''e = w – x''', bildet die eigentliche Eingangsgröße des Reglers.&lt;br /&gt;
&lt;br /&gt;
;Stellgröße y: Ausgangsgröße der Regeleinrichtung und zugleich Eingangsgröße der Strecke. Sie überträgt die steuernde Wirkung des Reglers auf die Strecke.&lt;br /&gt;
&lt;br /&gt;
;Störgröße z: Eine von außen wirkende Größe, die eine Änderung des Istwertes der Regelgröße bewirkt und einen Regelvorgang auslöst.&lt;br /&gt;
&lt;br /&gt;
==Die Regelstrecke==&lt;br /&gt;
Die Regelstrecke stellt den zu regelnden Teil bzw. den zu regelnden Prozess dar und umfasst normalerweise eine Reihe von einzelnen Gliedern. Die Glieder werden entsprechend ihrem Zeitverhalten charakterisiert. Um das Zeitverhalten herauszufinden, legt man an den Eingang ein Testsignal an und zeichnet die Antwort auf. Im einfachsten Fall wird der Eingang mit einer sprunghaften Änderung beaufschlagt. Die Antwort auf die sprunghafte Änderung der Eingangsgröße wird Sprungantwort genannt und gibt Aufschluss über die Art der Regelstrecke und kann eventuell bereits genutzt werden, um die Parameter der Regelstrecke zu bestimmen.&lt;br /&gt;
&lt;br /&gt;
Für den Aufbau eines gut funktionierenden Regelkreises und die Auslegung von Reglern ist es eine Voraussetzung zu wissen, wie die Regelstrecke reagiert. Ohne ein genaues Wissen um das dynamische Verhalten der Regelstrecke ist es nicht möglich geeignete Regler auszuwählen und diese zu parametrieren.&lt;br /&gt;
&lt;br /&gt;
Die wichtigsten dynamischen Grundelemente zur Charakterisierung der Regelstrecke sind nachfolgend aufgelistet. Jedes Element wird mit einem Block dargestellt und darin durch ein Symbol oder der stilisierten Sprungantwort gekennzeichnet.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Proportionalglied (P-Glied)===&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pglied.gif&lt;br /&gt;
&lt;br /&gt;
Die einfachste Art einer Regelstrecke.&lt;br /&gt;
;Beispiele: Hebel, Getriebe, Verstärker, Spannungsteiler, Sensoren bei denen das Zeitverhalten vernachlässigt werden kann&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Integrator (I-Glied)===&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/iglied.gif&lt;br /&gt;
&lt;br /&gt;
Strecke ohne Ausgleich, ist häufig in Regelstrecken vorhanden.&lt;br /&gt;
;Beispiele: Beschleunigung → Geschwindigkeit → Weg, Strom → Kondensatorspannung&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 0.Ordnung (Totzeitglied)===&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/ttglied.gif&lt;br /&gt;
&lt;br /&gt;
Entsteht durch Laufzeiten von Material oder Signalen. Je größer die Verzögerungszeit einer Regelstrecke ist, um so schwieriger ist sie zu regeln. &lt;br /&gt;
;Beispiele: Förderband, Rechenzeit, A/D-Wandler&lt;br /&gt;
&lt;br /&gt;
Nicht zu verwechseln mit der Totzeit, die durch das asynchrone Auftreten eines Ereignisses auf einen Zyklus entsteht. Vom Verzögerungsglied 0.Ordnung unterscheidet sich diese dadurch, daß sie mit einer gleichverteilten Wahrscheinlichkeit zwischen &amp;quot;gar nicht&amp;quot;  und dem gesamten Umfang auftritt. Diese Totzeit ist mechanisch mit einem Spiel vergleichbar das &amp;quot;gar nicht&amp;quot; bis zum vollen Umfang zu einem Fehler beiträgt. &lt;br /&gt;
;Beispiele: Erkennen eines Signals an einem Mikroprozessor&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 1.Ordnung (PT1-Glied)===&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pt1glied.gif&lt;br /&gt;
&lt;br /&gt;
Viele einfache Regelstrecken haben ein solches Verhalten bzw. können näherungsweise damit beschrieben werden. Ist ein P-Glied mit nicht vernachlässigbarem Zeitverhalten.&lt;br /&gt;
;Beispiele: Gleichstrommotor (Spannung → Drehzahl), näherungsweise; Widerstand-Kondensator-Schaltung (RC-Glied)&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===Verzögerungsglied 2.Ordnung (PT2-Glied)===&lt;br /&gt;
Man unterscheidet schwingungsfähige und nicht schwingungsfähige PT2-Glieder. Zur Charakterisierung gibt es die Parameter Dämpfung D und Eckfrequenz w&amp;lt;sub&amp;gt;0&amp;lt;/sub&amp;gt; oder die Zeitkonstanten T&amp;lt;sub&amp;gt;1&amp;lt;/sub&amp;gt; und T&amp;lt;sub&amp;gt;2&amp;lt;/sub&amp;gt;. Für Dämpfung D&amp;lt;1 ist es schwingungsfähig.&lt;br /&gt;
&lt;br /&gt;
'''Schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pt2aglied.gif&lt;br /&gt;
;Beispiele: Mechanischer Schwinger (Feder-Masse-System), elektrischer Schwingkreis (RLC-Kreis)&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Nicht schwingfähiges PT2-Glied:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pt2bglied.gif&lt;br /&gt;
;Beispiele: Zwei hintereinander geschaltete PT1-Glieder, Gleichstrommotor (Spannung → Drehzahl) mit berücksichtigter Induktivität&lt;br /&gt;
&lt;br /&gt;
==Der Regler==&lt;br /&gt;
Der Regler hat die Aufgabe, die Regelgröße zu messen, sie mit dem Sollwert zu vergleichen und bei Abweichungen die Stellgröße so zu verändern, dass Soll- und Istwert der Regelgröße wieder übereinstimmen bzw. die Differenz minimal wird.&lt;br /&gt;
&lt;br /&gt;
Die Wahl eines bestimmten Reglertyps richtet sich nach dem geforderten Zeitverhalten und der geforderten Regelgenauigkeit der Regelstrecke. Nachfolgend finden Sie eine Zusammenfassung der wichtigsten klassischen Reglertypen:&lt;br /&gt;
&lt;br /&gt;
===P-Regler===&lt;br /&gt;
Der proportionalwirkende Regler multipliziert die Regelabweichung mit seinem Verstärkungsfaktor '''Kp''' und gibt das Ergebnis unverzögert weiter. Er unterscheidet sich prinzipiell nicht vom dynamischen Element P-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der P-geregelte Kreis ist einfach und mittelschnell im Vergleich zu anderen Regelungen. Das Problem ist die bleibende Regelabweichung!&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software P-Regler:'''&lt;br /&gt;
 y = Kp * e&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===I-Regler===&lt;br /&gt;
Der integralwirkende Regler summiert die Regelabweichung über der Zeit auf und multipliziert die Summe (d.h. das Integral) mit dem Faktor '''Ki'''. Je länger eine Regelabweichung ansteht, desto größer wird die Stellgröße des I-Reglers. Er unterscheidet sich prinzipiell nicht vom dynamischen Element I-Glied, ist nur eben künstlich hergestellt für den Einsatz als Regler. Der I-geregelte Kreis ist langsam im Vergleich zu anderen Regelungen. Er hat aber den Vorteil, dass die Abweichung vollständig eliminiert wird.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/iregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software I-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
'''esum''' ist die Summe aller bisherigen Abweichungen '''e'''. Der Parameter des Software I-Reglers ist abhängig von der Rechenschrittweite '''Ta''' (Abtastzeit). Je öfter gerechnet wird, desto öfter wird auch hinzugezählt (aufintegriert). Eine kleine Abtastzeit erfordert also einen kleineren Faktor, dies wird durch die Multiplikation mit '''Ta''' verwirklicht.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PI-Regler===&lt;br /&gt;
Der PI-Regler ist die Kombination aus P- und I-Regler und kombiniert den Vorteil des P-Reglers, nämlich schnelle Reaktion, mit dem Vorteil des I-Reglers, der exakten Ausregelung.  Der PI-geregelte Kreis ist also genau und mittelschnell.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/piregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PI-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PD-Regler===&lt;br /&gt;
Der proportional-differential wirkende Regler kombiniert den P-Regler mit einem D-Anteil. &lt;br /&gt;
Der D-Anteil bewertet die Änderung einer Regelabweichung (er differenziert) und berechnet so deren Änderungsgeschwindigkeit. Diese wird mit dem Faktor '''Kd''' multipliziert und zum P-Anteil hinzuaddiert. Der PD-Regler reagiert damit schon auf Ankündigungen von Veränderungen, das bewirkt sozusagen ein Vorhalten beim Regeln.&lt;br /&gt;
&lt;br /&gt;
Der PD-geregelte Kreis ist sehr schnell im Vergleich zu anderen Regelungen, und manche Regelkreise (solche mit zweifacher Integration) sind ohne D-Anteil überhaupt nicht stabilisierbar. Das Problem der proportionalen Regler, die bleibende Regelabweichung, ist beim PD-Regler allerdings weiterhin vorhanden!&lt;br /&gt;
&lt;br /&gt;
Ein Nachteil aller Regler mit D-Anteil kann die Unruhe im Kreis sein. Ist das Sensorsignal verrauscht, so wird dieses Rauschen durch die Differenziation weiter verstärkt und wieder in den Kreis hineingegeben. Dadurch wird der Aktuator stärker belastet. Macht der Regler insbesondere sehr hohe Ausschläge als Folge von schnellen Änderungen des Sollwertes, dann kann es sein, dass das Stellglied oder der Aktuator diese nicht umsetzen kann - die Wirkung des D-Anteils würde dann durch die Begrenzung verpuffen, und das Einschwingverhalten wäre nicht wie berechnet, sondern meist langsamer. Dies gilt aber nur für große Sprünge. Bei den normalen kleinen Regelvorgängen zum Ausgleich von Störeinflüssen wirkt der D-Anteil wie beabsichtigt.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pdregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PD-Regler:'''&lt;br /&gt;
 y = Kp * e + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
Mit der neuesten Regelabweichung '''e''' und der vorhergehenden '''ealt''' wird der D-Anteil berechnet. Die Differenziation erfolgt damit angenähert durch Bildung des Differenzquotienten (e - ealt)/Ta.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
===PID-Regler===&lt;br /&gt;
Der PID Regler ist der universellste der klassischen Regler und vereinigt die guten Eigenschaften der anderen Regler. Zur Beschreibung der Eigenschaften des P-, I- und D-Anteils siehe die anderen Reglertypen. Der PID-geregelte Kreis ist genau und sehr schnell. In den meisten Anwendungen kommt deshalb der PID-Regler zum Einsatz.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/pidregler.gif&lt;br /&gt;
&lt;br /&gt;
'''Software PID-Regler:'''&lt;br /&gt;
 esum = esum + e&lt;br /&gt;
 y = Kp * e + Ki * Ta * esum + Kd * (e – ealt)/Ta&lt;br /&gt;
 ealt = e&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Alternative PID-Reglerstruktur:'''&lt;br /&gt;
&lt;br /&gt;
Es gibt 2 Darstellungsmöglichkeiten, die inhaltlich identisch sind. In der analogen Regeltechnik ist noch die Darstellung mit der Nachstellzeit '''Tn''' und der Vorhaltezeit '''Tv''' üblich. Die Umrechnung zwischen den beiden Strukturen ist mit den angegebenen Formeln möglich.&lt;br /&gt;
&lt;br /&gt;
[[Bild:PIDstruktur.gif]]&lt;br /&gt;
&lt;br /&gt;
==Vergleich der Reglertypen==&lt;br /&gt;
In der folgenden Abbildung ist der Vergleich von P-, I-, PI-, PD- und PID-Regler in einem Regelkreis mit PT2-Glied als Regelstrecke dargestellt. Es ist deutlich zu sehen, dass die Regler ohne I-Anteil (P und PD) eine bleibende Regelabweichung aufweisen. Erst die Regler mit I-Anteil können auf den Endwert von 1 ausregeln. Beim reinen I-Regler geht das so langsam, dass es gar nicht mehr auf dem Diagramm zu sehen ist. Der Hauptzweck eines I-Anteils ist also die Vermeidung bleibender Regelabweichungen. Daher ist ein&lt;br /&gt;
I-Anteil normalerweise nicht nötig, wenn die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
Ausnahme: Es wird ein doppelter I-Anteil zur Vermeidung von Schleppfehlern benötigt.&lt;br /&gt;
&lt;br /&gt;
Die schnellsten Regler sind die mit einem D-Anteil (PD und PID). Der D-Anteil kommt deshalb hauptsächlich zum Einsatz, wenn schnelle Dynamik gefragt ist oder die Strecke selbst schon instabil ist. Voraussetzung für die Schnelligkeit ist allerdings, dass keine Begrenzung im Stellglied oder Aktuator auftritt. In der Praxis ist eine Begrenzung meistens nicht zu vermeiden, deshalb gilt die Sprungantwort in der Praxis nur für kleine Sprünge.&lt;br /&gt;
&lt;br /&gt;
Die Regler ohne D-Anteil, aber mit P-Anteil (P und PI) sind mittelschnell. Für einfache Regelaufgaben reicht auch oft schon ein reiner P-Regler aus, wenn die bleibende Regelabweichung vernachlässigt werden kann oder weil die Strecke schon einen I-Anteil besitzt.&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/vergleich.gif&lt;br /&gt;
&lt;br /&gt;
Aus diesem Vergleich wird klar, warum der PID-Regler so beliebt ist, er vereinigt die Vorzüge aller anderen Regler.&lt;br /&gt;
&lt;br /&gt;
==Digitaler Regler==&lt;br /&gt;
Durch die Einführung leistungsfähiger und preiswerter Mikroprozessoren hat sich der digitale Regler mehr und mehr durchgesetzt. Im Gegensatz zum analogen Regler werden die Signale nicht mehr analog mit Operationsverstärker verarbeitet, sondern mit einem Mikroprozessor errechnet. Bevor das Signal vom Mikroprozessor bearbeitet werden kann, muss zunächst das Eingangssignal (Istwert) mit einem Analog-Digital-Umsetzer (ADU) digitalisiert werden, d.h. in einen Zahlenwert umgewandelt werden. Das vom digitalen Regler errechnete Ausgangssignal (Stellgröße) wird wiederum zur Ansteuerung des Stellglieds mit einem Digital-Analog-Umsetzer (DAU) in ein analoges Signal gewandelt. Funktionell unterscheiden sich analoger und digitaler Regler jedoch nicht wesentlich, es müssen nur die Schnittstellen angepasst werden.&lt;br /&gt;
&lt;br /&gt;
[[File:digreg.gif|right|framed|Digitaler Regler (Prinzip)]]&lt;br /&gt;
&lt;br /&gt;
Da die Wandlungen und das Regelprogramm eine gewisse Zeit beanspruchen, vergeht pro Durchlauf die sogenannte Takt- oder Abtastzeit. Diese Zeit wirkt sich im Regelkreis wie ein Totzeitglied mit der halben Abtastzeit als Totzeit aus. Das verursacht eine zusätzliche Phasenverschiebung, was sich ungünstig auf die Stabilität des Regelkreises auswirken kann. Ist die Abtastzeit sehr viel kleiner als die dominierende Zeitkonstante der Strecke, dann spricht man von quasi-kontinuierlichem Verhalten, da sich der digitale Regler ähnlich wie ein analoger Regler verhält. Der digitale Regler kann dann wie ein analoger dimensioniert werden. Ist die Abtastzeit größer, kann sie nicht mehr vernachlässigt werden, dann muss sie auch beim Reglerentwurf berücksichtigt werden.&lt;br /&gt;
&lt;br /&gt;
'''Vorteile digitaler Regler:'''&lt;br /&gt;
* Die Verarbeitung erfolgt driftfrei.&lt;br /&gt;
* Es lassen sich nichtlineare Kennlinien, intelligentes Verhalten oder adaptive Regelung leichter realisieren.&lt;br /&gt;
* Der Regler kann bei Bedarf per Software neu konfiguriert und parametriert werden&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Digitale Realisierung am Beispiel des PID-Algorithmus'''&lt;br /&gt;
&lt;br /&gt;
Ausgehend von der Differentialgleichung für kontinuierliche Systeme wird die Differenzengleichung für zeitdiskrete Systeme erstellt. Daraus folgt dann der Stellungsalgorithmus in allgemeiner Form.&lt;br /&gt;
&lt;br /&gt;
Ta = Abtastzeit; k = Nummer der Abtastung&lt;br /&gt;
&lt;br /&gt;
Kp = Proportionalbeiwert; Ki = Integrierbeiwert; Kd = Differenzierbeiwert&lt;br /&gt;
&lt;br /&gt;
&amp;lt;!-- http://www.roboternetz.de/wiki/uploads/Main/pidformel.gif --&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differentialgleichung für den kontinuierlichen PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y(t) \;=\;  Kp \!\cdot\! e(t) &lt;br /&gt;
          + Ki \int_0^t e(\tau) \, d\tau &lt;br /&gt;
          + Kd \, \frac{de(t)}{dt}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''Differenzengleichung für den zeitdiskreten PID-Regler:'''&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  Kp \!\cdot\! e_k&lt;br /&gt;
          + Ki \!\cdot\! Ta \sum_{i=0}^k e_i&lt;br /&gt;
          + \frac{Kd}{Ta}\, ( e_k - e_{k-1} )&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
'''PID Stellungs-Algorithmus:&lt;br /&gt;
:''' &amp;lt;math&amp;gt;&lt;br /&gt;
y_k \;=\;  y_{k-1} &lt;br /&gt;
          + q_0 \!\cdot\! e_k&lt;br /&gt;
          + q_1 \!\cdot\! e_{k-1}&lt;br /&gt;
          + q_2 \!\cdot\! e_{k-2}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Mit den Parametern:&lt;br /&gt;
:&amp;lt;math&amp;gt;&lt;br /&gt;
q_0 \,=\, Kp + Ki \!\cdot\! Ta + \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_1 \,=\, -Kp  - 2 \, \frac{Kd}{Ta}&lt;br /&gt;
     \, , \quad&lt;br /&gt;
q_2 \,=\, \frac{Kd}{Ta}&lt;br /&gt;
&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
'''Umsetzung in Code nach der Differenzengleichung:'''&lt;br /&gt;
&lt;br /&gt;
Im Code wurden einige Variablen umbenannt, da die Indexschreibweise nicht möglich ist.&lt;br /&gt;
&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, esum ist die Summenbildung&lt;br /&gt;
&lt;br /&gt;
In der Praxis wird man die Ausdrücke Ki*Ta und Kd/Ta vorab berechnen und mit Ersatzvariablen in die Reglergleichung einsetzen. Der Verständlichkeit halber wurde es hier im Code belassen. Des weiteren kann eine Begrenzung von esum notwendig werden, um einen Variablenüberlauf oder Windup-Effekt zu vermeiden.&lt;br /&gt;
&lt;br /&gt;
Der nachfolgende Code wird im Rhythmus der Abtastzeit Ta immer wieder aufgerufen.&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 esum = esum + e;				//Integration I-Anteil&lt;br /&gt;
 y = Kp*e + Ki*Ta*esum + Kd/Ta*(e – ealt);	//Reglergleichung&lt;br /&gt;
 ealt = e;&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
'''Alternative Umsetzung in Code nach dem Stellungsalgorithmus:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
y entspricht y&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, yalt entspricht y&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, e entspricht e&amp;lt;sub&amp;gt;k&amp;lt;/sub&amp;gt;, ealt entspricht e&amp;lt;sub&amp;gt;k-1&amp;lt;/sub&amp;gt;, ealt2 entspricht e&amp;lt;sub&amp;gt;k-2&amp;lt;/sub&amp;gt;&lt;br /&gt;
 e = w - x;					//Vergleich&lt;br /&gt;
 y = yalt + q0*e + q1*ealt + q2*ealt2;		//Reglergleichung&lt;br /&gt;
 ealt2 = ealt;&lt;br /&gt;
 ealt = e;&lt;br /&gt;
 yalt = y;&lt;br /&gt;
&lt;br /&gt;
==Dimensionierung des Reglers==&lt;br /&gt;
Die Auswahl des Reglertyps ist heutzutage bei den digitalen Reglern nicht mehr so kritisch, da der Mehraufwand in Software für einen PID-Regler gegenüber einfacheren Typen kaum zu Buche schlägt. Im Prinzip ist man deshalb mit einem PID-Regler fast immer auf der richtigen Seite, mit einer Ausnahme, bei einer Strecke mit reiner Totzeit. Die folgende Tabelle gibt eine Hilfestellung zur Auswahl des Reglers. &lt;br /&gt;
&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ '''Geeignete Reglertypen für die unterschiedlichen Regelstrecken'''&lt;br /&gt;
 |rowspan=2 |'''Strecke'''&lt;br /&gt;
 |colspan=4 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Regler'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PD'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |reine Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |-&lt;br /&gt;
 |1.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |&amp;amp;#160;  &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |2.Ordnung mit kleiner Totzeit&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |höhere Ordnung&lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |&amp;amp;#160; &lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |-&lt;br /&gt;
 |I-Glied und Verzögerung&lt;br /&gt;
 |geeignet&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;geeignet&amp;lt;/div&amp;gt;&lt;br /&gt;
 |gut geeignet&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Nachdem man einen geeigneten Reglertyp ausgewählt hat, stellt sich noch die Frage, wie man die Reglerparameter Kp, Ki, und Kd optimiert. Im Laufe der Zeit wurden viele Methoden zur Dimensionierung der Reglerparameter entwickelt, aber es können hier nicht alle aufgelistet werden. Diese Aufzählung beschränkt sich auf die einfacheren und gängigen Methoden der Parametrierung.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung durch Probieren (Empirisches Einstellen)===&lt;br /&gt;
&lt;br /&gt;
====Methode 1====&lt;br /&gt;
Diese Methode ist geeignet um einfache Systeme zu dimensionieren, insbesondere wenn man bereits Erfahrung mit ähnlichen Regelkreisen hat. Man fängt mit einer unkritischen Einstellung (Kp klein, Ki = 0, Kd = 0) an und erhöht langsam die Verstärkung Kp, bis die Dämpfung schlecht wird. Falls eine Schwingneigung auftritt, muss die Verstärkung wieder etwas zurück genommen werden. Dann nimmt man allmählich den Integralanteil hinzu, erhöht ihn in Schritten und probiert solange herum, bis das Ergebnis einigermaßen passt. Bei Bedarf kann noch ein D-Anteil (PID-Struktur) probiert werden. Wenn dabei die Regelung stabiler wird, kann noch mal Kp und Ki erhöht werden, bis man endgültig zufrieden ist. &lt;br /&gt;
&lt;br /&gt;
====Methode 2====&lt;br /&gt;
Alle Anteile erstmal auf 0. Dann erhöht man Kp so lange bis das System deutlich schwingt. Danach wird der Kd so lange erhöht bis das System nicht mehr schwingt. Anschliessend kann noch ein kleiner Ki Anteil hinzugegeben werden.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Es dürfte klar sein, dass so eine Optimierung im Blindflug nicht immer das Optimum ergibt, aber es ist eine gängige praktische Methode zur Ermittlung der Reglerparameter. Besser sieht es aus, wenn in einer Simulation empirisch optimiert wird. Zusätzliche Informationen über die Stabilität erlauben hierbei eine gezieltere Optimierung. Zudem ist das Probieren im Simulator gefahrlos möglich, was in der Realität nicht immer der Fall ist. Geeignete Programme zur Simulation sind [[Regelungstechnik#Hilfsprogramme_zur_Analyse_und_Optimierung| hier]] vorgestellt. Allerdings muss für eine Simulation die Regelstrecke bekannt sein. Ist das nicht der Fall, so bleibt nur das einfache Probieren oder das Einstellen nach der Schwingungsmethode wie im folgenden beschrieben.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung nach Einstellregeln===&lt;br /&gt;
Die Dimensionierung nach Rezept ist eine praktische Methode ohne viel Rechnerei und Hilfsmittel, eine Methode also für den Praktiker. Die bekanntesten Einstellregeln sind von Ziegler/Nichols und von Chien/Hrones/Reswick. Darüber hinaus gibt es noch eine Vielzahl anderer Einstelltabellen, auf die hier aber verzichtet wird, das würde den Rahmen dieses Artikels sprengen. An der Vielzahl kann man schon ersehen, dass es kein universell gültiges Rezept gibt und mit diesen Tabellen nicht unbedingt das Optimum erreicht wird, eine Nachoptimierung kann nötig sein.&lt;br /&gt;
&lt;br /&gt;
Bei Ziegler/Nichols unterscheidet man noch zwischen der Schwingungsmethode und der Einstellung nach der Sprungantwort.&lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Schwingungsmethode:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Bei der Schwingungsmethode nach Ziegler/Nichols werden die Reglerparameter so verstellt, dass die Stabilitätsgrenze erreicht wird und der Regelkreis zu schwingen beginnt, d.h. die Regelgröße periodische Schwingungen ausführt. Aus der so gefundenen Einstellung können die Reglerparameter ermittelt werden. Dieses Verfahren ist nur auf Regelstrecken anwendbar, bei denen ein Schwingen keinen Schaden anrichtet und die überhaupt instabil gemacht werden können. Die Vorgehensweise ist folgende:&lt;br /&gt;
# Einstellung des Reglers als reinen P-Regler: Ki = 0 und Kd = 0&lt;br /&gt;
# Die Reglerverstärkung Kp wird solange vergrößert, bis sich der geschlossene Regelkreis an der Stabilitätsgrenze befindet und Dauerschwingungen ausführt.&lt;br /&gt;
# Der dabei eingestellte Wert Kp wird als Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; bezeichnet. &lt;br /&gt;
# Die Periodendauer der sich einstellenden Dauerschwingung T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt; wird gemessen.&lt;br /&gt;
# Anhand der folgenden Tabelle werden dann die Reglerparameter bestimmt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.45*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;0.85*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6*Kp&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.5*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |0.12*T&amp;lt;sub&amp;gt;krit&amp;lt;/sub&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| border=0 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Der Vorteil dieses Verfahrens liegt darin, dass die Untersuchung während des Betriebes und ohne Öffnen des Regelkreises durchgeführt werden kann. Der Nachteil an dem Verfahren ist, dass es nur auf Strecken angewendet werden kann, die auch zum Schwingen gebracht werden können. &lt;br /&gt;
&lt;br /&gt;
'''Einstellung nach der Sprungantwort:'''&amp;lt;br/&amp;gt;&lt;br /&gt;
Diese Methode der Parameterbestimmung beruht auf der Aufnahme der Sprungantwort der Regelstrecke. Es eignet sich auch für Strecken, die nicht zum Schwingen gebracht werden können. Der Regelkreis muss allerdings geöffnet werden.&lt;br /&gt;
Vorgehensweise: Es wird die Sprungantwort aufgenommen und durch Einzeichnen der Wendetangente die Verzugszeit Tu und die Ausgleichszeit Tg ermittelt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tu_Tg.gif]]&lt;br /&gt;
&lt;br /&gt;
Mit den so festgestellten Werten werden die Parameter für den einzusetzenden Regler gemäß nachstehenden Tabellen ermittelt.&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Ziegler/Nichols:&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.9/Ks*Tg/Tu&lt;br /&gt;
 |3.3*Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |1.2/Ks*Tg/Tu&lt;br /&gt;
 |2*Tu&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |+ Einstellregeln nach Chien/Hrones/Reswick&lt;br /&gt;
 |'''Regler'''&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Kp'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tn'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''Tv'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''P'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.3/Ks*Tg/Tu&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PI'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.35/Ks*Tg/Tu&lt;br /&gt;
 |1.2*Tg&lt;br /&gt;
 |&amp;amp;#160;&lt;br /&gt;
 |-&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;'''PID'''&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.6/Ks*Tg/Tu&lt;br /&gt;
 |&amp;lt;div align=&amp;quot;center&amp;quot;&amp;gt;Tg&amp;lt;/div&amp;gt;&lt;br /&gt;
 |0.5*Tu&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
{| cellpadding=10&lt;br /&gt;
 |&lt;br /&gt;
{| border=1 cellpadding=4&lt;br /&gt;
 |'''Ki = Kp/Tn'''&lt;br /&gt;
 |-&lt;br /&gt;
 |'''Kd = Kp*Tv'''&lt;br /&gt;
 |}&lt;br /&gt;
 |&lt;br /&gt;
{| cellpadding=4 width=420&lt;br /&gt;
 |Die Parameter Tn und Tv sind aus der analogen Regelungstechnik und sind dort sehr geläufig. Die Umrechnung in die Parameter Ki und Kd erfolgt mit nebenstehenden Formeln. Siehe auch [[Regelungstechnik#PID-Regler| PID-Regler]]&lt;br /&gt;
 |}&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit dem Bodediagramm===&lt;br /&gt;
Ein Bode-Diagramm ist die grafische Darstellung des Frequenzganges. Es werden der Betrag der Übertragungsfunktion (Amplitudengang) und der Verlauf des Phasenwinkels (Phasengang) als Funktion der Frequenz aufgetragen. Die Frequenzachse und die Amplitudenachse werden logarithmisch dargestellt. Die logarithmische Darstellung hat den Vorteil, dass eine Multiplikation auf eine einfache Addition zurückgeführt wird. Somit wird eine Hintereinanderschaltung von Systemen im Blockschaltbild zu einer einfachen Addition im Bodediagramm.&lt;br /&gt;
&lt;br /&gt;
Das Zeitverhalten des rückgekoppelten Regelkreises hängt entscheidend vom Verlauf&lt;br /&gt;
des Frequenzganges der offenen Regelschleife in der Umgebung des Durchtretens durch&lt;br /&gt;
die 0dB-Achse ab. In der Regelungstechnik wird daher der offene Regelkreis im Bode-Diagramm aufgetragen. Das erlaubt einen schnellen Überblick über Stabilität und möglichen Reserven zur Optimierung. Ein Kriterium für die Stabilität der Schleife ist der Phasenrand und der Amplitudenrand. Der Phasenrand ist der Abstand (Phasenreserve) zur -180°-Linie bei der Durchtrittsfrequenz. Die Durchtrittsfrequenz ist diejenige Frequenz, bei der der Amplitudengang durch die 0dB-Linie geht. Siehe auch folgendes Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Phasenrand.gif]]&lt;br /&gt;
&lt;br /&gt;
{| {{Blauetabelle}}&lt;br /&gt;
 |'''Regel:''' Eine geschlossene Regelschleife arbeitet genau dann stabil, wenn der Phasenrand positiv ist.&lt;br /&gt;
 |}&lt;br /&gt;
Wird diese Bedingung verletzt, so wird in diesem Frequenzbereich die im Rückführzweig der Regelung eingebrachte Gegenkopplung zu einer Mitkopplung und das System kann schwingen.&lt;br /&gt;
&lt;br /&gt;
'''Beim Reglerentwurf sind folgende Punkte zu beachten:'''&lt;br /&gt;
* Der Phasenrand muss positiv sein. Der geschlossene Regelkreis kann sonst instabil sein. &lt;br /&gt;
* Je größer der Phasenrand ist, desto größer ist die Stabilitätsreserve des Regelkreises und desto höher ist die Dämpfung des Regelkreises. Üblich sind Werte von 40°...70° für gutes Führungsverhalten und 20°...50° für gutes Störverhalten.&lt;br /&gt;
* Die Durchtrittsfrequenz ist ein Maß für die Schnelligkeit des Regelkreises, je höher, desto schneller ist die Reaktion auf Änderungen der Führungsgröße oder Störungen.&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
Hier ein Beispiel zur Dimensionierung mit dem Bode-Diagramm.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Bode1.gif]]&lt;br /&gt;
&lt;br /&gt;
Die Strecke ist rot dargestellt und besteht in dem Beispiel aus einem nicht schwingfähigem PT2-Glied. Man sucht sich den Punkt, wo die Strecke für sich alleine noch ausreichend Phasenreserve hat, z.B. 70°. In dem Beispiel also die Frequenz, bei der die Strecke -110° Phasendrehung aufweist. Das ist etwa bei 15Hz. Da hat die Strecke ungefähr eine Dämpfung von 25dB. Wenn man nun diese Dämpfung durch eine Verstärkung von 25dB kompensiert, dann wird dieser Punkt zur Durchtrittsfrequenz. D.h. man wählt den P-Anteil des Reglers Kp=18, denn 25dB entspricht ungefähr dem Faktor 18. Um die Regelabweichung zu minimieren, wird noch ein I-Anteil hinzugefügt. Üblicherweise wählt man für die Grenzfrequenz des PI-Reglers die Grenzfrequenz des dominierenden Streckenteils, in dem Beispiel ca. 1.4Hz. Damit ergibt sich ein I-Anteil von 170. Im Bode-Diagramm ist der PI-Regler als schwarze Kurve eingezeichnet. Die Addition der Strecke und des Reglers im Bode-Diagramm führt dann zum Frequenzgang des offenen Regelkreises (blaue Kurve). Die resultierende Durchtrittsfrequenz ist wie gewählt bei etwa 15Hz. Der Phasenrand hat sich durch den I-Anteil im Regler auf ca. 60° reduziert, ist aber noch ausreichend. Das Einschwingen des geschlossenen Regelkreises für diese Dimensionierung sieht dann folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort3.gif]]&lt;br /&gt;
&lt;br /&gt;
Bei Bedarf könnte noch ein D-Anteil (PID-Regler) hinzugenommen werden, das würde die Phase anheben und man könnte dadurch die Durchtrittsfrequenz weiter nach oben schieben. In der Praxis wird dies allerdings wegen der wahrscheinlichen Begrenzung des Stellglieds kein schnelleres Einschwingen mehr bringen. &lt;br /&gt;
&lt;br /&gt;
Begrenzungen oder Nichtlinearitäten werden bei der Dimensionierung mit dem Bode-Diagramm nicht berücksichtigt. Das ist ein Nachteil dieser Methode. Eventuell muss deshalb noch einmal im Zeitbereich nachoptimiert werden.&lt;br /&gt;
&lt;br /&gt;
===Dimensionierung mit der Ortskurve===&lt;br /&gt;
Eine Alternative zur Dimensionierung mit dem Bodediagramm stellt die Methode über die Ortskurve des offenen Regelkreises dar.&lt;br /&gt;
&lt;br /&gt;
Bei diesem Verfahren ist schnell auf einem Blick ersichtlich ob der Regelkreis stabil ist.&lt;br /&gt;
&lt;br /&gt;
Liegt der Punkt -1 auf der Realteilachse links von der Ortskurve in Richtung steigendem Omega so ist der Regelkreis stabil.&lt;br /&gt;
Der Abstand zu der kritischen Kreisfrequenz Omega Krit von der Imaginärteilachse ist die Verstärkung Vr mit diesem Wert lässt sich der Amplitudenrand ermitteln. &lt;br /&gt;
Dazu wird folgende Formel verwendet: Ar = 20 lg (1/Vr) in dB&lt;br /&gt;
&lt;br /&gt;
Die Durchtrittskreisfrequenz Omega D ist an dem Punkt, wo der Betrag aus Realteil und Imaginärteil 1 ergibt. Wenn man weiß, wo die Durchtrittskreisfrequenz ist, dann kann man den Phasenrand bestimmen.&lt;br /&gt;
Dies ist der Winkel zwischen der -180° Linie zu Omega D.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Ortskurve.jpg]]&lt;br /&gt;
&lt;br /&gt;
==Hilfsprogramme zur Analyse und Optimierung==&lt;br /&gt;
Die Analyse und Optimierung von Regelkreisen wird wesentlich erleichtert durch die Zuhilfenahme von Programmen. Es erspart einem eine komplizierte Rechnerei von Hand oder umfangreiche Testläufe. Stellvertretend für all die verfügbaren Programme werden hier zwei Freeware-Programme vorgestellt, die dafür gut geeignet sind. Die Beschreibung hier ersetzt aber keine Tutorials, es wird nur die Anwendung für die Regelungstechnik beschrieben. &lt;br /&gt;
&lt;br /&gt;
===Scilab/Scicos===&lt;br /&gt;
Scilab ist ein wissenschaftlich-technisches Softwarepaket für numerische Berechnungen. Scicos ist eine Erweiterung dazu, die eine blockorientierte und modellbasierte Simulation und Analyse von dynamischen Systemen bietet. Dieses Softwarepaket kann von der [http://www.scilab.org/ Scilab Homepage] herunter geladen werden.&lt;br /&gt;
&lt;br /&gt;
====Scilab====&lt;br /&gt;
Mit Scilab ist es sehr einfach ein Bode-Diagramm zu zeichnen, es bedarf nur 3 Zeilen Code.&lt;br /&gt;
 s=poly(0,'s');&lt;br /&gt;
 G=syslin('c',0.72/(0.11*s+1));&lt;br /&gt;
 bode(G)&lt;br /&gt;
Die 1.Zeile '''s=poly(0,'s');''' legt die Variable s als Polynomvariable fest. Dies braucht in einer Sitzung nur einmal gemacht zu werden. Die 2.Zeile '''G=syslin('c',0.72/(0.11*s+1));''' definiert ein lineares System mit der Übertragungsfunktion 0.72/(0.11s+1). Die 3.Zeile '''bode(G)''' zeichnet das Bode-Diagramm des zuvor mit syslin definierten Systems G. Zu beachten ist, dass Scilab auf der x-Achse im Bode-Diagramm die Frequenz in Hertz und nicht wie üblich die Kreisfrequenz darstellt. Anstelle des Bode-Diagramms kann auch die Sprungantwort gezeichnet werden. Dies geschieht mit folgenden Befehlen:&lt;br /&gt;
 xbasc();&lt;br /&gt;
 t=[0:0.001:2];&lt;br /&gt;
 y=csim('step',t,G);&lt;br /&gt;
 plot2d(t,y)&lt;br /&gt;
'''xbasc()''' löscht den letzten Plot mit dem Bode-Diagramm und mit '''t=[0:0.001:2]''' wird ein Vektor t mit den angegebenen Zeiten im Intervall von 1ms definiert. Die Zeile '''y=csim('step',t,G)''' berechnet die Sprungantwort des zuvor mit syslin definierten Systems G und speichert sie in y ab. Das Ergebnis wird dann mit '''plot2d(t,y)''' dargestellt. Bei Bedarf können noch Gitternetzlinien mit dem Befehl '''xgrid()''' hinzugefügt werden.&lt;br /&gt;
&lt;br /&gt;
Ergänzend hier noch ein Scilab-Skript, welches recht hilfreich bei der Dimensionierung mit dem Bode-Diagramm ist. Den nachfolgenden Code einfach in das SciPad-Fenster (Editor von Scilab) kopieren und starten. Es werden 2 Grafikfenster angezeigt, eines mit dem Bode-Diagramm und ein zweites mit der Sprungantwort. Man kann im Skript die Streckencharakteristik anpassen und verschiedene Reglerparameter ausprobieren.&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Ks=0.72;                            // Verstärkung der Strecke&lt;br /&gt;
T1=0.11;                            // Zeitkonstante 1&lt;br /&gt;
T2=0.005;                           // Zeitkonstante 2&lt;br /&gt;
Kp=18;                              // Proportionalbeiwert&lt;br /&gt;
Ki=170;                             // Integralbeiwert&lt;br /&gt;
Kd=0;                               // Differenzialbeiwert&lt;br /&gt;
 &lt;br /&gt;
s=poly(0,'s');                      // definiert s als Polynomvariable&lt;br /&gt;
P=(T1*s+1)*(T2*s+1);                // Streckencharakteristik&lt;br /&gt;
Gs=syslin('c',Ks,P)                 // Übertragungsfunktion der Strecke&lt;br /&gt;
&lt;br /&gt;
RZ=poly([Ki Kp Kd],'s','coeff')     // Zählerpolynom des Reglers&lt;br /&gt;
RN=poly([0 1],'s','coeff')          // Nennerpolynom des Reglers&lt;br /&gt;
Gr=syslin('c',RZ,RN)                // Übertragungsfunktion des Reglers&lt;br /&gt;
&lt;br /&gt;
G=Gr*Gs                             // Übertragungsfunktion gesamt&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,0);&lt;br /&gt;
xbasc(0);&lt;br /&gt;
bode([Gr;G;Gs],0.1,100,['Regler';'gesamt';'Strecke'])&lt;br /&gt;
&lt;br /&gt;
Gcl=G/(G+1)                         // geschlossene Regelschleife&lt;br /&gt;
t=0:0.001:0.2;&lt;br /&gt;
y=csim('step',t,Gcl);               // berechnet Sprungantwort&lt;br /&gt;
xset(&amp;quot;window&amp;quot;,1);&lt;br /&gt;
xbasc(1);&lt;br /&gt;
plot2d(t,y,2);&lt;br /&gt;
xgrid();&lt;br /&gt;
xtitle(&amp;quot;Sprungantwort&amp;quot;,&amp;quot;sec&amp;quot;);&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
====Scicos====&lt;br /&gt;
Eine weitere Möglichkeit zur Simulation im Zeitbereich bietet Scicos. Die Modellierung geschieht mit einem grafischen Editor, in dem Blöcke mit vordefinierten oder selbstgemachten Funktionen miteinander verbunden werden. Ein einfaches Modell eines Regelkreises mit PID-Regler sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_anaReg.gif]]&lt;br /&gt;
&lt;br /&gt;
Der PID-Regler ist mit seinen 3 Zweigen (P, I und D) dargestellt. In den Verstärkerblöcken kann durch Ändern der Reglerparameter (KP, KI und KD) der Regler optimiert werden. Die Strecke ist in diesem Beispiel nur ein einzelner Block, in dem die Übertragungsfunktion eingegeben wird. Man kann die Strecke auch detaillierter mit einzelnen Funktionsblöcken darstellen. Ein Beispiel eines komplexen Blockschaltbilds für einen balancierenden Bot ist unter diesem [http://www.roboternetz.de/phpBB2/download.php?id=5082 Link] zu finden.&lt;br /&gt;
&lt;br /&gt;
Der Vorteil der Simulation mit Scicos ist die Möglichkeit Nichtlinearitäten zu berücksichtigen und die Kombination von kontinuierlichen und diskreten Funktionen. Das heißt, man kann einen digitalen Regler mit seinen diskreten Schritten und eine analoge Strecke, als kontinuierliche Funktion eingegeben, zusammen simulieren. Scicos bietet sogar einen 'Scifunc'-Block, mit dem Rechenschritte des digitalen Reglers nachgebildet werden können. Damit wird sowohl das dynamische Verhalten, verursacht durch die Abtastzeit Ta, als auch die etwas unterschiedliche Dynamik durch die digitale Ausführung eines I- und D-Anteils richtig simuliert. Ein Beispiel für den Einsatz des Scifunc-Blocks ist in folgendem Blockschaltbild zu sehen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Scicos_digReg.png]]&lt;br /&gt;
&lt;br /&gt;
Beispiel: [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlregelung]] mit digitalem Regler&lt;br /&gt;
&lt;br /&gt;
Die globalen Variablen für die Reglerparameter und die Abtastzeit werden unter dem Menüpunkt „Edit - Context“ abgelegt.&lt;br /&gt;
 Kp=18;&lt;br /&gt;
 Ki=60;&lt;br /&gt;
 Ta=0.01;&lt;br /&gt;
In den Taktgeber für den digitalen Regler wird als Clock-Periode die Abtastzeit Ta eingetragen. In das Dialogfenster zum Scifunc-Block wird folgender Code zur Simulation des digitalen PI-Reglers eingetragen:&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
z=z+Ki*Ta*u1&lt;br /&gt;
if z&amp;gt;5 then&lt;br /&gt;
z=5;&lt;br /&gt;
end&lt;br /&gt;
y1=Kp*u1+z&lt;br /&gt;
if y1&amp;gt;5 then&lt;br /&gt;
y1=5;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
z entspricht der Variable esum vom Beispiel des [[Regelungstechnik#Realisierung_mit_digitalem_Regler| digitalen Drehzahlreglers]]; u1 ist die Eingangsvariable und y1 die Ausgangsvariable des Scifunc-Blocks.&lt;br /&gt;
In den Block für die Strecke wird die Übertragungsfunktion eingetragen. Als Zähler die Verstärkung Ks, also 0.72. Im Nenner das Polynom (1+0.11*s) für die Charakteristik der Strecke. Mit ‚Simulate – Run’ wird die Simulation gestartet. Als Ergebnis sollte das Einschwingen der Stellgröße (schwarz) und der Regelgröße (grün), wie in folgender Abbildung erscheinen.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Sprungantwort_DZR.png]]&lt;br /&gt;
&lt;br /&gt;
Man kann nun mit den Reglerparametern und verschiedenen Abtastzeiten spielen, um zu sehen wie sich die Änderungen auswirken. Zum Beispiel wird bei einer Verdopplung der Abtastzeit der Regelkreis bereits instabil.&lt;br /&gt;
&lt;br /&gt;
Diese Beispiele sind nur ein kurzer Auszug von den Möglichkeiten mit Scilab/Scicos für den Einsatz in der Regelungstechnik. Darüber hinaus ist es auch sehr gut geeignet bei anderen Optimierungsverfahren wie z.B. beim WOK-Verfahren (Wurzelortskurven) oder zur Analyse und Optimierung von modernen Reglern wie z.B. Zustandsregler und Kalmanfilter.&lt;br /&gt;
&lt;br /&gt;
===LTspice/SwitcherCad III===&lt;br /&gt;
Dieses Programm ist ein SPICE-Derivat von der Firma Linear Technology und ist unter den 2 Namen LTspice und SwitcherCad III bekannt. Der Einfachheit halber wird für die weitere Beschreibung hier nur der Name LTspice verwendet. Das Programm ist Freeware und kann unter diesem Link herunter geladen werden. http://ltspice.linear.com/software/LTspiceIV.exe&lt;br /&gt;
&lt;br /&gt;
LTspice ist ein Simulationsprogramm zur Analyse von elektronischen Schaltungen. Mit LTspice kann sowohl im Zeitbereich als auch im Frequenzbereich analysiert werden und bietet sich dadurch mit den entsprechenden Modellen auch für den Einsatz in der Regelungstechnik an. Wer sich bereits mit SPICE-Programmen auskennt, für den sollte es auch in der Regelungstechnik die 1.Wahl sein. &lt;br /&gt;
&lt;br /&gt;
Der Vorteil von LTspice ist die Möglichkeit einer sehr detaillierten Analyse, vorausgesetzt die Modelle sind auch so detailliert nachgebildet. Insbesondere für analoge Regler, wo die elektrische Schaltung direkt umgesetzt werden kann, empfiehlt sich der Einsatz von LTspice. Der Nachteil ist, LTspice ist nicht auf regeltechnische Belange ausgelegt worden und spezifische Symbole für die Regelungstechnik müssen selbst erstellt werden. Einige selbst erstellte Symbole für dynamische Grundelemente in LTspice sind hier abgebildet.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTSpiceSymb.png]]&lt;br /&gt;
&lt;br /&gt;
Die 3 Symbole können [http://www.roboternetz.de/phpBB2/dload.php?action=file&amp;amp;file_id=285 hier] heruntergeladen werden. Weitere Symbole können anhand dieser Beispiele sehr leicht selbst erstellt werden. Ein P-Glied kann durch eine spannungsgesteuerte Spannungsquelle (E-Source) oder Operationsverstärker mit einstellbarer Verstärkung dargestellt werden.&lt;br /&gt;
&lt;br /&gt;
'''Analyse im Zeitbereich'''&lt;br /&gt;
&lt;br /&gt;
Das Beispiel des [[Regelungstechnik#Beispiel:_Drehzahlregelung| Drehzahlreglers]] mit analogem Regler wird hier mit LTspice simuliert. Das Schaltbild des Regelkreises zeigt nachfolgende Abbildung.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_TRAN.png]]&lt;br /&gt;
&lt;br /&gt;
Der Vergleicher (U1) und der analoge PI-Regler (U2) sind so dargestellt, wie es auch in Wirklichkeit ausgeführt werden kann. Da der PI-Regler in der Schaltung bereits invertiert, wurden die Eingänge am Vergleicher vertauscht, damit die Polarität wieder stimmt. Der Rest des Regelkreises wurde stark vereinfacht, kann aber nach Bedarf auch ausführlicher dargestellt werden. Das PT1-Glied U3 simuliert die Strecke des Regelkreises und der Verstärker U4 dient nur zur Umrechnung auf die Drehzahl. Zur Simulation im Zeitbereich wird auf den Führungswert w mit der Spannungsquelle V1 ein Sprung gegeben. In der Reglerschaltung wurde bewusst ein Operationsverstärker mit Versorgungsspannung gewählt, damit auch der Einfluss einer Begrenzung mit simuliert wird. Die Zeitbereichsanalyse wird durch den LTspicebefehl .TRAN erreicht. Die Sprungantwort (Tachospannung) bei diesem Regelkreis sieht dann folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Tacho2.png]]&lt;br /&gt;
&lt;br /&gt;
Durch Ändern der Bauelemente R5, R6 und C1 kann man den Regler optimieren. Eine Umrechnung auf die Reglerparameter Kp und Ki ist mit folgenden Formeln möglich, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1)&lt;br /&gt;
&lt;br /&gt;
Mit einem Mausklick auf den entsprechenden Knoten in der Schaltung können noch weitere Signale, wie z.B. die Stellgröße y angezeigt werden. Durch Verändern der Versorgungsspannung V3, V4 kann man sich auch die Auswirkung der Begrenzung ansehen. &lt;br /&gt;
&lt;br /&gt;
'''Analyse im Frequenzbereich'''&lt;br /&gt;
&lt;br /&gt;
Für die Darstellung des Bode-Diagramms der offenen Regelschleife in LTspice muss ein Trick angewendet werden, denn durch das Auftrennen der Regelschleife würde der Arbeitspunkt verloren gehen und dadurch die offene Schleife ohne Gegenkopplung an den Anschlag fahren.&lt;br /&gt;
&lt;br /&gt;
Mit einer zusätzlichen Spannungsquelle in der Schleife kann man dieses Problem umgehen. Die Schleife bleibt für den Erhalt des Arbeitspunktes weiterhin geschlossen und man kann trotzdem die Verstärkung der offenen Schleife durch das Verhältnis der Spannung vor und hinter der Spannungsquelle bestimmen. Das erweiterte Blockschaltbild sieht folgendermaßen aus.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_AC.png]]&lt;br /&gt;
&lt;br /&gt;
V2 ist die zusätzliche Spannungsquelle für die AC-Analyse. Die Spannungsquelle V1 wird von Pulsform auf Gleichspannung umgestellt. Sie wird so gewählt, dass sich der gewünschte Arbeitspunkt einstellt. Durch den LTspicebefehl .AC wird die Analyse im Frequenzbereich veranlasst. Um das Bode-Diagramm des offenen Regelkreises darzustellen, wird als Kurve nicht ein einzelner Knoten ausgewählt, sondern das Verhältnis der Spannung vom Ende zum Anfang des Regelkreises, in unserem Beispiel also V(tacho)/V(x). Zur Anzeige kommt dann das Bode-Diagramm (grüne Kurve) der offenen Schleife, wie in der folgenden Abbildung zu sehen. Für den Amplitudengang (durchgezogene Linien) gilt die linke Skala in dB, für den Phasengang (gestrichelte Linien) die rechte Skala in Grad.&lt;br /&gt;
&lt;br /&gt;
[[Bild:LTspice_Bode.png]]&lt;br /&gt;
&lt;br /&gt;
Zusätzlich ist noch das Bode-Diagramm der Strecke (rote Kurve) zu sehen. Dies ist durch einfaches Hinzufügen einer weiteren Kurve mit dem Ausdruck V(tacho)/V(y) durchgeführt worden. &lt;br /&gt;
&lt;br /&gt;
Im Gegensatz zur üblichen Darstellung des Bode-Diagramms eines offenen Regelkreises, beinhaltet das mit LTspice erstellte Bode-Diagramm auch die -180 Grad Phasendrehung der Gegenkopplung. Der Phasenrand ist deshalb nicht auf -180 Grad sondern auf 0 Grad zu beziehen. In unserem Beispiel ist der Phasenrand etwa 90 Grad, also ein sehr stabiler Regelkreis. Zu beachten ist, dass die Frequenzachse des Bode-Diagramms wie auch schon bei Scilab in der Einheit Hertz anstatt wie üblich in der Kreisfrequenzeinheit rad/s dargestellt ist.&lt;br /&gt;
&lt;br /&gt;
==Modellierung eines Motors/Antriebs==&lt;br /&gt;
[[Bild:ESB_Motor.png|thumb|320px|Ersatzschaltbild DC-Motor]]&lt;br /&gt;
Der Motor ist ein oft verwendeter Aktuator in der Robotik. Deshalb wird hier am Beispiel des Gleichstrommotors mit Permanentmagnet (Nebenschlussmotor) die Modellbildung gezeigt. Zur Modellierung gibt es mehrere Möglichkeiten. Je nachdem wie detailliert die Simulation sein soll, kann man sich ein Modell, von sehr einfach bis sehr detailliert, auswählen. Zwei Zeitkonstanten bestimmen die Dynamik eines Gleichstrommotors. Eine davon ist die mechanische Zeitkonstante, die ist meistens die dominierende Zeitkonstante und wird durch das Trägheitsmoment J des Rotors verursacht. Die zweite Zeitkonstante ist die elektrische Zeitkonstante, sie wird durch die Induktivität L bestimmt. Bei einfachen Regelungen kann in den meisten Fällen die elektrische Zeitkonstante vernachlässigt werden, damit reduziert sich das Modell auf ein einzelnes PT1-Glied.&lt;br /&gt;
&lt;br /&gt;
'''Definition: Motor und Antrieb'''&lt;br /&gt;
&lt;br /&gt;
Als '''Motor''' wird hier der Motor alleine verstanden. Die Ausgangsgröße ist die Winkelgeschwindigkeit w (Drehzahl).&lt;br /&gt;
 &lt;br /&gt;
Als '''Antrieb''' wird hier der komplette Antrieb eines Fahrzeugs verstanden, also Motor inklusive Getriebe und Masse des Fahrzeugs. Für die Dynamik ist nicht nur das Trägheitsmoment des Motors sondern auch die Masse des Fahrzeugs verantwortlich. Die Ausgangsgröße der Einheit „Antrieb“ ist die Geschwindigkeit v.&lt;br /&gt;
&lt;br /&gt;
Die hier vorgestellten Modelle gelten sowohl für einen Motor als auch für einen kompletten Antrieb, wenn man die Elastizität und das Spiel des Getriebes vernachlässigt.&lt;br /&gt;
&lt;br /&gt;
===Einfaches Modell mit PT1-Glied===&lt;br /&gt;
Die einfachste Art einen Motor oder Antrieb zu simulieren, ist mit einem PT1-Glied als Modell. Das Simulationsprogramm [[Regelungstechnik#Scicos|Scicos]] bietet dazu einen Block zur Eingabe der Übertragungsfunktion (num(s)=Zähler, den(s)=Nenner der Übertragungsfunktion).&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Übertragungsfunktion:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;G(s)=\frac{K}{1+Ts}&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |Beispiel:&lt;br /&gt;
 num(s) = K = 0.72&lt;br /&gt;
 den(s) = 1 + Ts = 1 + 0.11s&lt;br /&gt;
 |[[Bild:Scicos_TF.png]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Wird nicht nur das Ausgangssignal, also die Geschwindigkeit oder Drehzahl in der Simulation benötigt, sondern auch die Beschleunigung, dann kann nachfolgendes Modell verwendet werden. Dieses Modell ist der Differentialgleichung eines PT1-Glieds nachempfunden und liefert das gleiche Ergebnis wie vorheriges Modell, bietet aber noch den Zugriff auf das Beschleunigungssignal.&lt;br /&gt;
{| border=0 cellpadding=10&lt;br /&gt;
 |Differentialgleichung:&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
&amp;lt;math&amp;gt;v'=\frac{K}{T}U-\frac{1}{T}v&amp;lt;/math&amp;gt;&lt;br /&gt;
&lt;br /&gt;
 |&lt;br /&gt;
 v = Geschwindigkeit&lt;br /&gt;
 v’= Beschleunigung (Ableitung von v)&lt;br /&gt;
 K = Übertragungsmaß&lt;br /&gt;
 T = Zeitkonstante&lt;br /&gt;
 U = Eingangsgröße (z.B. Spannung)&lt;br /&gt;
 |[[Bild:Antrieb_PT1.png|thumb|Einfaches Modell eines Antriebs]]&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
Die beiden Parameter K und T müssen ausgemessen werden, wenn sie nicht bekannt sind. Die Zeitkonstante T kann in einem Anlaufversuch ermittelt werden. Dazu wird auf den Motor ein Spannungssprung gegeben und die Sprungantwort am Ausgang nachgemessen. Bei einem Antrieb erspart diese Methode die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente (Motor, Getriebe, Fahrzeug). Bei der Ermittlung des Übertragungsmaß K ist zu beachten, dass sich möglicherweise der Motor durch starke Reibung erst ab einer bestimmten Spannung dreht. Hier ist die Steigung der Kennlinie mit delta&amp;amp;nbsp;v&amp;amp;nbsp;/&amp;amp;nbsp;delta&amp;amp;nbsp;U auszuwerten, wie im folgenden Bild zu sehen ist.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_stat.png]]&lt;br /&gt;
&lt;br /&gt;
Die einfachen Modelle gelten nur für den linearen Teil der Kennlinie. Soll auch die Nichtlinearität durch Reibung modelliert werden, dann sind detailliertere Modelle, wie im Folgenden beschrieben, zu verwenden. Die Auswirkung einer Haftreibung ist auch in dem Geschwindigkeitsdiagramm durch die Hysterese in der Kennlinie zu sehen. Beim Hochfahren der Ansteuerspannung bewegt sich das Fahrzeug erst ab ca. 1.25V, während beim Herunterfahren der Ansteuerspannung das Fahrzeug noch bis 0.75V rollt und erst unter 0.75V stehen bleibt.&lt;br /&gt;
&lt;br /&gt;
===Detailliertes Modell===&lt;br /&gt;
&lt;br /&gt;
[[Bild:Motor_Model.png|thumb|350px|Detailliertes Motormodell]]&lt;br /&gt;
Ein detailliertes Motormodell ist rechts in dem Bild zu sehen. Es hat auf der linken Seite den elektrischen Teil mit den Parametern R (Widerstand) und L (Induktivität) und auf der rechten Seite den mechanischen Teil mit den Blöcken Trägheitsmoment und Reibung. Der elektrische Teil liefert das Stromsignal i, welches mit der Motorkonstante Km in das Drehmoment M umgerechnet wird. Mit dem folgenden Summierglied kann über einen zusätzlichen Eingang auch ein extern angreifendes Lastmoment mit simuliert werden. Am Ausgang des mechanischen Teils steht die Winkelgeschwindigkeit w in der Einheit [rad/s] bzw. über den Umrechnungsfaktor 9.55 die Drehzahl in [Upm] zur Verfügung. Die Reibung wird in einem nichtlinearen Block mittels Lookup-Table simuliert. In der einschlägigen Literatur wird die Reibung meistens mit einem Dämpfungsfaktor (linear) simuliert, was einer viskosen Reibung entspricht. Das passt aber nicht so gut für Kleinmotoren, da überwiegt vor allem die trockene Reibung. Die trockene Reibung hat ein konstantes Bremsmoment wenn sich der Motor dreht (unabhängig von Drehzahl, Vorzeichen abhängig von Drehrichtung). So eine Funktion kann sehr einfach mit einer Lookup-Table realisiert werden. Die Lookup-Table kann auch dazu verwendet werden, Mischformen von trockener, viskoser und turbulenter Reibung und sogar noch Haftreibung in einem Block zu simulieren, wenn man will.&lt;br /&gt;
&lt;br /&gt;
Bei einigen Herstellern, wie z.B. Faulhaber und Maxon, kann man die für das Modell nötigen Parameter im Datenblatt finden. Das Bremsmoment der Reibung berechnet sich aus dem Leerlaufstrom wie folgt: Bremsmoment&amp;amp;nbsp;=&amp;amp;nbsp;Motorkonstante&amp;amp;nbsp;*&amp;amp;nbsp;Leerlaufstrom &lt;br /&gt;
&lt;br /&gt;
Falls die Daten nicht verfügbar sind, muss man sie selbst ausmessen. Eine Hilfestellung zur Bestimmung der Motorkonstante und des Trägheitsmoments gibt es hier:&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/zeigebeitrag.php?p=96750&amp;amp;highlight=#96750&lt;br /&gt;
*http://www.roboternetz.de/phpBB2/viewtopic.php?t=12793&lt;br /&gt;
&lt;br /&gt;
[[Bild:Antrieb_Modell.png|thumb|350px|Modell eines Antriebs]]&lt;br /&gt;
&lt;br /&gt;
Das detaillierte Motormodell kann auch für einen Antrieb verwendet werden, wenn man eine starre Kopplung zwischen Motor und Antriebsrad voraussetzt, also Elastizität und Spiel des Getriebes vernachlässigt. Anstelle der rotatorischen Kenngrößen (Drehmoment M, Trägheitsmoment J, Winkelgeschwindigkeit w) werden die translatorischen Kenngrößen (Kraft F, Masse m, Geschwindigkeit v) eingesetzt. Das Drehmoment wird mittels Getriebeübersetzung ü und Radius r des Antriebsrades in die entsprechende Vortriebskraft umgerechnet. Daraus ergibt sich die Kraftkonstante Kf, die für das Antriebsmodell verwendet wird.&lt;br /&gt;
&lt;br /&gt;
Die Umrechnung ist: Kf = Km * ü/r&lt;br /&gt;
&lt;br /&gt;
Bei der Trägheitsmasse m muss neben der Masse des Fahrzeugs auch das Trägheitsmoment des Motors mit berücksichtigt werden. Die Umrechnung von Trägheitsmoment in eine äquivalente Masse = J * (ü/r)²&lt;br /&gt;
&lt;br /&gt;
Der Reibungsblock in diesem Modellbeispiel enthält eine Mischform aus Haftreibung, trockener und viskoser Reibung, wie sie typisch für einen Kleinbot mit 2 Antriebsrädern und einem Gleitpin ist.&lt;br /&gt;
&lt;br /&gt;
==Beispiel: Drehzahlregelung==&lt;br /&gt;
Es wird ein Gleichstrommotor in der Drehzahl geregelt. Als Sensor ist ein Tachogenerator vorhanden, der direkt auf der Motorwelle sitzt. Das System ist in einem kleinen Modellfahrzeug eingebaut und wird zur Geschwindigkeitsregelung eingesetzt, da die Drehzahl proportional zur Geschwindigkeit ist.&lt;br /&gt;
&lt;br /&gt;
Das Funktionsschaltbild sieht folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl1.gif&lt;br /&gt;
&lt;br /&gt;
Als Störgröße können unterschiedliche Reibwerte oder Steigung und Gefälle rückwirkend über das Getriebe die Drehzahl beeinflussen. Das Getriebe und die Last sind zwar außerhalb der Regelschleife, beeinflussen aber durch die feste Kopplung des Getriebes die Dynamik des Regelkreises. Durch die starre Kopplung kann das Trägheitsmoment des Motors und die Masse des Fahrzeugs zusammengefasst werden. Das Gleiche gilt auch für die Reibwerte. Damit vereinfacht sich die Modellierung und das Blockschaltbild reduziert sich auf folgende Schaltung:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl2.gif&lt;br /&gt;
&lt;br /&gt;
Zur Ermittlung des dynamischen Verhaltens der Regelstrecke wird die Sprungantwort gemessen. Dazu wird auf den Eingang der Regelstrecke (Stellglied) ein Spannungssprung gegeben und die Antwort am Ausgang des Tachogenerators nachgemessen. Diese Methode erspart die aufwändige Ermittlung der elektrischen und mechanischen Daten der einzelnen Elemente der Regelstrecke (Motor, Getriebe, Fahrzeug). Die Messung ergab folgende Sprungantwort der Regelstrecke:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/tacho.gif&lt;br /&gt;
&lt;br /&gt;
Wie zu erwarten, ist die Sprungantwort annähernd ein Verzögerungsglied 1.Ordnung. Die abgelesene Zeitkonstante ist 0.11s. Die Verstärkung der Regelstrecke ist Ks = 0.72. Das Übertragungsmaß des Tachogenerators ist 1V pro 2480Upm. Damit kann auf die Drehzahl rückgerechnet werden.&lt;br /&gt;
&lt;br /&gt;
Da die Regelstrecke nur aus einem PT1-Glied besteht, könnte eine analoge Regelung fast beliebig schnell gemacht werden. Wegen der Begrenzung bringt aber das Ausreizen der Optimierung für das Führungsverhalten nicht viel, nur für das Störverhalten wäre eine schnellere Regelung sinnvoll. Um aber einen Vergleich zwischen analogem und digitalem Regler anstellen zu können wird eine Parametrierung gewählt, die auch für den digitalen Regler mit seiner Totzeit noch stabil ist. Es wird deshalb auch auf einen D-Anteil im Regler verzichtet und nur ein PI-Regler realisiert. Das vereinfachte Blockschaltbild mit den dynamischen Elementen sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
http://www.roboternetz.de/wiki/uploads/Main/drehzahl3.gif&lt;br /&gt;
&lt;br /&gt;
Zur Veranschaulichung wurde ein analoger als auch ein digitaler Regler realisiert. Die Parametrierung des analogen Reglers wurde mit dem Programm [[Regelungstechnik#LTspice.2FSwitcherCad_III| LTspice]] durchgeführt. Es bot sich an, da die analoge Reglerschaltung exakt simuliert werden konnte. Für die Optimierung des digitalen Reglers wurde dann [[Regelungstechnik#Scicos| Scicos]] verwendet. &lt;br /&gt;
&lt;br /&gt;
===Realisierung mit analogem Regler===&lt;br /&gt;
Die elektrische Schaltung für einen analogen PI-Regler ist in der nächsten Abbildung zu sehen. Der erste Operationsverstärker vergleicht den Sollwert w mit dem Istwert x. Der zweite Operationsverstärker bildet den PI-Regler. Die Werte R5, R6 und C1 sind für die Charakteristik des PI-Reglers zuständig. Mit R6 kann der P-Anteil und mit C1 der I-Anteil eingestellt werden. Die Optimierung der Werte wurde empirisch in einer Simulation mit LTspice durchgeführt. Da die Schaltung des PI-Reglers invertiert, wurden zum Ausgleich am Vergleicher die Eingänge an U1 vertauscht, so dass sich über die gesamte Schaltung wieder die richtige Polarität ergibt.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Analogregler.png]]&lt;br /&gt;
&lt;br /&gt;
Zum Umrechnen auf Kp und Ki können diese Formeln verwendet werden, siehe auch [[Regelungstechnik#PI-Regler| PI-Regler]]:&lt;br /&gt;
&lt;br /&gt;
Kp = R6/R5 = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 1/(R5*C1) = 147&lt;br /&gt;
&lt;br /&gt;
===Realisierung mit digitalem Regler===&lt;br /&gt;
Im digitalen Regelkreis wird der Istwert '''x''' vom Tachogenerator mit einem A/D-Wandler digitalisiert. Der Sollwert '''w''' wird dem µC als digitaler Wert übergeben. Die Stellgröße '''y''' entspricht dem PWM-Wert für den Motortreiber. Um zum analogen Regler vergleichbar zu sein, wurde sowohl für den A/D-Wandler als auch für den PWM-Steller eine 8-Bit-Breite vorgesehen. Damit ist die Verstärkung in beiden Fällen gleich und analoger und digitaler Regler besser vergleichbar.&lt;br /&gt;
&lt;br /&gt;
Eigentlich könnte man bei kleiner Abtastzeit direkt die Parametrierung des analogen Reglers für die digitale Realisierung übernehmen. Aber es gibt doch kleine Unterschiede in der Dynamik zwischen analoger und digitaler Ausführung und um sicher zu gehen, dass die gewählte Abtastzeit einen nicht zu großen Einfluss hat, wird noch einmal mit [[Regelungstechnik#Scicos| Scicos]] nachoptimiert. Mit einer Abtastzeit Ta = 10ms und den Parametern des analogen Reglers ergibt sich ein Überschwingen, das nur sehr langsam auf den Endwert abklingt. Durch Verringern des I-Anteils auf 60 wird ein optimales Einschwingen für den digitalen Regler erreicht. Die Parameter sind:&lt;br /&gt;
&lt;br /&gt;
Kp = 18&lt;br /&gt;
&lt;br /&gt;
Ki = 60&lt;br /&gt;
&lt;br /&gt;
Ta = 0.01&lt;br /&gt;
&lt;br /&gt;
Zur Umsetzung in einen Code wurde die Programmiersprache C gewählt. Da der Code sehr einfach ist, sollte es auch kein Problem sein, den Code als Beispiel für andere Sprachen zu verwenden. Der Algorithmus wird im Takt der Abtastzeit, also alle 10ms aufgerufen. In der Reglergleichung kann zur Vereinfachung das Produkt Ki*Ta durch eine Ersatzvariable, die gleich das Ergebnis aus dem Produkt 60*0.01 = 0.6 hat, ersetzt werden. Zum besseren Verständnis wurde es hier beim Ki*Ta belassen. Um einen Windup-Effekt zu verhindern, wird die Summenbildung esum auf +-400 begrenzt. Der Wert wurde so gewählt, dass noch eine volle Aussteuerung durch den I-Anteil möglich ist. Zum Schluss wird die Stellgröße y auf die mögliche Aussteuerung des Stellglieds (0...255) begrenzt.&lt;br /&gt;
&lt;br /&gt;
'''Programmbeispiel digitaler PI-Regler:'''&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
	e = w - x;				//Vergleich&lt;br /&gt;
	esum = esum + e;			//Integration I-Anteil&lt;br /&gt;
	if (esum &amp;lt; -400) {esum = -400;}	        //Begrenzung I-Anteil&lt;br /&gt;
	if (esum &amp;gt; 400) {esum = 400;}&lt;br /&gt;
	y = Kp*e + Ki*Ta*esum;			//Reglergleichung&lt;br /&gt;
	if (y &amp;lt; 0) {y = 0;}			//Begrenzung Stellgröße&lt;br /&gt;
	if (y &amp;gt; 255) {y = 255;}&lt;br /&gt;
	PWM = y;				//Übergabe Stellgröße&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
== Beispiel: Lageregelung ==&lt;br /&gt;
Unter einer Lageregelung versteht man die Positionierung von Objekten. Als Beispiel soll hier ein kleiner Bot mit Radencoder eine bestimmte Weglänge fahren. Gegenüber der Drehzahl- oder Geschwindigkeitsregelung ist bei der Lageregelung noch ein zusätzlicher Integrator in der Strecke vorhanden. Die gesamte Strecke ist damit ein I-Glied mit Verzögerung. Laut Tabelle im Abschnitt „Dimensionierung des Reglers“ ist dafür ein PD-Regler gut geeignet. Der PD-Regler wird digital ausgeführt, zur Simulation und Parametrierung bietet sich deshalb Scicos an. &lt;br /&gt;
&lt;br /&gt;
Da bei einer Lageregelung der Geschwindigkeitsbereich von Null aus geht, also über den nichtlinearen Bereich geht, sollte auch in der Simulation die Nichtlinearität berücksichtigt sein. Für das Beispiel wird deshalb das Modell eines Antriebs mit Haft- und Gleitreibung genommen, wie es unter &amp;quot;Modellierung eines Antriebs – detailliertes Modell&amp;quot; bereits vorgestellt wurde. Im Scicos-Modell ist der Antrieb der Übersichtlichkeit wegen als Superblock ausgeführt. Das Blockschaltbild des Antriebs im Detail ist [http://www.roboternetz.de/wissen/images/7/73/Antrieb_Modell.png hier] zu sehen. Die Daten sind:&lt;br /&gt;
&lt;br /&gt;
R = 16 Ohm; L = 6 mH; m = 0.31 kg; Kf = 6.6 N/A&lt;br /&gt;
&lt;br /&gt;
Als Sensor kommt ein Inkrementalgeber zum Einsatz, allerdings muss der richtungssensibel sein, sonst ist keine Lageregelung möglich. Der Sensor wird in Scicos mit der Rundungsformel (round(u1*500)) simuliert. Das ergibt bei einer Auflösung von 2mm ganzzahlige Schritte, wie es auch die Hardware (Inkrementalgeber mit nachfolgendem Zähler) in Wirklichkeit macht.&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lageregelung.png]]&lt;br /&gt;
&lt;br /&gt;
Nach dem Regler folgt ein Block mit der Verstärkung (5/255), der den PWM-Wert auf die Ansteuerspannung für den Motor umsetzt. Der Bruch 5/255 entspricht der Ansteuerspannung von 5V bei PWM=255. Der PD-Regler kann damit in Scicos exakt so simuliert werden, wie er schlussendlich auch als C-Code umgesetzt wird. Dazu wird der Code des PD-Reglers als Funktion in den Scifunc-Block eingegeben. Der Code ist etwas unterschiedlich zum C-Code des realen Bots, da die Syntax in Scicos doch geringfügig anders ist und die Eingangs- und Ausgangsvariablen nur bestimmte Bezeichnungen haben dürfen. Im nachfolgenden Codefenster sind beide Varianten im Vergleich zu sehen.&lt;br /&gt;
{|&lt;br /&gt;
 | '''Scifunc-Code:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
y1=Kp*u1+Kd/Ta*(u1-z);&lt;br /&gt;
z=u1;&lt;br /&gt;
if y1&amp;gt;255 then&lt;br /&gt;
y1=255;&lt;br /&gt;
end&lt;br /&gt;
if y1&amp;lt;-255 then&lt;br /&gt;
y1=-255;&lt;br /&gt;
end&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''C-Code für µC:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
e = w - x;&lt;br /&gt;
y = Kp*e + Kd/Ta*(e-ealt);&lt;br /&gt;
ealt = e;&lt;br /&gt;
if (y &amp;gt; 255) {&lt;br /&gt;
    y = 255;&lt;br /&gt;
    }&lt;br /&gt;
if (y &amp;lt; -255) {&lt;br /&gt;
    y = -255;&lt;br /&gt;
    }&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 | '''Kommentar:'''&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
Vergleich&lt;br /&gt;
PD-Reglergleichung&lt;br /&gt;
alten Wert speichern&lt;br /&gt;
&lt;br /&gt;
pos. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
neg. Begrenzung&lt;br /&gt;
&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
 |}&lt;br /&gt;
&lt;br /&gt;
In der praktischen Umsetzung des C-Codes wird man den Bruch Kd/Ta durch eine Ersatzvariable oder Konstante ersetzen. Dabei ergibt sich (wie in diesem Beispiel 2/0.01 = 200) meistens ein ganzzahliger Wert, was sich positiv auf die Rechenzeit auswirkt.&lt;br /&gt;
&lt;br /&gt;
Für die Abtastzeit Ta wurde 10ms gewählt. Das ist einerseits nicht zu schnell für einen µC und andererseits nicht zu lang, um die Regelung unnötig zu verlangsamen. Die Parametrierung von Kp und Kd erfolgte empirisch durch Probieren in der Simulation. Begonnen wurde mit einem reinen P-Regler und kleinem P-Anteil (Kp=1, Kd=0). In groben Schritten wurde Kp solange erhöht, bis sich deutlich Überschwinger zeigten. Dann wurde ein D-Anteil hinzugefügt und Kd so variiert, dass der Überschwinger verschwindet. Mit ein bisschen Feintuning ergaben sich so die Werte Kp=61 und Kd=2. Das Simulationsergebnis für Ansteuerspannung, Geschwindigkeit und Weg sieht damit folgendermaßen aus:&lt;br /&gt;
&lt;br /&gt;
[[Bild:Lage_antwort.png]]&lt;br /&gt;
&lt;br /&gt;
==Autoren==&lt;br /&gt;
* [[Benutzer:Waste|Waste]]&lt;br /&gt;
&lt;br /&gt;
==Siehe auch==&lt;br /&gt;
* [[SwitcherCAD-Tutorial]]&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
== External links ==&lt;br /&gt;
*[http://www.roboternetz.de/phpBB2/viewtopic.php?t=11818 Post: Line follower with PID controller]&lt;br /&gt;
*[http://www.scicos.org/ Scicos Homepage]&lt;br /&gt;
* [http://www.scicoslab.org/  ScicosLab Homepage]&lt;br /&gt;
* [http://www.scilab.org/ Scilab Homepage]&lt;br /&gt;
* [http://ltspice.linear.com/software/swcadiii.exe LTspice / SwitcherCAD III Download]&lt;br /&gt;
* [http://www.kahlert.com/web set_download.php demo version of WinFACT 7]&lt;br /&gt;
* [http://www.physi.uni-heidelberg.de/fp/anleitg/E01.pdf instructions for electronic placement, the last part is based PID controller]&lt;br /&gt;
* [http://www.simapp.com/ SimApp website] with trial&lt;br /&gt;
* [http://www.expertcontrol.com/ ExpertControl Homepage, Automatische Reglerauslegung mit ecICP] ecICP-Trial über Support-Seite verfügbar&lt;br /&gt;
* [http://www.me.th-mittelhessen.de/personen/professoren/orlowski/simulation-regelungstechnik/ TH-Mittelhessen Prof. Peter F. Orlowski, Simulationsprogramm SIMLER-PC]&lt;br /&gt;
&lt;br /&gt;
[[Category: Microcontroller]]&lt;br /&gt;
[[Category: Software]]&lt;br /&gt;
[[Category: Elektronik]]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	<entry>
		<id>https://rn-wissen.de/wiki/index.php?title=Datei:Digreg.gif&amp;diff=25234</id>
		<title>Datei:Digreg.gif</title>
		<link rel="alternate" type="text/html" href="https://rn-wissen.de/wiki/index.php?title=Datei:Digreg.gif&amp;diff=25234"/>
				<updated>2014-09-13T07:46:43Z</updated>
		
		<summary type="html">&lt;p&gt;SprinterSB: reimport von [http://www.roboternetz.de/wiki/uploads/Main/digreg.gif]&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;reimport von [http://www.roboternetz.de/wiki/uploads/Main/digreg.gif]&lt;/div&gt;</summary>
		<author><name>SprinterSB</name></author>	</entry>

	</feed>